Presenting Flows
Show paywalls and screens to users as overlay WebViews
Presenting Flows
Flows are the published screen bundles you build in the Studio -- paywalls, onboarding sequences, upgrade prompts -- compiled and delivered to the SDK. Present them as overlay WebViews that render above your app's UI and support native actions like purchases, navigation, and custom events.
Terminology note: In the Studio you edit a Project. Publishing creates an immutable Version (
ver_...).
The SDK and profile payload still refer to these published versions as "flows", so theflowIdyou pass toshowFlow()is a version ID.
How flows reach the device
- You design and publish a project in the Nuxie Studio.
- The SDK fetches the flow definition as part of the user's profile payload.
- Flow assets (HTML, CSS, JavaScript, fonts) are cached locally as a WebArchive for fast presentation.
- When a campaign triggers or you call
showFlow(), the SDK loads the cached assets into a WebView overlay.
The SDK prefetches flow assets in the background whenever the profile updates, so flows load instantly even on first presentation.
Manual presentation
Present a flow directly by its ID:
try await NuxieSDK.shared.showFlow(with: "ver_abc123")This opens the flow in a dedicated overlay window above your app's current view hierarchy. The flow renders full-screen and handles its own dismissal through actions configured in the Studio.
You can also get a FlowViewController for custom embedding:
let viewController = try await NuxieSDK.shared.getFlowViewController(with: "ver_abc123")
present(viewController, animated: true)Automatic presentation via campaigns
Campaigns present flows automatically based on triggers you configure in the dashboard:
- Event triggers -- a flow appears when the user fires a specific event via
trigger(). - Segment triggers -- a flow appears when the user enters (or exits) a segment.
When a campaign matches, the SDK presents the flow without any additional code:
// If a campaign targets "checkout_started", this may present a flow
NuxieSDK.shared.trigger("checkout_started")Use the TriggerHandle to observe what happened:
NuxieSDK.shared.trigger("checkout_started") { update in
switch update {
case .decision(.flowShown(let ref)):
print("Flow presented: \(ref)")
case .decision(.suppressed(let reason)):
print("Campaign suppressed: \(reason)")
case .decision(.noMatch):
print("No campaign matched this event")
default:
break
}
}Reentry policies
Campaigns support reentry policies that control how often a flow appears:
The overlay window
Flows display in a dedicated UIWindow layered above your app:
- The window sits at the
.alertwindow level, so it appears above navigation bars, tab bars, and modals. - Only one flow can be presented at a time. Presenting a new flow dismisses the current one.
- After the app returns to the foreground, there is a short grace period (under one second) before flows can appear, preventing abrupt presentations.
Runtime bridge
The flow's web content communicates with your native app through a runtime bridge. This bridge supports:
- Purchase actions -- initiate a StoreKit purchase from a button in the flow.
- Restore actions -- trigger a purchase restore.
- Navigation actions -- move between screens within a multi-screen flow.
- Dismiss actions -- close the flow.
- Open link actions -- open a URL in the system browser.
- Custom delegate actions -- send a message to your app via
NotificationCenter.
Listening for delegate actions
When a flow fires a call_delegate action, the SDK posts a Notification your app can observe:
NotificationCenter.default.addObserver(
forName: .nuxieCallDelegate,
object: nil,
queue: .main
) { notification in
let message = notification.userInfo?["message"] as? String
let payload = notification.userInfo?["payload"] as? [String: Any]
// Handle the delegate call
}Other bridge actions post similar notifications: .nuxiePurchase, .nuxieRestore, .nuxieOpenLink, .nuxieDismiss.
Flow caching
The SDK caches flow assets at multiple layers for fast loading:
- WebArchive cache -- the full flow bundle is stored on disk as a WebArchive file. On presentation, the SDK loads from the local file instead of fetching over the network.
- Font cache -- custom fonts referenced by flows are downloaded and served from a local cache via a custom URL scheme.
- In-memory cache -- enriched flow models (including resolved StoreKit product metadata) are held in memory for the current session.
Cache invalidation happens automatically:
- When the profile delivers updated flow content (detected by content hash), the old cache is removed and the new version is prefetched.
- When the user logs out (
reset()), all flow caches are cleared.
Next steps
- Purchases -- handle purchases initiated from within flows
- Campaigns -- configure triggers, goals, and reentry policies in the dashboard
- Features & Entitlements -- gate features based on what the user has purchased