# API Reference

## DetourProvider

Top-level React component that initializes the Detour SDK. It handles deferred link matching, Universal Links and App Links, the initial URL, and sending analytics events.

On mount, the provider:

1. Checks for an initial URL that launched the app, a Universal Link or App Link on cold start.
2. If there is none, asks the Detour API for a deferred link. This happens on the first launch after install only.
3. Starts listening for Universal Links and App Links while the app is running.
4. Forwards analytics events to the Detour backend.

With `linkProcessingMode: 'deferred-only'`, steps 1 and 3 are skipped.

Use exactly one `DetourProvider` at the root of your app tree. With more than one mounted, analytics events are dropped.

### Signature

```ts
function DetourProvider(props: {
  config: Config;
  children: React.ReactNode;
}): JSX.Element;
```

### Web behavior

On `Platform.OS === 'web'`, the provider does nothing: no link processing, no analytics, no storage access. It returns this context value:

- `isLinkProcessed: true`
- `link: null`
- `clearLink: () => {}`

In development builds the SDK logs one warning, `🔗[Detour:WEB_UNSUPPORTED]`. Code shared between web and native can use the provider safely.

### Config fields

<PropertyList>
  <Property name="appID" type={"string"} required>
    App identifier from the Detour Dashboard.
  </Property>
  <Property name="apiKey" type={"string"} required>
    Publishable API key from the Detour Dashboard. Sent as a Bearer token on every API call.
  </Property>
  <Property name="shouldUseClipboard" type={"boolean"} default={"true"}>
    iOS only. When `true`, the SDK reads the clipboard as a signal for deferred link matching. Set it to `false` to skip the read.

    On Android the clipboard is never read. The Play Install Referrer carries the click ID there.

    The clipboard string is sent as read, so declare it in the store questionnaires unless you turn this off. See [Privacy](https://detour.swmansion.com/docs/sdk/react-native/privacy).
  </Property>
  <Property name="shouldTrackAutomaticEvents" type={"boolean"} default={"true"}>
    From **2.3.1**. Controls the `app_open` retention event the SDK logs once per session on cold start.

    Set it to `false` to opt out, for example until the user grants tracking consent. Manual `DetourAnalytics` calls still send.
  </Property>
  <Property
    name="linkProcessingMode"
    type={"LinkProcessingMode"}
    typeHref="#linkprocessingmode"
    default={"'all'"}
  >
    Which link sources the SDK processes. See [LinkProcessingMode](#linkprocessingmode).
  </Property>
  <Property
    name="storage"
    type={"DetourStorage"}
    typeHref="#detourstorage"
    default={"AsyncStorage"}
  >
    Storage adapter for the first-launch flag and the device ID.

    Defaults to `@react-native-async-storage/async-storage`. If that package is not installed and you pass no adapter, the provider throws an error.
  </Property>
</PropertyList>

## useDetourContext

Hook that returns the link state from the nearest `DetourProvider`. Throws an error when called outside a `DetourProvider`.

### Signature

```ts
function useDetourContext(): DetourContextType;
```

### Returned object

<PropertyList>
  <Property name="isLinkProcessed" type={"boolean"}>
    `true` once the SDK has finished looking for a link, whether or not it found one. Use it to show a loading screen during cold start.
  </Property>
  <Property name="link" type={"DetourLink"} typeHref="#detourlink">
    The resolved link, or `null`. Stays set until `clearLink()` is called.
  </Property>
  <Property name="clearLink" type={"() => void"}>
    Resets `link` to `null`. Call it after navigating, so the same link does not redirect again.
  </Property>
</PropertyList>

## DetourAnalytics

Analytics module exported from the package root. It needs a mounted `DetourProvider`. Without one, each call is dropped and the SDK logs `🔗[Detour:ANALYTICS_WARNING]`.

### Methods

#### `logEvent`

```ts
DetourAnalytics.logEvent(
  eventName: DetourEventNames | `${DetourEventNames}`,
  data?: any,
): void;
```

Records a user action. `eventName` must be one of the predefined [`DetourEventNames`](#detoureventnames), as the enum member or its string value. Custom names are not accepted. `data` takes any metadata, for example `{ itemId: '123', price: 49.99 }`.

#### `logRetention`

```ts
DetourAnalytics.logRetention(retentionEventName: string): void;
```

Records a retention event under any name you choose.

### Automatic events

`DetourProvider` logs an `app_open` retention event once per session, on cold start. Set [`shouldTrackAutomaticEvents: false`](#config-fields) to turn it off.

Universal Link and App Link opens are recorded on the server through the click endpoint, not as client events. See [Click limits](https://detour.swmansion.com/docs/sdk/react-native/sdk-usage#click-limits).

Every API request the SDK sends carries an `X-SDK: react-native/<version>` header, used for diagnostics and SDK-usage analysis.

## Expo Router helper

Import it from the subpath:

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

### Signature

```ts
function createDetourNativeIntentHandler(
  options?: DetourNativeIntentOptions,
): DetourNativeIntentHandler;
```

The returned handler leaves a URL whose host does not match `hosts` unchanged.

### Options

<PropertyList>
  <Property id="fallbackpath" name="fallbackPath" type={"string"} default={"''"}>
    Route returned for a matching URL when resolve mode is off, when resolution fails, or when the click limit is reached. For example `''` for the home screen or `'/welcome'` for onboarding.
  </Property>
  <Property
    id="hosts"
    name="hosts"
    type={"Array<string | RegExp>"}
    default={"[/\\.godetour\\.link$/i]"}
  >
    Host patterns the handler intercepts. Each entry is matched against `url.hostname`:

    - an exact string, for example `go.example.com`
    - a suffix wildcard, for example `*.example.com`
    - a regular expression, for example `/\.example\.org$/i`

    An empty array falls back to the default.

    :::caution[`hosts` replaces the default]
    Passing `hosts` replaces `[/\.godetour\.link$/i]`, it does not add to it. Keep the default pattern next to your [custom domain](https://detour.swmansion.com/docs/platform/advanced/custom-domain). If the custom domain is removed or the paid plan lapses, Detour serves the app's links from `.godetour.link` again, and a build without the pattern ignores them.

    ```ts
    hosts: ["links.yourdomain.com", /\.godetour\.link$/i],
    ```
    :::
  </Property>
  <Property
    id="config"
    name="config"
    type={"DetourNativeIntentResolveConfig"}
    typeHref="#detournativeintentresolveconfig"
  >
    Passing this object turns on **resolve mode**. The handler checks the click against your plan's click limit, resolves short links to their destination, and returns the matching route.

    Without it the handler runs in **intercept mode** and returns `fallbackPath` for every matching URL.

    Over the click limit, the handler returns `fallbackPath` and logs `🔗[Detour:CLICK_LIMIT_ERROR]`. See [Click limits](https://detour.swmansion.com/docs/sdk/react-native/sdk-usage#click-limits).
  </Property>
  <Property
    id="maptoroute"
    name="mapToRoute"
    type={"(value: DetourNativeIntentResolvedValue) => string"}
  >
    Turns a resolved URL into an in-app route. It receives a [`DetourNativeIntentResolvedValue`](#detournativeintentresolvedvalue).

    The default drops the first path segment, the app hash, from web URLs with more than one segment, and converts custom scheme URLs to a path. Pass your own when link destinations do not match your route structure.
  </Property>
</PropertyList>

:::tip[DetourProvider configuration]
In resolve mode, set `linkProcessingMode: 'deferred-only'` on `DetourProvider`, so the provider handles only deferred links and `+native-intent.tsx` handles the rest. See [Configure DetourProvider for native intent](https://detour.swmansion.com/docs/sdk/react-native/sdk-usage#configure-detourprovider-for-native-intent).
:::

## React Navigation adapter

Exported from the package root, for React Navigation's custom linking API. See [React Navigation integration](https://detour.swmansion.com/docs/sdk/react-native/sdk-usage#react-navigation-integration) for a walkthrough.

### `Detour`

```ts
const Detour: {
  getInitialURL: () => Promise<string | undefined>;
  addEventListener: (
    event: 'url',
    listener: (event: DetourUrlEvent) => void,
  ) => DetourUrlSubscription;
};
```

A `Linking`-shaped object for a React Navigation `linking` config. It needs a `DetourProvider` mounted above your `NavigationContainer`.

<PropertyList>
  <Property name="getInitialURL" type={"() => Promise<string | undefined>"}>
    Resolves to the route Detour matched on cold start, or `undefined`. It waits until link processing finishes and returns the URL only once.
  </Property>
  <Property
    name="addEventListener"
    type={"(event, listener) => DetourUrlSubscription"}
    typeHref="#detoururlsubscription"
  >
    Subscribes to routes Detour resolves while the app is running.
  </Property>
</PropertyList>

### `DETOUR_LINKING_PREFIX`

```ts
const DETOUR_LINKING_PREFIX: string; // "detour://"
```

The prefix of the URLs the adapter emits. Add it to `prefixes` in your `linking` config. Each URL carries `fromDeepLink=true` and a `linkType` query parameter.

## Types

### LinkProcessingMode

```ts
type LinkProcessingMode = 'all' | 'web-only' | 'deferred-only';
```

| Value             | Processes                                                                       |
| ----------------- | ------------------------------------------------------------------------------- |
| `'all'` (default) | Deferred links, Universal Links and App Links, the initial URL, and custom scheme links |
| `'web-only'`      | The same as `'all'`, without custom scheme links                                |
| `'deferred-only'` | Deferred links only. Use it when Expo Router's `+native-intent.tsx` handles the rest |

The package does not export this type by name. Use `Config['linkProcessingMode']` to refer to it.

### LinkType

```ts
type LinkType = 'deferred' | 'verified' | 'scheme';
```

| Value        | How the link arrived                                                   |
| ------------ | ---------------------------------------------------------------------- |
| `'deferred'` | From the Detour API on the first launch after install                  |
| `'verified'` | As a Universal Link or App Link that the OS verified for your app      |
| `'scheme'`   | Through a custom URL scheme, for example `myapp://path`                |

### DetourLink

```ts
type DetourLink = {
  url: string | URL;
  route: string;
  pathname: string;
  params: Record<string, string>;
  type: LinkType;
} | null;
```

<PropertyList>
  <Property name="url" type={"string | URL"}>
    The original URL as a `URL` object, or the raw string if it could not be parsed.
  </Property>
  <Property name="route" type={"string"}>
    In-app route with the query string, for example `/details?utm=1`. For web and deferred links, the first path segment, the app hash, is removed.
  </Property>
  <Property name="pathname" type={"string"}>
    The route without the query string, for example `/details`.
  </Property>
  <Property name="params" type={"Record<string, string>"}>
    Query parameters. All values are strings.
  </Property>
  <Property name="type" type={"LinkType"} typeHref="#linktype">
    How the link arrived in the app.
  </Property>
</PropertyList>

### DetourContextType

```ts
type DetourContextType = {
  isLinkProcessed: boolean;
  link: DetourLink;
  clearLink: () => void;
};
```

The value returned by `useDetourContext`. See [Returned object](#returned-object) for each field.

### DetourStorage

```ts
interface DetourStorage {
  getItem(key: string): Promise<string | null> | string | null;
  setItem(key: string, value: string): Promise<void> | void;
  removeItem?(key: string): Promise<void> | void;
}
```

Interface for a custom storage adapter. Methods can be synchronous or asynchronous. The SDK stores a first-launch flag, which limits deferred matching to the first launch, and a device ID for analytics.

To use MMKV, Expo SecureStore or another store, see [Custom Storage](https://detour.swmansion.com/docs/sdk/react-native/custom-storage).

### DetourUrlEvent

```ts
type DetourUrlEvent = {
  url: string;
};
```

Passed to the [`Detour.addEventListener`](#detour) listener. `url` is the resolved route, prefixed with [`DETOUR_LINKING_PREFIX`](#detour_linking_prefix).

### DetourUrlSubscription

```ts
type DetourUrlSubscription = {
  remove: () => void;
};
```

Returned by [`Detour.addEventListener`](#detour). Call `remove()` to detach the listener, usually in the cleanup of your `linking.subscribe`.

### DetourNativeIntentArgs

```ts
type DetourNativeIntentArgs = {
  path: string;
  initial: boolean;
};
```

<PropertyList>
  <Property name="path" type={"string"}>
    The incoming system path or URL from Expo Router.
  </Property>
  <Property name="initial" type={"boolean"}>
    `true` for the URL that launched the app, `false` for links received while it runs.
  </Property>
</PropertyList>

### DetourNativeIntentHandler

```ts
type DetourNativeIntentHandler = (
  args: DetourNativeIntentArgs,
) => string | Promise<string>;
```

The function `createDetourNativeIntentHandler` returns. Export it as `redirectSystemPath` from `+native-intent.tsx`.

### DetourNativeIntentResolveConfig

```ts
type DetourNativeIntentResolveConfig = {
  apiKey: string;
  appID: string;
  timeoutMs?: number;
  onResolveError?: (error: unknown, context: DetourNativeIntentArgs) => void;
};
```

<PropertyList>
  <Property name="apiKey" type={"string"} required>
    Publishable API key, the same value as in the `DetourProvider` config.
  </Property>
  <Property name="appID" type={"string"} required>
    App identifier, the same value as in the `DetourProvider` config.
  </Property>
  <Property name="timeoutMs" type={"number"} default={"1200"}>
    How long to wait for short-link resolution, in milliseconds. On timeout the handler returns `fallbackPath`.
  </Property>
  <Property name="onResolveError" type={"(error, context) => void"}>
    Called when short-link resolution fails or times out, or when `mapToRoute` throws. Use it for logging.
  </Property>
</PropertyList>

### DetourNativeIntentOptions

```ts
type DetourNativeIntentOptions = {
  fallbackPath?: string;
  hosts?: Array<string | RegExp>;
  config?: DetourNativeIntentResolveConfig;
  mapToRoute?: (value: DetourNativeIntentResolvedValue) => string;
};
```

See [Options](#options) for each field.

### DetourNativeIntentResolvedValue

```ts
type DetourNativeIntentResolvedValue = {
  originalPath: string;
  initial: boolean;
  resolvedUrl: URL;
};
```

<PropertyList>
  <Property name="originalPath" type={"string"}>
    The incoming system path, before resolution.
  </Property>
  <Property name="initial" type={"boolean"}>
    `true` for the URL that launched the app.
  </Property>
  <Property name="resolvedUrl" type={"URL"}>
    The destination URL after short-link resolution.
  </Property>
</PropertyList>

### DetourEventNames

| Category    | Event name                   | String value                    |
| :---------- | :--------------------------- | :------------------------------ |
| **General** | `Login`                      | `login`                         |
|             | `Search`                     | `search`                        |
|             | `Share`                      | `share`                         |
|             | `SignUp`                     | `sign_up`                       |
|             | `TutorialBegin`              | `tutorial_begin`                |
|             | `TutorialComplete`           | `tutorial_complete`             |
|             | `ReEngage`                   | `re_engage`                     |
|             | `Invite`                     | `invite`                        |
|             | `OpenedFromPushNotification` | `opened_from_push_notification` |
| **Sales**   | `AddPaymentInfo`             | `add_payment_info`              |
|             | `AddShippingInfo`            | `add_shipping_info`             |
|             | `AddToCart`                  | `add_to_cart`                   |
|             | `RemoveFromCart`             | `remove_from_cart`              |
|             | `Refund`                     | `refund`                        |
|             | `ViewItem`                   | `view_item`                     |
|             | `BeginCheckout`              | `begin_checkout`                |
|             | `Purchase`                   | `purchase`                      |
|             | `AdImpression`               | `ad_impression`                 |