Superwall

Handling Deep Links

Use handleDeepLink and campaign rules to present paywalls from deep links without hardcoding logic in your app.

When your app receives a deep link, you might be tempted to write a switch statement that maps each URL to a specific placement and calls register. This works, but it means every time you add a new link or change which paywall shows, you have to ship an app update.

A better approach is to pass the URL to handleDeepLink and let Superwall's deepLink_open standard placement handle the rest. The SDK extracts the URL's path, query parameters, and other components, then fires deepLink_open as a placement. You write campaign rules on the dashboard to decide which paywall to show, which means there is no app update required.

The problem

Here's a common pattern where deep link routing is hardcoded in the app:

function handleUrl(url: string) {
  const path = new URL(url).pathname;
  let placement: string | undefined;

  switch (path) {
    case "/promo":
      placement = "promoPlacement";
      break;
    case "/onboarding":
      placement = "onboardingPlacement";
      break;
    case "/upgrade":
      placement = "upgradePlacement";
      break;
    case "/special-offer":
      placement = "specialOfferPlacement";
      break;
  }

  if (placement) {
    superwall.register(placement);
  }
}

Every new URL path means a code change, a build, and an app store review. If you want to change which paywall shows for /promo, that's another update too.

Instead, pass the URL to handleDeepLink. The SDK fires the deepLink_open standard placement with all of the URL's components as parameters. Then, on the Superwall dashboard, you create campaign rules that match on those parameters to decide what to show.

function handleUrl(url: string) {
  SuperwallExpoModule.handleDeepLink(url);
}

That's it on the app side. The routing logic lives on the dashboard.

Setting up campaign rules

Once handleDeepLink is wired up, the deepLink_open placement fires every time a deep link arrives. The URL's path, host, query parameters, and other components are available as parameters you can match against in your campaign's audience filters.

  1. 1

    Create a campaign

    On the Superwall dashboard, create a new campaign — for example, "Deep Link Paywalls".

  2. 2

    Add the deepLink_open placement

    In your campaign, add a placement and select deepLink_open from the standard placements list.

  3. 3

    Add audience filters

    Edit the default audience and add filters that match the URL components you care about. For example, if your deep link is myapp://promo?offer=summer:

    • Set params.path is promo to match the path.
    • Set params.offer is summer to match the query parameter.

    See deepLink_open parameters for the full list of available fields.

  4. 4

    Attach a paywall

    Click Paywalls at the top of the campaign and choose which paywall to present when the filters match.

Now when a user opens myapp://promo?offer=summer, the SDK fires deepLink_open, the campaign rule matches, and the paywall shows. That's all without touching your app code. To add a new deep link path or change which paywall it shows, just update the campaign on the dashboard.

You can handle several deep link patterns from a single campaign by adding multiple audiences, each with its own filters and paywalls. For example:

Deep linkFilterPaywall
myapp://promo?offer=summerparams.path is promo AND params.offer is summerSummer Sale
myapp://promo?offer=newyearparams.path is promo AND params.offer is newyearNew Year Offer
myapp://upgradeparams.path is upgradeUpgrade Paywall

Each audience evaluates independently. When you need to add a new route, create a new audience on the dashboard — no app update needed.

Prerequisites

To use handleDeepLink, your app needs deep link handling set up first. If you haven't done that yet, follow the setup guide:

  • Deep Link Setup — Configure URL schemes, universal links, and wire handleDeepLink into your app so Superwall can respond to incoming links.

How is this guide?

Edit on GitHub