Skip to main content
A user opens your paywall, hesitates, and leaves without subscribing. Instead of losing them, present a partner-funded offer that unlocks a better-than-standard deal on your product: they claim the partner offer, purchase your exclusive offer with an extended free trial, and are then sent to the partner. This is the canonical two-phase deferred flow: the claim and the redirect are decoupled so your own checkout sits in between. For the surface right after a successful purchase, see Post-Purchase Placements instead.

The complete pattern

An example fitness app, FitTracker, whose exclusive offer is an extended 1-month free trial (vs the standard 7 days), unlocked by claiming the partner offer:
import Encore from '@encorekit/web-sdk';

Encore.configure({ apiKey: 'pk_live_yourpublishablekey' }); // deferred is the default mode
Encore.identify(userId); // bind the claim to an id that survives reloads

// 1. The user dismisses your paywall without subscribing
async function onPaywallAbandoned() {
  const result = await Encore.placement('paywall_abandon', {
    appearance: { accentColor: '#2E6BFF' },
    // display: { appDisplayName: 'FitTracker', trialPeriod: '1 month' },
    // ^ only if you don't manage the app name / entitlement / icon in the portal
  }).show();

  if (result.status !== 'claimed') {
    return; // 'dismissed' | 'unavailable': continue your normal exit path
  }

  // 2. Claim recorded, no redirect. The SDK's primer screen has handed the
  //     user off. Now sell YOUR OWN exclusive offer: the extended free trial.
  openTrialCheckout(); // your checkout: "1 month free (usually 7 days), then $9.99/mo"
}

// 3. After the user purchases your exclusive offer, from a click/flow handler:
async function onTrialCheckoutComplete() {
  const outcome = await Encore.placement('paywall_abandon').redeem();
  // outcome.status === 'redeemed': the redemption screen showed the user's
  // new plan and sent them to the partner on the CTA tap.
}
Full contracts: show() · redeem() · placement().

Wire up analytics

The flow above drives trials, but Encore can only credit them to the offer if your subscription events join back to the exposures it recorded. Identify the user with your stable customer id (as in the setup above) and forward your subscription events to Encore with that same id. Attribute Subscriptions to Offers is the how-to, including the simple path if RevenueCat already manages your subscriptions.

Gotchas

  • Identify before show(). Call Encore.identify() with your stable customer id before presenting the offer; that id is what links later subscription events to the offer cohort. See Attribute Subscriptions to Offers.
  • The claim is a fact. show() resolves claimed whether the user tapped the primer’s CTA or dismissed it; dismissing the primer does not un-claim. Branch on the result, never on how the primer closed.
  • The display values must resolve. The deferred sheet and primer render your app name, trial length, and logo; if they resolve from neither the portal nor display.*, show() resolves dismissed with a CONFIGURATION_ERROR (or NETWORK_ERROR when the config was unreachable) before any UI. See when resolution fails.
  • Call redeem() from a user gesture. The partner tab opens synchronously on the CTA tap; trigger redeem() from a click/flow handler, not a timer or background promise, or popup blockers may swallow it.
  • The claim survives reloads. It is stored locally with a ~7-day TTL; even if your checkout navigates or reloads, redeem() on a fresh page still resolves it (and resolves { status: 'none' } if nothing is pending).
  • claimed ≠ conversion. Partner conversion is asynchronous and server-authoritative; never gate access on the client result.