Present Paywall Builder paywalls in Observer mode in iOS SDK
If you’ve customized a paywall using the Paywall Builder, you don’t need to worry about rendering it in your mobile app code to display it to the user. Such a paywall contains both what should be shown within the paywall and how it should be shown.
This section refers to Observer mode only. If you do not work in the Observer mode, refer to the iOS - Present Paywall Builder paywalls.
Before you start presenting flows (Click to Expand)
- Set up initial integration of Adapty with the App Store.
- Install and configure Adapty SDK. Make sure to set the
observerModeparameter totrue. Refer to the iOS SDK installation guide. - Create products in the Adapty Dashboard.
- Configure flows or paywalls in the builders and assign products to them.
- Create placements and assign your flows or paywalls to them.
- Fetch flows and their configuration in your mobile app code.
-
Implement the
AdaptyObserverModeResolverobject. The protocol is the same as in SDK v3 — observer mode itself does not change between flow and paywall rendering:func observerMode(didInitiatePurchase product: AdaptyPaywallProduct, onStartPurchase: @escaping () -> Void, onFinishPurchase: @escaping () -> Void) { // use the product object to handle the purchase // call onStartPurchase / onFinishPurchase to notify AdaptyUI about the purchase progress } func observerModeDidInitiateRestorePurchases(onStartRestore: @escaping () -> Void, onFinishRestore: @escaping () -> Void) { // call onStartRestore / onFinishRestore to notify AdaptyUI about the restore progress } -
Create a flow configuration object, passing your resolver as the
observerModeResolver:parameter:do { let flowConfiguration = try await AdaptyUI.getFlowConfiguration( forFlow: flow, observerModeResolver: <AdaptyObserverModeResolver> ) } catch { // handle the error }Request parameters:
Parameter Presence Description forFlow required An AdaptyFlowobject obtained viaAdapty.getFlow(placementId:). See Get flows and paywalls.observerModeResolver required The AdaptyObserverModeResolveryou implemented above. -
Initialize the flow controller using
AdaptyUI.flowController(with:delegate:):import AdaptyUI let visualFlow = try AdaptyUI.flowController( with: flowConfiguration, delegate: <AdaptyFlowControllerDelegate> )Request parameters:
Parameter Presence Description flowConfiguration required An AdaptyUI.FlowConfigurationobject containing visual details of the flow. See Get flows and paywalls.delegate required An AdaptyFlowControllerDelegateto listen to flow events. See Handle flow & paywall events.Returns:
Object Description AdaptyFlowController An object representing the requested flow screen. -
Present the controller:
present(visualFlow, animated: true)
Don’t forget to associate paywalls to purchase transactions. Otherwise, Adapty will not determine the source paywall of the purchase.
In SwiftUI, fetch the flow configuration with the resolver and pass it to the .flow modifier:
@State var flowPresented = false
@State var flowConfiguration: AdaptyUI.FlowConfiguration?
var body: some View {
Text("Hello, AdaptyUI!")
.flow(
isPresented: $flowPresented,
flowConfiguration: flowConfiguration,
didPerformAction: { action in
switch action {
case .close:
flowPresented = false
default:
break
}
},
didFailPurchase: { product, error in /* handle the error */ },
didFinishRestore: { profile in /* check access level and dismiss */ },
didFailRestore: { error in /* handle the error */ },
didReceiveError: { error in flowPresented = false }
)
.task {
flowConfiguration = try? await AdaptyUI.getFlowConfiguration(
forFlow: flow,
observerModeResolver: <AdaptyObserverModeResolver>
)
}
}The observerModeResolver: parameter on getFlowConfiguration is what makes the rendered flow respect your custom purchase logic — the modifier itself uses the same callbacks as full mode.
Don’t forget to associate paywalls to purchase transactions. Otherwise, Adapty will not determine the source paywall of the purchase.
Before you start presenting paywalls (Click to Expand)
- Set up initial integration of Adapty with the Google Play and with the App Store.
- Install and configure Adapty SDK. Make sure to set the
observerModeparameter totrue. Refer to our framework-specific instructions for iOS. - Create products in the Adapty Dashboard.
- Configure paywalls, assign products to them, and customize them using Paywall Builder in the Adapty Dashboard.
- Create placements and assign your paywalls to them in the Adapty Dashboard.
- Fetch Paywall Builder paywalls and their configuration in your mobile app code.
-
Implement the
AdaptyObserverModeResolverobject:func observerMode(didInitiatePurchase product: AdaptyPaywallProduct, onStartPurchase: @escaping () -> Void, onFinishPurchase: @escaping () -> Void) { // use the product object to handle the purchase // use the onStartPurchase and onFinishPurchase callbacks to notify AdaptyUI about the process of the purchase } func observerModeDidInitiateRestorePurchases(onStartRestore: @escaping () -> Void, onFinishRestore: @escaping () -> Void) { // use the onStartRestore and onFinishRestore callbacks to notify AdaptyUI about the process of the restore }The
observerMode(didInitiatePurchase:onStartPurchase:onFinishPurchase:)event will inform you that the user has initiated a purchase. You can trigger your custom purchase flow in response to this callback.The
observerModeDidInitiateRestorePurchases(onStartRestore:onFinishRestore:)event will inform you that the user has initiated a restore. You can trigger your custom restore flow in response to this callback.Also, remember to invoke the following callbacks to notify AdaptyUI about the process of the purchase or restore. This is necessary for proper paywall behavior, such as showing the loader, among other things:
Callback Description onStartPurchase() The callback should be invoked to notify AdaptyUI that the purchase is started. onFinishPurchase() The callback should be invoked to notify AdaptyUI that the purchase is finished. onStartRestore() The callback should be invoked to notify AdaptyUI that the restore is started. onFinishRestore() The callback should be invoked to notify AdaptyUI that the restore is finished. -
Create a paywall configuration object:
do { let paywallConfiguration = try AdaptyUI.getPaywallConfiguration( forPaywall: <paywall object>, observerModeResolver: <AdaptyObserverModeResolver> ) } catch { // handle the error }Request parameters:
Parameter Presence Description Paywall required An AdaptyPaywallobject to obtain a controller for the desired paywall.ObserverModeResolver required The AdaptyObserverModeResolverobject you’ve implemented in the previous step -
Initialize the visual paywall you want to display by using the
.paywallController(for:products:viewConfiguration:delegate:)method:import AdaptyUI let visualPaywall = AdaptyUI.paywallController( with: <paywall configuration object>, delegate: <AdaptyPaywallControllerDelegate> )
Request parameters:
| Parameter | Presence | Description |
|---|---|---|
| Paywall Configuration | required | An AdaptyUI.PaywallConfiguration object containing visual details of the paywall. Use the AdaptyUI.getPaywallConfiguration(forPaywall:locale:) method. Refer to Fetch Paywall Builder paywalls and their configuration topic for more details. |
| Delegate | required | An AdaptyPaywallControllerDelegate to listen to paywall events. Refer to Handling paywall events topic for more details. |
Returns:
| Object | Description |
|---|---|
| AdaptyPaywallController | An object, representing the requested paywall screen |
After the object has been successfully created, you can display it like so:
present(visualPaywall, animated: true)Don’t forget to Associate paywalls to purchase transactions. Otherwise, Adapty will not determine the source paywall of the purchase.
In order to display the visual paywall on the device screen, use the .paywall modifier in SwiftUI:
@State var paywallPresented = false
var body: some View {
Text("Hello, AdaptyUI!")
.paywall(
isPresented: $paywallPresented,
paywallConfiguration: <paywall configuration object>,
didPerformAction: { action in
switch action {
case .close:
paywallPresented = false
default:
// Handle other actions
break
}
},
didFinishRestore: { profile in /* check access level and dismiss */ },
didFailRestore: { error in /* handle the error */ },
didFailRendering: { error in paywallPresented = false }
)
}Request parameters:
| Parameter | Presence | Description |
|---|---|---|
| Paywall Configuration | required | An AdaptyUI.PaywallConfiguration object containing visual details of the paywall. Use the AdaptyUI.getPaywallConfiguration(forPaywall:locale:) method. Refer to Fetch Paywall Builder paywalls and their configuration topic for more details. |
| Products | optional | Provide an array of AdaptyPaywallProduct objects to optimize the display timing of products on the screen. If nil is passed, AdaptyUI will automatically fetch the necessary products. |
| TagResolver | optional | Define a dictionary of custom tags and their resolved values. Custom tags serve as placeholders in the paywall content, dynamically replaced with specific strings for personalized content within the paywall. Refer to Custom tags in Paywall Builder topic for more details. |
| ObserverModeResolver | optional | The AdaptyObserverModeResolver object you’ve implemented in the previous step |
Closure parameters:
| Closure parameter | Description |
|---|---|
| didFinishRestore | If Adapty.restorePurchases() succeeds, this callback will be invoked. |
| didFailRestore | If Adapty.restorePurchases() fails, this callback will be invoked. |
| didFailRendering | If an error occurs during the interface rendering, this callback will be invoked. |
Refer to the iOS - Handling events topic for other closure parameters.
Don’t forget to Associate paywalls to purchase transactions. Otherwise, Adapty will not determine the source paywall of the purchase.
Before you start presenting paywalls (Click to Expand)
- Set up initial integration of Adapty with the Google Play and with the App Store.
- Install and configure Adapty SDK. Make sure to set the
observerModeparameter totrue. Refer to our framework-specific instructions for iOS, React Native, Flutter, and Unity. - Create products in the Adapty Dashboard.
- Configure paywalls, assign products to them, and customize them using Paywall Builder in the Adapty Dashboard.
- Create placements and assign your paywalls to them in the Adapty Dashboard.
- Fetch Paywall Builder paywalls and their configuration in your mobile app code.
-
Implement the
AdaptyObserverModeDelegateobject:func paywallController(_ controller: AdaptyPaywallController, didInitiatePurchase product: AdaptyPaywallProduct, onStartPurchase: @escaping () -> Void, onFinishPurchase: @escaping () -> Void) { // use the product object to handle the purchase // use the onStartPurchase and onFinishPurchase callbacks to notify AdaptyUI about the process of the purchase }The
paywallController(_:didInitiatePurchase:onStartPurchase:onFinishPurchase:)event will inform you that the user has initiated a purchase. You can trigger your custom purchase flow in response to this event.Also, remember to invoke the following callbacks to notify AdaptyUI about the process of the purchase. This is necessary for proper paywall behavior, such as showing the loader, among other things:
Callback Description onStartPurchase The callback should be invoked to notify AdaptyUI that the purchase is started. onFinishPurchase The callback should be invoked to notify AdaptyUI that the purchase is finished. -
Initialize the visual paywall you want to display by using the
.paywallController(for:products:viewConfiguration:delegate:observerModeDelegate:)method:import AdaptyUI let visualPaywall = AdaptyUI.paywallController( for: <paywall object>, products: <paywall products array>, viewConfiguration: <LocalizedViewConfiguration>, delegate: <AdaptyPaywallControllerDelegate> observerModeDelegate: <AdaptyObserverModeDelegate> )
Request parameters:
| Parameter | Presence | Description |
|---|---|---|
| Paywall | required | An AdaptyPaywall object to obtain a controller for the desired paywall. |
| Products | optional | Provide an array of AdaptyPaywallProduct objects to optimize the display timing of products on the screen. If nil is passed, AdaptyUI will automatically fetch the necessary products. |
| ViewConfiguration | required | An AdaptyUI.LocalizedViewConfiguration object containing visual details of the paywall. Use the AdaptyUI.getViewConfiguration(paywall:locale:) method. Refer to Fetch Paywall Builder paywalls and their configuration topic for more details. |
| Delegate | required | An AdaptyPaywallControllerDelegate to listen to paywall events. Refer to Handling paywall events topic for more details. |
| ObserverModeDelegate | required | The AdaptyObserverModeDelegate object you’ve implemented in the previous step |
| TagResolver | optional | Define a dictionary of custom tags and their resolved values. Custom tags serve as placeholders in the paywall content, dynamically replaced with specific strings for personalized content within the paywall. Refer to Custom tags in Paywall Builder topic for more details. |
Returns:
| Object | Description |
|---|---|
| AdaptyPaywallController | An object, representing the requested paywall screen |
After the object has been successfully created, you can display it like so:
present(visualPaywall, animated: true)Don’t forget to Associate paywalls to purchase transactions. Otherwise, Adapty will not determine the source paywall of the purchase.
In order to display the visual paywall on the device screen, use the .paywall modifier in SwiftUI:
@State var paywallPresented = false
var body: some View {
Text("Hello, AdaptyUI!")
.paywall(
isPresented: $paywallPresented,
paywall: <paywall object>,
configuration: <LocalizedViewConfiguration>,
didPerformAction: { action in
switch action {
case .close:
paywallPresented = false
default:
// Handle other actions
break
}
},
didFinishRestore: { profile in /* check access level and dismiss */ },
didFailRestore: { error in /* handle the error */ },
didFailRendering: { error in paywallPresented = false },
observerModeDidInitiatePurchase: { product, onStartPurchase, onFinishPurchase in
// use the product object to handle the purchase
// use the onStartPurchase and onFinishPurchase callbacks to notify AdaptyUI about the process of the purchase
},
)
}Request parameters:
| Parameter | Presence | Description |
|---|---|---|
| Paywall | required | An AdaptyPaywall object to obtain a controller for the desired paywall. |
| Product | optional | Provide an array of AdaptyPaywallProduct objects to optimize the display timing of products on the screen. If nil is passed, AdaptyUI will automatically fetch the necessary products. |
| Configuration | required | An AdaptyUI.LocalizedViewConfiguration object containing visual details of the paywall. Use the AdaptyUI.getViewConfiguration(paywall:locale:) method. Refer to Fetch Paywall Builder paywalls and their configuration topic for more details. |
| TagResolver | optional | Define a dictionary of custom tags and their resolved values. Custom tags serve as placeholders in the paywall content, dynamically replaced with specific strings for personalized content within the paywall. Refer to Custom tags in paywall builder topic for more details. |
Closure parameters:
| Closure parameter | Description |
|---|---|
| didFinishRestore | If Adapty.restorePurchases() succeeds, this callback will be invoked. |
| didFailRestore | If Adapty.restorePurchases() fails, this callback will be invoked. |
| didFailRendering | If an error occurs during the interface rendering, this callback will be invoked. |
| observerModeDidInitiatePurchase | This callback is invoked when a user initiates a purchase. |
Refer to the iOS - Handling events topic for other closure parameters.
Don’t forget to Associate paywalls to purchase transactions. Otherwise, Adapty will not determine the source paywall of the purchase.