# Usage

## Initialize provider in app root

```ts
import { DetourProvider, type Config } from '@swmansion/react-native-detour';

const config: Config = {
  apiKey: process.env.EXPO_PUBLIC_DETOUR_API_KEY!,
  appID: process.env.EXPO_PUBLIC_DETOUR_APP_ID!,
  shouldUseClipboard: true,
  // linkProcessingMode: 'all' // default
};

export default function RootLayout() {
  return (
    <DetourProvider config={config}>
      <RootNavigator />
    </DetourProvider>
  );
}
```

:::caution[One DetourProvider per app]
Use exactly one `DetourProvider` in your app tree.

On Expo Web, `DetourProvider` is disabled:
it returns a no-op context (`isLinkProcessed: true`, `link: null`) and does not process links.
:::

If you want complete, runnable integrations for each navigation style, go to [Examples](https://detour.swmansion.com/docs/sdk/react-native/examples).

## Handle resolved links with `useDetourContext()`

```ts
import { useDetourContext } from '@swmansion/react-native-detour';
import { useEffect } from 'react';
import { useRouter } from 'expo-router';

export function RootNavigator() {
  const { isLinkProcessed, link, clearLink } = useDetourContext();
  const router = useRouter();

  useEffect(() => {
    if (!isLinkProcessed || !link) return;

    router.replace({
      pathname: link.pathname,
      params: link.params,
    });

    clearLink();
  }, [clearLink, isLinkProcessed, link, router]);

  if (!isLinkProcessed) {
    return null;
  }

  return <AppStack />;
}
```

### `link` structure

`useDetourContext()` returns a `link` object (or `null`):

<PropertyList>
  <Property name="link.route">
    Full in-app route with query string (e.g. `/details?utm=1`).
  </Property>
  <Property name="link.pathname">
    Path without query (e.g. `/details`).
  </Property>
  <Property name="link.params">
    Parsed query params record.
  </Property>
  <Property name="link.url">
    Original URL or raw value.
  </Property>
  <Property name="link.type" type={"'deferred' | 'verified' | 'scheme'"} />
</PropertyList>

Use `clearLink()` after handling navigation to avoid repeated redirects.

## Choose `linkProcessingMode`

`Config.linkProcessingMode` controls which link sources are handled by the SDK:

| Value             | Deferred | Universal / App | Custom scheme |
| ----------------- | -------- | --------------- | ------------- |
| `'all'` (default) | Yes      | Yes             | Yes           |
| `'web-only'`      | Yes      | Yes             | No            |
| `'deferred-only'` | Yes      | No              | No            |

Use `'deferred-only'` when Expo Router `+native-intent.tsx` already handles runtime and initial URLs.

## Expo Router integration

:::tip[Recommended for Expo apps]
If you use Expo Router, we **strongly recommend** using our dedicated `createDetourNativeIntentHandler` API in a [`+native-intent.tsx`](https://docs.expo.dev/router/advanced/native-intent/) file. This intercepts URLs at the router level before any screen renders, avoiding flash-of-wrong-screen issues and providing the smoothest deep-linking experience.
:::

Expo Router's `+native-intent.tsx` file lets you intercept and transform incoming system URLs before the router processes them. The Detour SDK provides `createDetourNativeIntentHandler`, a factory that creates a handler pre-configured for Detour link resolution.

### Basic setup

Create a `+native-intent.tsx` file in your app directory (e.g. `src/app/+native-intent.tsx`):

```ts
import { createDetourNativeIntentHandler } from "@swmansion/react-native-detour/expo-router";

export const redirectSystemPath = createDetourNativeIntentHandler();
```

:::note[This is intercept mode]
Any URL matching a Detour host is caught and the user is routed to the home screen (default `fallbackPath`). Deferred links are still handled separately by `DetourProvider`.
:::

### Resolve mode

To resolve Detour short links to their full destination URLs at the router level, pass a `config` object:

```ts
import { createDetourNativeIntentHandler } from "@swmansion/react-native-detour/expo-router";

export const redirectSystemPath = createDetourNativeIntentHandler({
  config: {
    apiKey: process.env.EXPO_PUBLIC_DETOUR_API_KEY!,
    appID: process.env.EXPO_PUBLIC_DETOUR_APP_ID!,
  },
});
```

In resolve mode, when a user taps a Detour short link (e.g. `https://abc123.godetour.link/xyz`), the handler resolves it to the full destination URL and routes directly to the correct screen, all before the first render.

See [Expo Router helper](https://detour.swmansion.com/docs/sdk/react-native/api-reference#expo-router-helper) for the full list of options (custom hosts, fallback path, timeout, route mapping, etc.).

### Configure `DetourProvider` for native intent

When using `+native-intent.tsx` to handle Universal Links and App Links, configure the provider to only process deferred links:

```ts
const config: Config = {
  apiKey: process.env.EXPO_PUBLIC_DETOUR_API_KEY!,
  appID: process.env.EXPO_PUBLIC_DETOUR_APP_ID!,
  linkProcessingMode: "deferred-only",
};
```

This avoids double-processing: `+native-intent.tsx` handles runtime and initial URLs, while `DetourProvider` handles deferred deep links only.

### Advanced examples

The SDK repository includes examples for common native intent scenarios:

- **`expo-router-native-intent`** — Full resolve mode setup with a custom `mapToRoute` function and scheme URL handling. Use this as a starting point when you need to transform resolved URLs before routing (e.g. stripping path prefixes) or when you want to handle custom scheme links alongside Detour links.

- **`expo-router-advanced`** — Demonstrates Detour inside an auth- and onboarding-gated flow. Deferred and runtime links are preserved through sign-in and one-time onboarding before navigating to their destination. Use this when your app requires the user to be signed in (and optionally onboarded) before a deep link should take effect.

For all runnable examples, see [Examples](https://detour.swmansion.com/docs/sdk/react-native/examples).

### Alternative: catch-all route without `+native-intent.tsx`

If you prefer not to use `+native-intent.tsx`, you can handle all incoming links through `DetourProvider` with `linkProcessingMode: 'all'` (the default) and implement a catch-all route in your navigation stack.

In this approach, `DetourProvider` processes all link types (deferred, Universal/App Links, and custom scheme). You consume the resolved link via `useDetourContext()` in a top-level component and navigate programmatically:

```ts
const { isLinkProcessed, link, clearLink } = useDetourContext();

useEffect(() => {
  if (!isLinkProcessed || !link) return;
  router.replace({ pathname: link.pathname, params: link.params });
  clearLink();
}, [isLinkProcessed, link]);
```

This was the primary integration pattern before the SDK introduced native intent support (pre-1.x). It still works but the `+native-intent.tsx` approach provides better UX by resolving links before the first screen renders.

## Analytics module

`DetourAnalytics` emits events that are sent by the active `DetourProvider`.

```ts
import {
  DetourAnalytics,
  DetourEventNames,
} from "@swmansion/react-native-detour";

DetourAnalytics.logEvent(DetourEventNames.Purchase, {
  item: "subscription_premium",
  currency: "USD",
});

DetourAnalytics.logRetention("home_screen_opened");
```

### Automatic events

Besides the events you log manually, `DetourProvider` reports some events on its own, with no wiring needed:

- `app_open` — a retention event logged once per session when the provider first mounts (cold start).
- `opened_via_universal_link` — logged whenever the app is opened through a Universal Link (iOS) or App Link (Android). Custom scheme links and deferred links do not trigger this event.

:::note[SDK version header]
Every request the SDK sends to the Detour backend carries an `X-SDK: react-native/<version>` header. It is used for diagnostics and SDK-usage analysis and requires no configuration.
:::

## Related pages

- [Examples](https://detour.swmansion.com/docs/sdk/react-native/examples)
- [Migration to v2](https://detour.swmansion.com/docs/sdk/react-native/migration-2-0-0)
- [API Reference](https://detour.swmansion.com/docs/sdk/react-native/api-reference)
- [Custom Storage](https://detour.swmansion.com/docs/sdk/react-native/custom-storage)
- [Testing & Troubleshooting](https://detour.swmansion.com/docs/sdk/react-native/testing)