The 2026 guide to adding a paywall to React Native (Expo + bare)
There are three ways to get a paywall into a React Native app in 2026:
- A dashboard paywall — RevenueCat Paywalls (free under $2.5k monthly tracked revenue), composed in their dashboard, rendered by their SDK. Fastest to iterate; the paywall isn't your code. (How to choose.)
- Hand-rolled — write the screen yourself on
react-native-purchases(orreact-native-iap). Full control; you own every failure mode. - Install a tested module — copy pre-built, pre-tested paywall code into your repo and configure one file. Your code afterward, with the boring parts already verified.
This guide is the map for all three: the store and RevenueCat setup is identical regardless, and the code step differs. It condenses a nine-phase install runbook (the same one our paywall module ships) into one page. Numbers below were current as of writing — verify store pricing and consoles' UIs, which change often.
Phase 0 — Prerequisites and costs
- A React Native app, TypeScript: either Expo (SDK ≥ 52) or bare RN CLI — the tooling below detects which.
- Google Play developer account: US$25 one-time. Apple Developer Program: US$99/year (skip if Android-only).
- RevenueCat account: free while monthly tracked revenue is under US$2.5k.
- A clean git working tree in the app. You'll want to review this diff.
Phase 1 — Store setup (do this first)
RevenueCat reads products from the stores, not the other way round — so stores first.
- Google Play: create the app (note the package name — it must match your
applicationId); set up the merchant profile (Monetize → Payments) — subscription products cannot be created without it; create two subscription products (e.g.yourapp_pro_monthly,yourapp_pro_yearly); add your Gmail as a license tester (Setup → License testing) so sandbox purchases show a test card instead of charging money. - App Store Connect: register the bundle ID, create the app, add a subscription group with the same two product IDs (trials live on the product as an introductory offer — not in app code), and create a sandbox tester.
- Products must be Active before real or sandbox purchases work.
Phase 2 — RevenueCat
Create a project; add one app per platform (Android needs a Google service account with its JSON credentials pasted into RevenueCat — this links billing). Import the two products; create an entitlement (e.g. pro) with both products attached; create an offering with Monthly ($rc_monthly) and Annual ($rc_annual) packages and mark it Current — stock paywall screens read only the Current offering. Grab the public SDK API keys (goog_… / appl_… — public, safe to embed).
Phase 3 — The Expo Go trap (read before Phase 4)
You cannot test purchases in Expo Go. Native billing SDKs (react-native-purchases included) contain native code that the Expo Go runtime doesn't include — the module errors on load. You need a development build: npx expo prebuild, then EAS (free tier available; first builds typically queue 15–45 minutes) or a local build (npx expo run:android / run:ios). On bare RN, the SDK autolinks — rebuild from Xcode/Gradle as usual, plus cd ios && pod install on macOS.
Phase 4 — The paywall code (the three ways fork here)
- Dashboard (RC Paywalls): follow RevenueCat's paywall tooling; requires react-native-purchases ≥ 8.11.3 (single-page) or ≥ 10.6.0 (multipage); iOS 15+/Android 7+.
- Hand-rolled: build a screen on
fetchOfferings/purchase/restorePurchases; render prices from the Current offering; handle loading, error, and empty-offering states; expose restore. The failure modes to cover by name: silent purchase failure, entitlement races, missing restore, stale config. - Module: one command copies the six files into
src/paywall/— screen with live prices,useEntitlement()hook, purchase/restore wiring, zod-validated config (startup validation; a typo names its field and fails fast). Configurepaywall.config.ts: API key, entitlement ID, product IDs, copy, colors, trial toggle (1–90 days). Gate features withuseEntitlement("pro"); route the four analytics events (paywall_view,subscribe,trial_start,restore) to your analytics.
Whatever route: validate config at startup. A strict schema beats a console.log you never read.
Phase 5 — Sandbox test (human hands)
Automated checks can't buy anything — this step is yours. Android: use an emulator image with the Google Play icon (API 34/35 — "Google APIs"-only images have no Play Store), sign into the Play Store with the license-tester Gmail, install the build, and run the loop: purchase (payment sheet must show test-card wording) → kill and reopen the app → Restore Purchases → entitlement returns → cancel via Play Store's Payments & subscriptions. iOS: purchase with the sandbox tester, confirm the sandbox dialog; manage/cancel test subscriptions in Settings → App Store → Sandbox Account.
Phase 6 — Production checklist
Before submitting: products Active in both consoles; offering still Current; subscription disclosed in the listing (price, period, auto-renewal, cancellation); privacy policy URL present; data-safety/privacy-label forms answered accurately (purchase history and entitlement validation transit the store and RevenueCat — say so); Google personal accounts created after 2023-11-13 need closed testing first (12 testers, 14 days). The full list with guideline references: the rejection checklist. Run the free preflight audit before every submission build.
Phase 7 — Getting paid
Google: payouts flow through the merchant profile — attach a bank account in Play Console's payments profile. Apple: accept the paid-apps agreement, complete banking and tax forms in App Store Connect. RevenueCat adds no fee under the $2.5k threshold; the stores' own commissions apply per store.
Why this is all still worth it in 2026
The ecosystem is deep: react-native-purchases averages roughly 2.9 million downloads a month on npm (measured August 2026), with react-native-iap around 570k — the tooling is mature and the store plumbing is the stable, boring kind of problem. Boring is good. Boring means a tested part can do it once.
That's the honest case for way #3: if you direct a coding agent, hand it a runbook and let it install code whose install ends with a verify receipt — the paywall module is exactly that ($79 one-time, Expo SDK ≥ 52 and bare RN, code lives in your repo). If you'd rather build every line yourself, phases 1–2 and 5–7 above are still your checklist.
FAQ
Can I test purchases in Expo Go?
No. Billing SDKs contain native code the Expo Go runtime doesn't include. Use a development build: npx expo prebuild + EAS or a local build. An agent that reports success testing in Expo Go has tested nothing.
One codebase, both stores?
Yes — RevenueCat's SDK abstracts StoreKit and Play Billing. You create products per store (same product IDs), and your Current offering in RevenueCat determines what's actually sold. Store consoles own prices and trials.
Do I really need the Google merchant profile?
Yes — Play Console cannot create subscription products without it (Monetize → Payments). It's also where payouts are configured later.
What does it cost to run subscriptions?
Accounts: Google $25 one-time, Apple $99/yr. RevenueCat: free under $2.5k monthly tracked revenue, then 1%. Store commissions apply per store on revenue. Verify current pricing on each vendor's page — these numbers move.