Overview
Encore presents a premium brand offer (a real perk a brand funds to acquire customers, such as a free trial, discount, or credit) at a moment you choose. Start with Reward Users: a reward sheet at a moment the user just earned, such as a completed purchase, a streak, or a milestone, at no cost to you. The other use case, Reduce Churn, presents offers in a cancel flow or after a paywall decline.Present Offers
The facade is@MainActor, so call show() from a main-actor context: a SwiftUI button action, a .task, or a UIKit handler. show() never throws and always resolves; a SwiftUI Button action is synchronous, so wrap the await in a Task:
- Reward Users
- Reduce Churn
.useCase(.rewardUsers) on every reward placement. A reward placement never runs a purchase and never falls back to the paywall sheet, so it needs no subscription product and no purchase controller. The walkthrough, including per-call copy, is the Reward Placements guide.placement() · PresentationResult.
Callback form
When the call site can’t await,show(resume:) delivers every outcome (including .notPresented) on the main actor:
show() never throws. Failures arrive as .notPresented(.error(EncoreError)) on the PresentationResult, so there is no catch block to forget.Handle Purchases
This section applies to Reduce Churn placements only. A reward placement never runs a purchase, so an app that presents only reward placements can skip it. When a user accepts an offer that requires a purchase, the SDK calls theEncorePurchaseController you registered at configure time. It performs the purchase through your billing code (StoreKit 2, RevenueCat, Adapty, or your own) and reports what happened:
If your app uses Encore offers without a subscription product, no controller is needed and no purchase is ever attempted. If a product is configured but no controller is registered, the SDK never attempts a purchase: the claim completes with
publisher: .notAttempted and the sdk_iap_no_purchase_controller analytics event flags the misconfiguration.Observe Outcomes Passively
Anything that wants to watch results without owning a call site (analytics forwarding, a debug overlay, cross-screen state) consumes theoutcomes stream:
What a Grant Looks Like
The result ofshow() records the raw facts of the flow; read the granted entitlement itself from isActive / isActivePublisher, the authoritative state. See Two-phase entitlements in EntitlementScope for how provisional and verified grants differ and which scope to gate on.
Next Steps
- Reward Placements - Reward a user at a moment they just earned, with copy you set per call
- Configure Analytics - Track offer performance and measure impact
- Add Subscription Product - Reduce Churn only: pick the App Store subscription Encore purchases when a user accepts an offer