Skip to main content
Most apps use one setup function and one mounted host. The host owns the built-in native prompt and the full-screen WebView.
import {
  createUserJourneysInterviews,
  UserJourneysInterviewHost,
} from "@userjourneys/interviews-react-native";

createUserJourneysInterviews

Creates a wrapper around your existing analytics client and returns link handling utilities.
const interviews = createUserJourneysInterviews({
  publicKey: "USERJOURNEYS_INTERVIEWS_PUBLIC_KEY",
  referenceId: currentUser.id,
});
publicKey
string
required
The Interviews public SDK key from Settings -> API Keys. It is scoped to loading interview triggers and launching eligible in-app interviews.
referenceId
string | null | undefined
Your stable person id. Use the same id you use for your analytics person id, such as a Mixpanel distinct_id, or your canonical user id.
openFallbackUrl
(url) => void | Promise<void>
Optional override for opening the server-provided browser interview URL. Defaults to React Native Linking.openURL.
mapTrackProperties
(eventName, properties) => metadata
Optional allowlist mapper for event properties. Only JSON primitive metadata is accepted.
metadata
metadata
Optional app-level primitive metadata added to eligible event and link launch requests.
onDiagnostic
(event) => void
Optional low-level diagnostics for logging config loads, ignored events, fallbacks, and WebView bridge errors.

wrapTrackClient

Wraps a client that already exposes a track(eventName, properties, ...extraArgs) method, such as the Mixpanel React Native client or an app-owned analytics helper with the same method shape.
export const analytics = interviews.wrapTrackClient(rawAnalytics);
The wrapper returns a proxy with the same surface as the original client. Non-track properties pass through unchanged. The original analytics call still runs first, and the wrapper preserves the track return value. UserJourneys receives the event name and mapped context in the background and decides whether to create a pending invite. UserJourneys config, API, or network failures are reported through onDiagnostic; they do not change the wrapped analytics return value. If your analytics provider uses a different event method, call that provider and then call interviews.track(eventName, properties) from the same analytics helper instead of using wrapTrackClient. The SDK does not call UserJourneys for every analytics event. It loads the active trigger config for the project, caches it for the server-provided TTL, ignores unrelated events locally, and only resolves matching events with the server. Matching events do not open the interview immediately. They set snapshot.pendingInvite. By default, UserJourneysInterviewHost renders the prompt for that invite.

useUserJourneysInterviews

Subscribes to the SDK snapshot so you can render a custom native prompt. When using a custom prompt, mount UserJourneysInterviewHost with showPrompt={false}.
const { pendingInvite, activeLaunch } = useUserJourneysInterviews(interviews);
pendingInvite is set after an eligible analytics event or synced audience match. activeLaunch is set when an invite starts or an explicit link opens in-app.

startPendingInvite

Starts the current pending invite.
await interviews.startPendingInvite();
Returns:
type UserJourneysStartPendingInviteResult =
  | "webview"
  | "external_browser"
  | "not_eligible"
  | "expired"
  | "none";
webview means the full-screen host can render the in-app interview. external_browser means the SDK opened the fallback URL. expired means the signed launch expired before the user accepted. not_eligible means the server declined the launch after the user accepted a pending audience prompt. none means no pending invite was available or launch resolution failed without breaking the app.

dismissPendingInvite

Clears the current pending invite without opening the interview.
interviews.dismissPendingInvite();
Handles HTTPS invite links from Intercom, email, push, or any other channel.
await interviews.handleUserJourneysLink("https://app.userjourneys.ai/i/dS8FFCgu");
Supported formats:
  • https://app.userjourneys.ai/i/{inviteCode}
  • https://app.userjourneys.ai/interviews/{inviteCode}
Returns:
type UserJourneysLinkResult =
  | { handled: true; mode: "webview" | "external_browser" | "not_eligible" }
  | { handled: false; reason: "not_userjourneys_link" | "resolve_failed" };

UserJourneysInterviewHost

Mounts the built-in prompt and full-screen WebView host.
<UserJourneysInterviewHost
  client={interviews}
  onStarted={({ sessionId }) => {
    analytics.track("UserJourneys Interview Started", { sessionId });
  }}
/>
client
UserJourneysInterviews
required
The client returned by createUserJourneysInterviews.
visible
boolean
Optional app-controlled visibility gate. The host still requires an active pending invite or active server launch decision.
showPrompt
boolean
Controls whether the built-in pending-invite prompt is rendered. Defaults to true. Set to false when rendering your own prompt with useUserJourneysInterviews.
allowedOrigins
readonly string[]
Optional extra origins that the WebView may navigate to. The launch and fallback origins are allowed automatically.
onLoaded
(event) => void
Called when the web interview reports that the embed loaded.
onStarted
(event & { sessionId: string }) => void
Called when the interview session starts.
onCompleted
(event & { sessionId: string }) => void
Called when the session completes.
onAbandoned
(event & { sessionId?: string }) => void
Called when the participant leaves before completion.
onClosed
(event & { reason: 'user' | 'system' }) => void
Called when the participant closes the in-app interview.
onError
(error, event) => void
Called for WebView load failures, invalid bridge messages, blocked navigation, or interview runtime errors reported by the embed.

referenceId and triggerEvent

referenceId answers who the respondent is. Use your analytics person id or canonical user id. triggerEvent answers what app event opened the interview. It is attribution context; UserJourneys targeting and eligibility are server-controlled.

Attribution fields

SDK snapshots and callbacks can include these server-provided attribution fields:
launchRuleId
string | undefined
The Study Launch Rule that created the pending invite or launch.
experimentId
string | undefined
The study that UserJourneys selected for the launch.
audienceId
string | undefined
The synced audience that matched the current referenceId, when the launch started from an audience prompt.
Apps normally do not construct these values. They come from UserJourneys so in-app WebView launches and browser fallback sessions keep the same attribution.

Public API boundary

The SDK uses two versioned public endpoints:
  • GET /api/v1/interview-participant/config
  • POST /api/v1/interview-participant/launches
The app never calls bootstrap, conversation-token, vendor, or raw interview runtime endpoints. config returns server-controlled trigger rules. launches returns a launch decision object: webview, external_browser, or not_eligible.

Package boundary

Install @userjourneys/interviews-react-native in your app. The SDK includes the shared UserJourneys interview runtime in its published JavaScript and type output, so there is no separate UserJourneys core package for app teams to install or version.