Superwall

Post-Checkout Redirecting

Learn how to handle users redirecting back to your app after a web purchase.

After a user completes a web purchase, Superwall needs to redirect them back to your app. You can configure this behavior in two ways:

Post-Purchase Behavior Modes

You can configure how users are redirected after checkout in your Application Settings:

Redeem Mode (Default)

Superwall manages the entire redemption experience:

  • Users are automatically deep linked to your app with a redemption code
  • Fallback to App Store/Play Store if the app isn't installed
  • Redemption emails are sent automatically
  • The SDK handles redemption via delegate methods (detailed below)

This is the recommended mode for most apps.

Redirect Mode

Redirect users to your own custom URL with purchase information:

  • When to use: You want to show a custom success page, perform additional actions before redemption, or have your own deep linking infrastructure
  • What you receive: Purchase data is passed as query parameters to your URL

Query Parameters Included:

  • app_user_id - The user's identifier from your app
  • email - User's email address
  • stripe_subscription_id - The Stripe subscription ID
  • Any custom placement parameters you set

Example:

https://yourapp.com/success?
  app_user_id=user_123&
  email=user@example.com&
  stripe_subscription_id=sub_1234567890&
  campaign_id=summer_sale

You'll need to implement your own logic to handle the redirect and deep link users into your app.


Whether you're showing a checkout page in a browser or using the In-App Browser, the Superwall SDK relies on deep links to redirect back to your app.

Prerequisites

  1. Configuring Stripe Keys and Settings
  2. Deep Links

If you're not using Superwall to handle purchases, then you'll need to follow extra steps to redeem the web purchase in your app.


Handling Redemption (Redeem Mode)

When using Redeem mode (the default), handle the user experience when they're redirected back to your app using SuperwallDelegate methods:

When your app opens via the deep link, we will call the delegate method willRedeemLink() before making a network call to redeem the code. At this point, you might wish to display a loading indicator in your app so the user knows that the purchase is being redeemed.

class SWDelegate : SuperwallDelegate {
  override fun willRedeemLink() {
    // Show a loading indicator to the user
    showToast("Activating your purchase...")
  }
}

You can manually dismiss the paywall at this point if needed, but note that the paywall will be dismissed automatically when the didRedeemLink method is called.

After receiving a response from the network, we will call didRedeemLink(result:) with the result of redeeming the code. This result can be one of the following:

  • RedemptionResult.Success: The redemption succeeded and contains information about the redeemed code.
  • RedemptionResult.Error: An error occurred while redeeming. You can check the error message via the error parameter.
  • RedemptionResult.ExpiredCode: The code expired and contains information about whether a redemption email has been resent and an optional obfuscated email address.
  • RedemptionResult.InvalidCode: The code that was redeemed was invalid.
  • RedemptionResult.ExpiredSubscription: The subscription that the code redeemed has expired.

On network failure, the SDK will retry up to 6 times before returning an Error RedemptionResult in didRedeemLink(result:).

Here, you should remove any loading UI you added in willRedeemLink and show a message to the user based on the result. If a paywall is presented, it will be dismissed automatically.

class SWDelegate : SuperwallDelegate {
  override fun didRedeemLink(result: RedemptionResult) {
    when (result) {
      is RedemptionResult.ExpiredCode -> {
        showToast("Expired Link")
        Log.d("Superwall", "Code expired: ${result.code}, ${result.expiredInfo}")
      }
      is RedemptionResult.Error -> {
        showToast(result.error.message)
        Log.d("Superwall", "Error: ${result.code}, ${result.error}")
      }
      is RedemptionResult.ExpiredSubscription -> {
        showToast("Expired Subscription")
        Log.d("Superwall", "Expired subscription: ${result.code}, ${result.redemptionInfo}")
      }
      is RedemptionResult.InvalidCode -> {
        showToast("Invalid Link")
        Log.d("Superwall", "Invalid code: ${result.code}")
      }
      is RedemptionResult.Success -> {
        val email = result.redemptionInfo.purchaserInfo.email
        if (email != null) {
          Superwall.instance.setUserAttributes(mapOf("email" to email))
          showToast("Welcome, $email!")
        } else {
          showToast("Welcome!")
        }
      }
    }
  }
}

How is this guide?