Skip to main content
Presenting an offer is one call. When the user taps Claim, the use case decides when the advertiser opens: A 'rewardUsers' claim goes straight through, because the user already did the thing you reward. A 'reduceChurn' claim waits so the user can finish your own step first, such as starting a trial or completing a cancel, before Encore sends them to the advertiser. On 'reduceChurn', optimistic mode’s provisional grant lands at redeem(), not at the claim.

Redeem a saved 'reduceChurn' claim

redeem() can also run on a later page, and getPendingTransaction() returns the saved claim without showing anything. How long it lasts and where it is stored: redeem() gotchas.
Requires the current @encorekit/web-sdk 2.x release. Upgrading an existing integration: Updating to 2.x.

What a claimed result carries

The payload mirrors the iOS and Android ClaimedOffer field for field, so a cross-platform integration reads one shape everywhere.
transactionId is optional, and that is deliberate. The transaction write can fail while the claim itself genuinely happened. When that occurs the SDK logs a warning naming the attribution consequence rather than fabricating a placeholder id, and the result still resolves claimed: a failed write must never retroactively turn a real claim into a decline. Persist transactionId when it is present, and treat its absence as a claim you cannot later join on, not as a failure.

Use cases

The useCase option names the use case, which decides the sheet, and it defaults to 'reduceChurn'. The sheet is the served variant for that use case, or the SDK’s built-in sheet for it; see Sheet Variants. A use case with nothing to present is not an error. show() resolves { status: 'unavailable' }, the same result no eligible offers produce, and it never falls back to another use case’s offers or copy.
These symbols match the native SDKs verbatim (iOS .reduceChurn / .rewardUsers, Android REDUCE_CHURN / REWARD_USERS), so a cross-platform integration reads one vocabulary. The values Encore sends and stores are separate frozen labels, which is what keeps a rename from ever changing the wire. You never type a wire value: passing one is rejected as an unrecognized use case.

Where the sheet’s copy comes from

headline and subheadline on the placement options set the copy for one presentation, ahead of the copy Encore resolved for your app. The full resolution order, and how blank values behave, are on Where the copy comes from.

Identify before you present

Call identify() with your stable user id before presenting, so the claim binds to an account id that survives reloads, navigations, and device switches. Exposures recorded before identify() are keyed to the auto-generated anonymous id and are not retro-linked, so a late identify leaves them unattributed. See Configure Analytics.

A claim is not a conversion

claimed reports a presentation fact: the user tapped Claim. Nothing has been earned or verified at that moment. Advertiser completion happens later, is asynchronous, and is server-authoritative. Verify real access from your backend through Encore’s HMAC-authenticated server-side entitlements API, by user, never from this result and never from the client.

Gotchas

  • Your confirmation is yours to render. Apart from the primer, the redemption screen, and a served variant’s post-claim screen, the SDK shows nothing after a claim. Render your own moment when the result is claimed.
  • A post-claim screen keeps the sheet up. claimed arrives when the user closes it, and a second show() before then resolves dismissed with the reason 'alreadyPresenting'.
  • unavailable is overloaded on purpose. It means no eligible offers, a measurement control cohort, or nothing to present for the requested use case, and the SDK keeps them indistinguishable so incrementality experiments aren’t contaminated. Show your normal fallback; don’t branch on a suspected control assignment.
  • You don’t need a click handler for show() or redeem(). Every advertiser tab opens inside a tap on a button in the SDK’s own sheet (Claim, or the redemption screen’s button). Present offers and call redeem() from whatever moment makes sense in your app.
  • reset() drops a saved claim. It clears local SDK state, including a claim waiting for redeem(), and generates a fresh anonymous id. It revokes nothing: claims already recorded belong to the user id they were made under.