Tap Behaviors
Tap behaviors define what happens when a user interacts with an actionable component (buttons, links, toggles). They are specified via the action prop on cta_button and link_row components.
Available Actions
| Action | Description |
|---|---|
purchase | Initiate purchase of the specified or selected product |
select_product | Set the selected product (used in product pickers) |
restore | Restore previous purchases |
close | Dismiss the paywall |
open_url | Open a URL in the system browser |
custom_action | Fire a custom action handled by the app delegate |
custom_placement | Register another placement (chain paywalls) |
navigate_page | Navigate to the next page in a multi-page flow |
request_review | Trigger the App Store / Play Store review prompt |
purchase
Initiates a purchase flow for a product.
Required props: product (slot name or "selected")
{
"type": "cta_button",
"id": "buy",
"props": {
"text": "Subscribe Now",
"action": "purchase",
"product": "selected"
}
}The product value can be:
"selected"-- Purchase whichever product the user has selected via the product picker"primary","secondary","tertiary"-- Purchase a specific product slot
On iOS, this triggers a StoreKit 2 purchase. On Android, this triggers Google Play Billing.
select_product
Sets the currently selected product. Used internally by product_picker but can also be used on custom buttons.
{
"type": "cta_button",
"id": "pick_annual",
"props": {
"text": "Annual Plan",
"action": "select_product",
"product": "primary"
}
}restore
Triggers a purchase restoration flow. On iOS, this calls AppStore.sync(). On Android, this queries Play Billing for existing purchases.
{
"text": "Restore Purchases",
"action": "restore"
}The SDK tracks restore_started and restore_complete events and calls the delegate's didRestorePurchases() method on success.
close
Dismisses the paywall. The SDK tracks a paywall_close event.
{
"text": "Not Now",
"action": "close"
}open_url
Opens a URL in the system browser (Safari on iOS, Chrome on Android).
Required props: url
{
"text": "Terms of Service",
"action": "open_url",
"url": "https://example.com/terms"
}custom_action
Fires a named action that the app handles via the delegate. This is an escape hatch for app-specific behavior that the paywall schema cannot express.
Required props: action_name
{
"type": "cta_button",
"id": "watch_video",
"props": {
"text": "Watch Demo Video",
"action": "custom_action",
"action_name": "play_demo_video"
}
}The delegate receives this via:
- iOS:
handleCustomAction(name: "play_demo_video") - Android:
onCustomAction("play_demo_video")
custom_placement
Registers another placement, allowing paywalls to chain. For example, a paywall could have a button that triggers a different paywall flow.
Required props: placement_name
{
"type": "cta_button",
"id": "see_plans",
"props": {
"text": "See All Plans",
"action": "custom_placement",
"placement_name": "full_pricing"
}
}navigate_page
Navigates to the next page in a slides component. Used for multi-step onboarding or wizard-style paywalls.
{
"type": "cta_button",
"id": "next",
"props": {
"text": "Next",
"action": "navigate_page"
}
}request_review
Triggers the native app review prompt (SKStoreReviewController on iOS, ReviewManager on Android). Typically used after a positive user interaction.
{
"type": "cta_button",
"id": "rate",
"props": {
"text": "Rate Us",
"action": "request_review"
}
}Note: The system may throttle review prompts. The SDK calls the system API but cannot guarantee the prompt will appear.