For the complete documentation index, see llms.txt. This page is also available as Markdown.

Paywall versioning

Swap paywall variants, target them to specific cohorts, and roll back the same day — no App Store or Play Store submission.

Use this when you want to test seasonal pricing, headline copy, or a new paywall layout without blocking on a release train. Don't use this when the variant needs new native UI that is not already shipped in the build; remote config cannot introduce new screens, only pick between ones that exist.

Goal

Paywall changes that live in app code are expensive to iterate on: two weeks of review, a rollback means another submission, and you cannot target a variant to a specific cohort. This recipe ships the paywall as a remote-selectable deeplink so the dashboard decides which variant a given user sees and when.

Setup

In the dashboard

  • Create one campaign per variant: paywall-control, paywall-winter-offer, paywall-long-copy.

  • Trigger: session start, or on a custom event like PaywallRequested fired from a feature gate.

  • Target audience: the free cohort (subscription_status != "pro").

  • Split variants by audience filter rather than a percentage split — for example, send paywall-winter-offer to users with country in ["US","CA"], paywall-long-copy to users with install_date after a given date, and leave paywall-control as the broadest-audience fallback that catches every free user not matched by a narrower variant.

  • Action: fire the deeplink for that variant (yourapp://paywall/control, yourapp://paywall/winter, yourapp://paywall/long-copy).

  • To retire a seasonal variant, move its campaign state to Cancel on the planned end date. The change propagates on the next session. Use Draft state to stage a variant that is not yet live.

In the app (engineering hand-off)

  • Ship every variant screen in the build before you promote the campaign. Remote config selects between them; it cannot create them.

  • Register a deeplink handler for yourapp://paywall/<variant> that resolves <variant> to the matching view controller.

  • Track the outcome so variants are comparable:

    await Amply.track({ name: 'PaywallViewed', properties: { variant: 'winter' }});
    await Amply.track({ name: 'PurchaseCompleted', properties: { variant: 'winter', product: sku }});

How it runs

  1. User opens the app. Session starts.

  2. Amply evaluates the paywall campaigns. The user's country is "US", so the narrower paywall-winter-offer audience matches; the broader paywall-control audience would also match but is only selected when no narrower variant does.

  3. Amply fires yourapp://paywall/winter. The app presents the winter variant.

  4. App tracks PaywallViewed with variant: "winter". If the user converts, PurchaseCompleted carries the same variant tag.

  5. The growth team compares conversion across variant values in their analytics tool.

  6. When the winter window closes, the operator moves that campaign to Cancel. Amply stops firing it. Users fall back to the control variant.

Metrics to watch

  • View-to-purchase rate per variant. This is the headline number.

  • Average revenue per paying user per variant — protects against a variant that converts more people into a worse plan.

  • Trial-start rate per variant, if the product has a trial.

  • Refund and cancel rate per variant over the following 30 days. A variant that converts well but refunds high is a net loss.

Last updated