# 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 [#post-purchase-behavior-modes]

You can configure how users are redirected after checkout in your [Application Settings](/docs/web-checkout/web-checkout-configuring-stripe-keys-and-settings#post-purchase-behavior):

Redeem Mode (Default) [#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-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, or the Stripe Checkout session ID for one-time purchases
* 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.

***

Setting Up Deep Links [#setting-up-deep-links]

Whether checkout starts from a web link or from a paywall that opens an external browser, the Superwall SDK relies on deep links to redirect back to your app.

Prerequisites [#prerequisites]

1. [Configuring Stripe Keys and Settings](/docs/web-checkout/web-checkout-configuring-stripe-keys-and-settings)
2. [Deep Links](/docs/android/quickstart/in-app-paywall-previews)

> **Warning**

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.



* [Using RevenueCat](/docs/android/guides/web-checkout/using-revenuecat)
* [Using a PurchaseController](/docs/android/guides/web-checkout/linking-membership-to-iOS-app#using-a-purchasecontroller)

***

Handling Redemption (Redeem Mode) [#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:

willRedeemLink [#willredeemlink]

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.

```kotlin
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.

didRedeemLink [#didredeemlink]

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.

```kotlin
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
        val productIdentifier = result.redemptionInfo.paywallInfo?.productIdentifier
        
        if (email != null) {
          Superwall.instance.setUserAttributes(mapOf("email" to email))
          showToast("Welcome, $email!")
        } else {
          showToast("Welcome!")
        }
        
        // Access the product identifier if available (2.6.3+)
        productIdentifier?.let {
          Log.d("Superwall", "Redeemed product: $it")
        }
      }
    }
  }
}
```