Before you startPaywalls build on the standard FlowPilot setup, plus RevenueCat:
- A FlowPilot workspace, an app inside it, and an SDK API key for that app.
- A RevenueCat account with your products, entitlements, and an offering configured for your app.
- Paywalls enabled for your workspace. If you do not see a Paywalls item in the dashboard sidebar, reach out and we will turn it on.
Create a paywall
1
Start a new paywall
Open the Paywalls section in the sidebar and choose New paywall. This creates a flow of type paywall, seeded with a starter layout and its monetization settings already turned on.
2
Set the offering
In the flow settings, under Monetization, pick which RevenueCat offering this paywall shows. The default is your current offering, so changing your featured offering in RevenueCat updates the paywall without a republish. You can also pin a specific offering by identifier.
Monetization settings
The paywall inspector holds the settings that make a flow behave like a paywall. You reach it from the flow settings panel.Add Offers blocks
Paywall-specific building blocks live in the editor’s Offers category. They are compositions of standard components, so they render on every SDK with no extra work, but they carry the purchase wiring for you.Plan picker
A group of selectable plan cards that behaves like a single-select question. Add or remove plans, bind each to a package, set the order, and mark a best-value badge.
Plan option
A single selectable plan card: name, price, period, a trial line that shows only when the user is eligible, and a savings badge slot. Tapping it selects that package.
Purchase CTA
The primary button. It runs the purchase, shows a busy state while it is in flight, and closes the flow on success by default.
Restore
A text button that restores a previous purchase. App Review requires one somewhere in the flow.
Bind plans to packages
Each plan card points at one package from your synced catalog. Select a plan card, open its controller, and pick the package. When you rebind a plan, FlowPilot rewrites its price bindings and its selection wiring in one step, and keeps the plan order in sync, so you do not chase references by hand.TODO: screenshot of a plan option controller showing the package picker fed by the synced catalog.
Dynamic, store-truth pricing
Plan cards never contain a typed-in price. They read live values from the store through variables in thepaywall namespace, so what a user sees is exactly what they will be charged, in their currency, after any eligible trial.
The most useful values:
Use them in copy the same way you use any variable, wrapped in interpolation. For example, a CTA label of
Continue for {{paywall.selected.price}} updates as the user switches plans.
Preview every state
Prices, trials, and purchase outcomes only exist at runtime, so the editor gives you a paywall preview to exercise them. Open the paywall preview control in the phone toolbar and switch between:- Products: loading, loaded, or failed to load.
- Trial: eligible or not eligible.
- Purchase result on tap: success, cancelled, pending, or failure.
- Restore result: found or not found.
- Entitlement: subscribed or not, to preview the skip-if-entitled path.
- Locale: sample currencies including a right-to-left layout, to catch overflow and truncation.
Publish
Publishing a paywall runs the normal publish flow plus a set of paywall checks. If any fail, publishing is blocked until you fix them. The main ones:- A purchase CTA is present.
- A restore action exists somewhere in the flow.
- Legal links (Terms and Privacy) are set.
- No hardcoded prices anywhere in the paywall’s text.
- Every bound package exists in your catalog and is not removed.
Common mistakes
- Typing a price into a headline or button. Bind to
paywall.selected.priceor apaywall.package.<id>.pricevariable so the store’s real, localized price shows. - Forgetting the restore button. App Review will reject a subscription paywall with no way to restore. Add the restore block.
- Leaving trial copy unconditional. A “7 days free” line must be bound to the trial variable so it only appears for users who are actually eligible.
- Not previewing the failed-products state. If products fail to load on device, your paywall still has to look right. Preview the loading and failed states.