> ## Documentation Index
> Fetch the complete documentation index at: https://docs.userjourneys.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Event-triggered interviews

> Use the React Native SDK to launch UserJourneys interviews from an existing analytics track client.

Use the analytics wrapper when your app already sends product events through one
central client with a `track(eventName, properties)` method. This is the
Mixpanel path and also works for app-owned analytics helpers with the same
method shape. Analytics providers with different event APIs should call
`interviews.track(eventName, properties)` from the app's central analytics
helper instead.

## Flow

```text theme={null}
analytics.track("Order Completed")
  -> original analytics call runs (return value preserved)
  -> SDK checks the cached interview trigger config (loaded at startup)
  -> unrelated events are ignored locally
  -> matching events create a pendingInvite from local config — no network call
  -> app shows a native prompt instantly
  -> user accepts -> SDK resolves the signed launch with UserJourneys
  -> server returns webview, external_browser, or not_eligible
  -> WebView or browser fallback opens
```

The SDK does not replace your analytics provider. It observes the same event
stream from one wrapper point and preserves the original `track` return value.
Interview config, API, or network failures are reported through diagnostics
and do not block the original analytics call.

## Track client shape

The wrapped client must have a `track` method whose first argument is the event
name and whose second argument is the event properties object.

```ts theme={null}
type TrackMethodClient = {
  track: (
    eventName: string,
    properties?: Record<string, unknown>,
    ...extraArgs: unknown[]
  ) => unknown;
};
```

`wrapTrackClient` returns a proxy with the same surface as the original
client. All properties other than `track` pass through unchanged. When `track`
is called, the wrapper:

* calls the original analytics client first;
* returns the original `track` result;
* reads the event name and allowlisted properties;
* creates a pending invite locally from the cached trigger config when the event
  can launch an interview — with no network call, so the prompt appears
  instantly. The signed launch is resolved later, only when the user accepts the
  prompt.

## Server-controlled triggers

Study Launch Rules own trigger config, eligibility, interview selection, and
fallback behavior after the app integration. The SDK loads active event trigger
config for the project, caches it for the server-provided TTL, and ignores
unrelated analytics events locally. Matching events create a pending invite
instead of opening an interview without user action. You do not need an app
release when UserJourneys changes which study is active for an event.

The app does not define trigger rules. If UserJourneys changes the
event-to-study mapping, targeting, fallback policy, or active study, the
server config changes and the installed SDK keeps working.

To create an event trigger, add an app-event
[Study Launch Rule](/interviews/targeting-rules) on the study and set its event
name.

## Metadata

Only pass allowlisted primitive metadata.

```ts theme={null}
const interviews = createInterviewClient({
  publicKey: "INTERVIEWS_PUBLIC_KEY",
  referenceId: user.id,
  mapTrackProperties: (_eventName, properties) => ({
    total: typeof properties?.total === "number" ? properties.total : null,
    currency:
      typeof properties?.currency === "string" ? properties.currency : null,
  }),
});
```

Nested analytics payloads, tokens, emails, and private vendor ids should stay
out of SDK metadata.

## Prompt before opening

Matching events create a pending invite. The mounted
`InterviewHost` shows the in-app popup for that invite. Accepting
the prompt opens the in-app WebView or browser fallback. Dismissing the prompt
clears the invite without opening anything.

See [Customize the prompt](/react-native-interviews/customize-prompt) to render
your own prompt component.
