Feature Gating
Gate premium features behind product purchases
Use features and entitlements to control access to premium capabilities. Check entitlements from the SDK, show an upgrade paywall when users lack access, and handle metered usage for consumption-based features.
Prerequisites:
- A Nuxie account with an app and at least one product configured
- The iOS SDK installed and configured (see Quickstart)
- Native StoreKit, or an optional provider/custom delegate (see Purchases)
Step 1: Define a feature
Navigate to Features in your app’s dashboard. Click Create Feature and configure:
- Name – “Premium Export”
- External ID –
premium_export - Type – Boolean
Boolean features are simple on/off access checks. The user either has the feature or does not. No additional configuration is needed.
Step 2: Add an entitlement to a product
Open your product (e.g., “Pro Monthly”) and go to the Entitlements tab. Click Add Entitlement and select the premium_export feature.
For boolean features, the entitlement is straightforward: owning the product grants access. The interval is automatically set to lifetime.
Now any user who purchases the Pro Monthly product receives the premium_export entitlement.
Step 3: Check the feature in your app
Use hasFeature() to check access at runtime:
// nuxie-doc-fragment: gate-feature-in-task harness=sync-body
Task {
let access = try await NuxieSDK.shared.hasFeature("premium_export")
if access.allowed {
performExport()
} else {
showUpgradePrompt()
}
}
The default cache-first policy serves fresh authenticated profile state and asks the server when the cache is absent or stale.
Step 4: Show an upgrade paywall when not entitled
When the feature check returns allowed: false, trigger a paywall. There are two approaches:
Approach A: Trigger an experience
Fire a named event that your experience is configured to respond to:
// nuxie-doc-snippet: trigger-upgrade-prompt
import Nuxie
func showUpgradePrompt() {
NuxieSDK.shared.trigger("feature_locked")
}
In the dashboard, create an experience with an event trigger for feature_locked and a re-entry policy of Every time. This way, tapping the locked feature always presents the paywall.
Dismissing a presented Experience
The engine owns presentation: an Experience appears because a trigger matched a
campaign, and the journey decides when it ends. When the app itself needs to end
a presentation (a deep link arriving, a sign-out), call dismiss():
// nuxie-doc-snippet: dismiss-upgrade-prompt
import Nuxie
@MainActor
func closeAnyPresentedExperience() {
Task {
await NuxieSDK.shared.dismiss()
}
}
dismiss() is a no-op when nothing is presented. It waits for an in-flight
purchase or restore rather than interrupting StoreKit, then exits the journey as
dismissed.
Step 5: Handle the purchase and verify access
After the user purchases from the paywall, the SDK syncs the transaction with the server. The entitlement updates immediately, and the feature check returns allowed: true:
// nuxie-doc-fragment: recheck-access-after-purchase harness=async-body
// After purchase completes, re-check
let access = try await NuxieSDK.shared.hasFeature("premium_export")
// access.allowed is now true
For SwiftUI apps, observe the reactive feature map to update your UI automatically:
// nuxie-doc-snippet: reactive-export-button
import Nuxie
import SwiftUI
struct ExportButton: View {
@ObservedObject var features = NuxieSDK.shared.features
var body: some View {
Button("Export") {
if features.isAllowed("premium_export") {
performExport()
} else {
showUpgradePrompt()
}
}
}
}
FeatureInfo is an ObservableObject that updates whenever feature access changes – after purchases, profile refreshes, or real-time entitlement checks.
Metered features: track and limit usage
For consumption-based features like API calls or credits, use metered features instead of boolean features.
Create a metered feature
In the dashboard, click Create Feature with:
- Name – “API Calls”
- External ID –
api_calls - Type – Metered (single use)
- Event name (optional) – the event that triggers automatic usage tracking
Add a metered entitlement
On your product’s Entitlements tab, add the api_calls feature with:
- Allowance type – Fixed
- Allowance – 1000
- Reset interval – Month
- Carry from previous – No
This grants 1,000 API calls per month. The balance resets at the start of each billing period.
Check balance for presentation
// nuxie-doc-fragment: metered-api-call-access harness=async-body
let access = try await NuxieSDK.shared.hasFeature(
"api_calls",
requiredBalance: 1
)
if access.allowed {
// Show the enabled state. Authoritative consumption still happens below.
showEnabledApiCallButton()
} else {
// Balance exhausted -- show upgrade prompt
showUpgradePrompt()
}
Reserve usage before the side effect
For a fixed allowance or credit-backed operation, wait for the server to accept the deduction before performing the protected side effect:
// nuxie-doc-fragment: consume-metered-api-call harness=async-body
do {
let result = try await NuxieSDK.shared.useFeatureAndWait("api_calls", amount: 1)
guard result.success else {
showUpgradePrompt()
return
}
performApiCall()
} catch {
// Includes an exhausted balance or unavailable authoritative service.
showUpgradePrompt()
}
The cached check keeps the interface responsive, but it is not authority to spend a
newly purchased or otherwise unconfirmed fixed balance. Immediately after a native
App Store purchase, useFeatureAndWait() automatically attaches the matching protected
transaction evidence. Nuxie verifies the purchase, grants the allowance, and consumes
this use as one idempotent server operation. The result’s authoritativeAccess contains
the resulting access and balance.
useFeature() remains useful
for telemetry or optimistic counters whose side effect does not depend on that balance;
do not use it to authorize quota- or credit-backed work.
Next steps
- Features & Entitlements – Deep dive into boolean, metered, and credit system features
- Features & Entitlements (SDK) – Full SDK API reference for entitlement checks
- Presenting Experiences – Control how upgrade paywalls are displayed
- Your First Paywall – End-to-end paywall setup if you have not done it yet