Skip to main content
The Userpilot React Native module supports a custom URL scheme that lets you preview experiences on a real device before publishing them, and that carries push notification taps back into your app. Setting it up is two steps: register the scheme on each platform so the OS routes matching links to your app, then forward the incoming URL to the Userpilot SDK from JavaScript.
Using Expo? Follow Custom URL Scheme with Expo instead. Expo registers the scheme from app.json and delivers links through expo-linking, so the setup differs from the steps below.

Prerequisites

Your app must be configured to support Linking. Follow the React Native guide for Enabling Deep Links on both Android and iOS before continuing.

Register the custom URL scheme

Replace APP_TOKEN with your app’s Userpilot token, which you can obtain from your Environments Page. For example, if your token is NX-12345678, your scheme value is userpilot-nx-12345678. The quickest way to register it on both platforms is uri-scheme:
After running the Android command, open android/app/src/main/AndroidManifest.xml and set android:host="sdk" on the Userpilot scheme’s <data> element in the main Activity’s VIEW intent filter:
Userpilot validates that incoming preview and push-notification URLs use the sdk host.

Register it manually

To register the scheme by hand instead, apply the following changes. iOS — in Info.plist:
iOS — in AppDelegate.swift, hand the URL to React Native’s linking manager so it reaches your JavaScript listener:
Android — in AndroidManifest.xml, on the main Activity. Set android:launchMode="singleTop" so an incoming link is delivered to the running Activity rather than creating a second instance of it:

Handle the custom URL scheme

Pass every incoming URL to Userpilot.didHandleURL(url). It resolves to true when the SDK recognized and handled the link, and false when your app should handle it. The function is asynchronous, so await it or use the returned promise. React Native delivers links through two separate paths, and you need both: Handling only the event listener silently drops every link that starts the app, which includes scanning the Builder’s QR code while your app is closed.
Set up the SDK before you consume the launch linkdidHandleURL returns false when the SDK hasn’t been set up yet, which sends the link to your own routing instead of Userpilot. Call Userpilot.setup(...) before you resolve getInitialURL().

The SDK only claims a URL when the scheme matches your token and the host is sdk. Every other URL is passed back to your app.
didHandleURL is the single entry point on both platforms, and it covers push notification taps too. On Android the SDK posts each notification with a matching deep link, so a tap arrives at this same handler. On iOS notification taps are handled natively by the SDK and never reach your URL listener. The didHandleIntent method was removed in @userpilot/react-native 1.2.0, so don’t reach for it.

Preview an experience with a QR code

Userpilot can render a draft experience on your device before you publish it, so you can check layout, copy, and behavior on a real screen. Preview is supported for Flows and Surveys. The preview is delivered over the custom URL scheme. It works once your app is installed on the device and the scheme is registered and handled as described above.
1

Open the experience

Open a Flow or Survey in the Experience Builder and enter Edit Mode.
2

Start the preview

Select Preview in the top-right corner of the builder. A popup with a QR code appears.
3

Scan the QR code

Scan the code with your device camera. Your app opens and the experience appears.
Points to keep in mind:
  • You don’t need to apply or save your changes before previewing them.
  • The experience doesn’t need to be live.
  • A preview bypasses the experience’s targeting and frequency settings, so it appears even when the current user wouldn’t normally qualify for it.
  • Once you close the experience, the app resumes normal behavior.

Test push notifications

You can send a test push to a specific user from the Userpilot dashboard and verify delivery and tap handling on a real device without sending anything to your wider audience. The notification doesn’t need to be live, so you can test it while it’s still a draft.
  • Test pushes work in both the staging and production environments.
  • Test pushes are not counted as real sends, and they’re excluded from analytics.
  • Test pushes bypass the notification’s targeting and frequency settings.
For the dashboard steps, see Mobile push notifications. Because a notification tap arrives as a deep link on Android, a test push also exercises your didHandleURL handling there. If the notification appears but tapping it does nothing, the scheme registration is the first thing to check.
Open a link directly to confirm your scheme is registered and your handler runs, without going through the Builder:
Replace the scheme with your own token and 12345 with a real experience ID. You can also use npx uri-scheme open "userpilot-nx-12345678://sdk/experience_preview/12345" --ios if you prefer to stay in the JavaScript toolchain.

Troubleshooting

Confirm the registered scheme matches your token exactly, lowercased. A mismatched scheme means the OS never routes the link to your app, so your listener is not called at all. Verify the registration with the commands above.
You’re handling Linking.addEventListener but not Linking.getInitialURL(). The event listener never fires for the link that launched the app, so a cold start needs the explicit getInitialURL() call shown above.
Two common causes. First, the SDK wasn’t set up yet when you called it, so call Userpilot.setup(...) first. Second, didHandleURL returns a promise: without await, you’re testing the promise object rather than its result, and a promise is always truthy.
Notification taps travel over this same URL scheme on Android, so they need the intent filter and the didHandleURL forwarding described above. Confirm the host in your filter is exactly sdk.
Each environment has its own token, and the scheme follows the token. Confirm the staging build registers the scheme for the token it initializes the SDK with.