Getting the customer back into the app after Stripe Checkout.

Why a Stripe Checkout success URL cannot simply open your iOS app, how URL schemes, Universal Links, sign-in, codes and device claims compare, and which to use.

Why the success URL is the hard part

Stripe Checkout ends by sending the customer to your success_url. It is tempting to make that address open the app and be done. It works in a demo and fails in the field, because the customer finishing a web checkout is in one of four places:

  1. In Safari, on the phone where the app is already installed.
  2. In the in-app browser of Instagram, Facebook or TikTok, because they came from an ad.
  3. On a phone that does not have the app yet.
  4. On a laptop.

The first is the only one where “open the app” is straightforward. A method that only handles the first leaves a paying customer in front of an app that does not know them, which is the most expensive support ticket there is.

The five methods

A custom URL scheme. The success page links to yourapp://paid?token=…. In Safari the customer is asked whether to open the app; if it is not installed, Safari reports an invalid address. In-app browsers handle schemes inconsistently and some block them outright. Fast when it works, and always in need of a fallback.

A Universal Link. An https:// link that iOS opens in the app when it is installed. It needs an apple-app-site-association file on your domain and the Associated Domains entitlement in Xcode. It opens the app on a tap, not on a redirect, and a link to the same domain the customer is already on stays in the browser, so the success page needs a button on a different domain from the one it is served from.

Sign in. The customer makes an account during checkout and signs in to the app with it. It works everywhere, including across devices, and it is one more form at the moment the customer thinks they have finished.

A code. The success page and the receipt show a short code; the app has a field for it. It works everywhere and it is manual.

Claim by device. The app opens the funnel itself, with an identifier it generated on the URL. The purchase is recorded against that identifier, and on its next launch the app asks whether it is subscribed. Nothing to type, nothing to declare in Xcode. It covers the customer who started in the app, not the one who arrived from an ad before installing.

Side by side

MethodSafari, installedAd's in-app browserNot installed yetLaptop
URL schemeYes, after a promptUnreliableNoNo
Universal LinkYes, on a tapUnreliableFalls back to the web pageNo
Sign inYesYesYesYes
CodeYesYesYesYes
Claim by deviceYesOnly if the app opened the funnelNoNo

No single row is yes all the way across without asking the customer to do something. The answer is two methods: one automatic for the common case, one manual that always works.

Don't wait for the webhook

Whichever method you use, the app will ask “am I subscribed?” within seconds of the payment. Stripe's checkout.session.completed webhook usually arrives by then, and sometimes does not. Record the subscription when the customer lands on the success page, by retrieving the session Stripe has just completed, and let the webhook write the same record when it comes. Keep whichever read is newer, so a late event never overwrites a live subscription with a stale one.

How Passback does it

Claim by device is the default: the app opens the funnel with ?d=<id>, and PassbackKit asks for the subscription on the next launch. For everyone else there is a six-digit code on the confirmation page and in the receipt email: single use, good for a day, valid only inside your app, and locked after ten wrong guesses. A URL scheme is optional, for an instant return, with a single-use token that expires in five minutes. All three answer with the same document, so the app has one parser. The subscription is written on the return from Checkout, before the webhook, as above.

The checkout itself is Stripe Checkout on your own connected account, and the screens before it are built in the web funnel editor. The calls are in the documentation: the return trip, paid before installing and the instant return.


Updated 24 September 2026. Corrections via contact. Related: web-to-app funnels, explained, web purchases on RevenueCat or Adapty.