Shopify App Billing: Mastering Custom UI and 'Cancel' Button Redirects

Hey everyone, it's your friendly Shopify migration expert here, diving into another fantastic discussion from the Shopify community forums. We recently saw a really insightful thread kicked off by a developer named bshah, who was grappling with a common challenge for app developers: how to maintain a custom pricing plan selection UI while using Shopify's recommended App Pricing, especially when it comes to controlling the 'Cancel' button redirect on the Plan Approval page.

bshah's goal was clear: guide users through their own beautifully designed custom pricing page, then hand them off to Shopify's hosted Plan Approval page for the final subscription confirmation. The hiccup? If a user decided to hit 'Cancel' on that Shopify-hosted page, they were being sent to Shopify's own hosted plan selection page, creating a jarring, inconsistent experience. Understandably, bshah wanted that 'Cancel' button to gracefully lead users back to their custom plan selection UI.

The 'Cancel' Button Conundrum: Why Direct Redirects Aren't an Option

Now, this is where the community really stepped up with some clear, consistent advice. The short answer, as confirmed by experts like ahsandoesntcare, VikashJ, dropfeed, and alaattincagil, is that there's simply no supported way to directly configure or override the 'Cancel' button's destination on Shopify's hosted Plan Approval page. It's hardcoded.

When you're using Shopify App Pricing (which used to be called Managed Pricing), Shopify essentially takes ownership of that entire approval flow, including where a 'Cancel' action leads. As dropfeed pointed out, with Shopify App Pricing, you're not calling appSubscriptionCreate yourself; Shopify handles the subscription creation when the merchant approves a plan. This means there's no returnUrl or cancel parameter for you to set in that specific flow. The only redirect you get to control is the 'welcome link' which fires after a successful approval, not on cancellation.

The community echoed that this isn't something developers are 'missing'; it's genuinely not exposed. An older forum thread with a similar complaint went unanswered, indicating this behavior has been consistent for a while.

The Smart Solution: Handling 'Cancel' with a State Check

So, if you can't directly control the redirect, what's the solution? This is where the community's collective wisdom shines, offering a robust and elegant workaround: handle the 'cancel' as a state check within your app.

Implementing the 'Subscription Status Check' Workaround

Instead of fighting the redirect, you build your app to intelligently react to the user's subscription status. Here's how the experts recommend you approach it:

  1. Own Your App's Landing Route: When a merchant opens your embedded app, it lands on a default route. Make this route smart.
  2. Check Subscription Status on Load: On this landing route, immediately perform a check to see if the merchant has an active subscription to your app. You can do this using the appSubscription / active subscription query in GraphQL, or if you're using the older Billing API, with billing.check().
  3. Conditional UI Rendering:
    • If an active subscription IS found: Proceed with your app's main functionality.
    • If NO active subscription IS found: This is your trigger! Regardless of whether they just clicked 'Cancel' on Shopify's page, or if they cancelled their subscription later from their Shopify admin, your app should now render your custom pricing/plan selection UI.

As alaattincagil and VikashJ highlighted, this approach is incredibly robust because it covers all scenarios where a merchant might not have an active subscription, not just the 'Cancel' button on the approval page. They might cancel from their own billing settings, completely outside your app's flow, and your app still needs to gracefully handle that 'no subscription' state. This makes your app's billing flow much more resilient and user-friendly.

App Pricing vs. Billing API: Choosing Your Path for UI Control

bshah initially wanted to stick with Shopify App Pricing, viewing the Billing API as a legacy approach. However, the discussion clarified that if maintaining full control over your custom plan selection UI is paramount, the Billing API might actually be the better fit, despite being older.

  • Shopify App Pricing (Managed Pricing): This is Shopify's preferred, more hands-off approach. It's designed for Shopify to manage the entire plan selection and approval process, often hosting the plan selection screen itself. If you use this, your custom pricing page essentially acts as a pre-selection step before the merchant is directed to Shopify's hosted plan picker. You lose control over the 'Cancel' redirect.
  • Billing API (Manual Pricing): If your goal is to only hand off the final approval step to Shopify while keeping your custom plan selection UI, then the Billing API with AppSubscriptionCreate is the way to go. With this, you get to specify a returnUrl that fires after approval, and your app's state check handles the 'cancel' scenario.

A Critical Check: VikashJ and dropfeed both raised a vital point: before committing to the Billing API, double-check your app's configuration in the Partner Dashboard. Newer public apps might default to Shopify App Pricing, and switching to Manual/Billing API pricing later could require re-approval from Shopify's app review team. This isn't a small detail, so confirm your options early!

So, while a direct custom redirect for the 'Cancel' button on Shopify's Plan Approval page isn't an option, the community has provided a clear and effective path forward. By implementing a smart subscription status check within your app's landing route, you can ensure a consistent and user-friendly experience, regardless of whether a merchant approves, cancels, or manages their subscription outside your immediate flow. It's all about building a resilient app that understands its own state. This kind of collaborative problem-solving is what makes the Shopify developer community so valuable!

Share:

Use cases

Explore use cases

Agencies, store owners, enterprise — find the migration path that fits.

Explore use cases