Feature gating
Run code only when a user is entitled to it.
Beta
The Web SDK is in beta and its API may change between releases.
The feature callback
Wrap the code you are gating in feature and the SDK decides whether it runs.
await sw.register({
placement: "export_report",
feature: () => downloadReport(),
});The callback runs when:
- The user is already entitled, so no paywall is shown.
- The user purchased or restored on the paywall.
- The paywall was non-gated and the user dismissed it without buying.
- The placement was skipped: not found, no audience match, or holdout.
It does not run when a gated paywall is dismissed without a purchase.
A skipped placement still runs your feature. If the placement name does not exist in any campaign, or the user matches no audience rule, the SDK runs feature and returns { type: "skipped" }. A typo in a placement name grants the feature. This matches the iOS and Android SDKs. To check whether someone has paid, read entitlements and enforce on your server.
Gated versus non-gated is set on the paywall in the dashboard, not passed from code.
Branching yourself
To decide in your own code, read the result instead.
const result = await sw.register({ placement: "export_report" });
switch (result.type) {
case "presented":
if (result.result.type === "purchased") unlock();
break;
case "skipped":
console.log("no paywall shown:", result.reason);
break;
case "error":
console.error(result.error);
break;
}Checking entitlements directly
To read entitlement state without triggering a placement, use the entitlements namespace.
sw.entitlements.active.value; // Entitlement[]
sw.entitlements.inactive.value;
sw.entitlements.all.value;
sw.entitlements.byProductIds(["pro_monthly"]);These are reactive. Subscribe to re-render when they change:
const unsubscribe = sw.entitlements.active.subscribe((active) => {
render({ isPro: active.some((e) => e.id === "pro") });
});Enforcement
These checks control UI only. Local subscription state can be edited from DevTools. Enforce access to paid resources on your server with @superwall/server or @superwall/verify.
Next, track subscription state.
How is this guide?