For the complete documentation index, see llms.txt. This page is also available as Markdown.

Monetize in React Native

This guide walks through a complete React Native integration: creating products, installing the SDK, wiring checkout, gating content on what the user has bought, and going live.

The tiun React Native SDK covers authentication and checkout — subscriptions and one-time purchases. It renders the tiun overlays inside your app and binds the user's session to a hardware-backed device key, so the session survives restarts without you storing anything.


1. Set up your environment and products

Most teams build against sandbox first: click the Sandbox toggle in the dashboard sidebar and Enable it — see setting up your environment.

Then, in the environment you'll point the app at, go to Settings → Environment setup, turn on App, and enter your app scheme — for example myapp://. This is how checkout gets back into your app after payment; you'll register the same scheme natively in step 3. tiun checks your app's returnUrl against this scheme when login or checkout opens, so a scheme that isn't registered here — or is registered in the other environment — fails right away, not at the end of payment.

Create one product per plan — for example Light and Pro — and copy their product IDs. The full walkthrough is in creating your first product. Copy your snippet ID from the same environment.


2. Install the SDK

Install the SDK and its native dependencies, then rebuild:

npm install @tiun/react-native-sdk react-native-webview \
  react-native-secure-sign react-native-keychain \
  react-native-inappbrowser-nitro react-native-nitro-modules
cd ios && bundle exec pod install

These are native modules, so a JavaScript reload isn't enough — rebuild and reinstall the app. The full list of what each dependency does is in Installation.


After payment, the provider redirects back into your app through a deep link that you choose — for example myapp://tiun/return. Register its scheme natively, or checkout can never complete.

One scheme, three places. The scheme has to match everywhere: the App scheme in the dashboard's Environment setup (myapp://), the native registration below (myapp), and the returnUrl you pass to the SDK in step 4 (myapp://tiun/return). The host and path after the scheme are up to you.

On iOS, add it to Info.plist:

Still on iOS, forward incoming links to React Native's Linking module in AppDelegate.swift — the Info.plist entry alone doesn't get the link to React Native, and checkout won't resolve without it:

On Android, add an intent filter to your main activity and set android:launchMode="singleTask":


4. Add the provider

Keep your config and product IDs in one module so every screen references the same values:

Wrap your app root in <TiunProvider>. The one rule is that it sits above everything that uses the tiun hooks — the overlay sizes itself to the window, so it covers your UI from anywhere in the tree:

The provider takes up no space on screen until the user opens login or checkout.


5. Build a pricing screen

One button per plan, each calling checkout() with its product ID:

tiun opens the checkout overlay — it collects the user's email, verifies their identity, takes payment, and grants access in one flow. Payment itself happens in the in-app browser and returns to your app through the deep link you registered in step 3. For what the overlay does behind the scenes, see Checkout / How it works in Reference.


6. Gate content on what the user bought

After a successful purchase the user's productAccess array contains the product they just bought. It's the canonical source of truth for what they can access — see Product access in Reference.

Derive the current tier in one place:

Then gate your screens on it:

useTiun() re-renders your component whenever the user changes, so the same code covers checkout success, login, logout, and the session restore at launch. If you need to react to a change rather than render from it — refetching data, resetting a screen — subscribe with useTiunEvent('userChange', ...).

The userChange payload has no event field in React Native. If you're porting from the web SDK, replace data.event === 'login' checks with the separate login and logout events. See Hooks and events.


7. Add login and logout

Returning subscribers sign in without buying again — their existing productAccess comes back with the session, and your gating picks it up unchanged.


8. Verify on your server

Gating in the app controls what it renders. If your backend serves the premium payload itself, verify the user there before responding — a client can be modified.

Get a signed token from the SDK and send it with the request:

The token is the same signed JWT the web SDK issues, so the backend half is unchanged — see verify authentication server-side for the exchange, and verify subscriptions server-side for checking entitlements.


9. Test on a device

The user's session is bound to a key in the device's secure hardware, which limits where you can test:

  • iOS Simulator can't do login or checkout — there's no Secure Enclave. Use a physical iPhone.

  • Android emulators and devices work normally.

  • On iOS, checkout shows a one-time system prompt — "…wants to use…to sign in". That's expected; it's how the payment redirect gets back into your app.

  • Set debug: true in your config to see [tiun] bridge logs in the Xcode or Android console.

  • Check that Metro can reach your iPhone. Office and guest Wi-Fi often isolate clients, and the failure is silent — the app keeps running its last cached bundle, so your changes look like they did nothing. Personal Hotspot is the quickest way to rule it out.

Use simulated payments in sandbox so you can run the full purchase flow without real cards.

If login or checkout doesn't work

Most failures come from the return scheme not matching across the three places from step 3. What you see tells you which one:

What you see
Likely cause
Fix

Login or checkout opens and closes straight away

The scheme in your returnUrl isn't the App scheme in the dashboard — or it's registered only in a different environment from the one host points at

Compare returnUrl with Settings → Environment setup → App scheme, character for character, in the environment you target

Payment succeeds, but the app never finishes checkout

The scheme is accepted by tiun, but the app doesn't receive the deep link

Check the scheme in Info.plist and the Android intent filter, the RCTLinkingManager forwarding in AppDelegate, and android:launchMode="singleTask" — see step 3

Login or checkout fails only on the iOS Simulator

No Secure Enclave

Test on a physical iPhone

After changing anything native — Info.plist, AppDelegate, or AndroidManifest.xml — rebuild and reinstall the app; a JavaScript reload doesn't pick it up.


10. Go live

When the sandbox integration works:

  1. Set up live in the dashboard, if you haven't — register your app scheme in the live Settings → Environment setup, and create live products and API keys; all are separate from sandbox.

  2. Remove host from your config (or set it to https://api.tiun.live) so the app targets live.

  3. Swap in your live snippet ID and live product IDs (p-test-… → p-live-…).

  4. Turn off debug.

  5. If you verify server-side, switch to the live API base URL and a live API key.

  6. Enable payouts so live revenue can be paid out to you.

The SDK API is identical across environments — only these IDs and credentials change. See setting up your environment for the full sandbox-to-live workflow.


For the full hook and event reference, see Hooks and events in the SDK docs, and React Native examples for more patterns.

Last updated

Was this helpful?