I’m getting my app reviewed for ‘Built for Shopify’ and have run into a strange issue.
We’re using managed pricing on this app and shopify automatically creates test charges for dev stores, we also have detection within the app which looks at if the shopify plan is development or not, so once the merchant has moved to a paid plan, they will need to re-activate their subscription.
We use partnerDevelopment in the following graphql query to check the plan type
shop { plan { displayName partnerDevelopment } }
The store Shopify used to audit the app appears to be on a ‘custom’ plan, which generates test charges, but partnerDevelopment is not true.
In such cases, how can we tell if a store is actually on a paid plan or not?
Hey @Min_Liu, the store used for your BFS review isn’t a partner development store, which is why partnerDevelopment is false. Shopify staff also have access to install apps on their internal stores for testing and merchant support, so you’ll likely see this pattern beyond just BFS reviews.
The recommended way to handle this is the free testing setup described here:
We recommend subscribing to the SHOP_UPDATE webhook to get notified if the development store changes to a paid plan. If you receive this webhook, then block access to your app and create an app charge for the paid plan. After the user agrees to the charge, unblock their access to the app.
For the staff stores, you can also check the test field on the active subscription. With managed pricing, test is true.
Shop_update triggers when other stores data is updated too right? if a merchant is already subscribed and updates some store information it is unfair for them to have the app blocked (and because the app runs behind the scenes, they will likely not notice this until their customers complains) which is a very poor user experience.
In the past we have looked at the plan names however I believe the direction from shopify was to avoid that and use the partnerDevelopment parameter, as plan names change, and or are localized, its inconsistent and wasn’t very reliable.
is there a more robust way for us to detect this?
can there be a field introduced that tells us for certain if the shopify plan will produce test app charges or not then at least this way we know if the customer should have a test charge or not.
Hey @Min_Liu, thanks for the feedback on this. I’ve filed it as a feature request for a field that tells you whether a store will produce test charges. That’s a fair ask.
To your concern about SHOP_UPDATE, the scenario where a merchant gets blocked after updating store info on an already-active subscription isn’t how this works in practice. The billing block should only apply during the development store handoff, when a partner transfers a dev store to a merchant who selects a paid plan. The new store owner accepts any charges as part of that process, and the partner building for them is responsible for advising their client about those charges upfront. At this point, the store will no longer be a development store and not eligible for a test charge.
So are you saying the shop_update payload will be different depending on what has triggered the update and we shouldn’t receive any information about billing in the webhook unless it is a plan change?
Even so, with the current state, if we did create test charges, there would be no way of syncing this state as we can’t tell if the plan the merchant is on is supposed to produce rest charges or not, i was thinking, perhaps in the meantime, for customers on partnerDevelopment (as these are the only ones that can become paid plans right?) we simply don’t create an app charge, and to sync, we check if the store has a lack of a appSubscription and partnerDevelopment = false then force them to accept a plan. For staff plans, because they didn’t have partnerDevelopment = true, we assume they will always be creating test charges, so they pick a plan from the start and stay on that plan as they will never become a paid plan, is this a fair assumption?
Hey @Min_Liu, the SHOP_UPDATE payload does include plan_name and plan_display_name regardless of what triggered it, so you can check that against their current app subscription to confirm if it changed from development or not.
If plan_display_name is "Development", the store gets test charges. If it’s anything else, require them to pick a paid plan. For stores like internal Shopify test stores, managed pricing handles the test charge override automatically so that’s not logic you would really need to account for.