# API Reference

## DetourProvider

Top-level React component that initializes the Detour SDK. It manages the full link processing lifecycle: deferred link matching, Universal/App Link listening, initial URL handling, and analytics event transport.

On mount, the provider:

1. Checks for an initial URL that launched the app (Universal/App Link on cold start)
2. If no initial link is found, queries the Detour API for a deferred link (first install only)
3. Attaches a runtime listener for Universal/App Links received while the app is running
4. Subscribes to analytics events and forwards them to the Detour backend

Use exactly one `DetourProvider` at the root of your app tree. Multiple providers are detected at runtime and will cause analytics events to be dropped.

### Signature

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

### Config fields

<PropertyList>
  <Property name="appID" type={"string"} required>
    Unique app identifier from the Detour Dashboard. Used to authenticate API requests and route links to the correct app.
  </Property>
  <Property name="apiKey" type={"string"} required>
    Publishable API key from the Detour Dashboard. Used as a Bearer token for all API calls (deferred link matching, short-link resolution, analytics)
  </Property>
  <Property name="shouldUseClipboard" type={"boolean"} default={"true"}>
    iOS only. When `true`, the SDK reads the device clipboard as part of probabilistic fingerprinting for deferred link matching. Set to `false` if your app lacks clipboard permissions or you want to skip clipboard access.
  </Property>
  <Property name="linkProcessingMode" type={"LinkProcessingMode"} typeHref="#linkprocessingmode" default={"'all'"}>
    Controls which link sources the SDK processes. See [LinkProcessingMode](#linkprocessingmode) for details on each value.
  </Property>
  <Property name="storage" type={"DetourStorage"} typeHref="#detourstorage" default={"AsyncStorage"}>
    Custom storage adapter for SDK persistence. The SDK stores a first-entrance flag (for deferred link matching) and a device ID (for analytics). Defaults to `@react-native-async-storage/async-storage` if installed.
  </Property>
</PropertyList>

## useDetourContext

Hook that returns the current link processing state and resolved link payload from the nearest `DetourProvider`. Throws an error if called outside of a `DetourProvider` tree.

### Signature

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

### Returned object

<PropertyList>
  <Property name="isLinkProcessed" type={"boolean"}>
    `true` once the SDK has finished all link detection attempts, regardless of whether a link was found. Use this to conditionally show a loading/splash screen during cold start.
  </Property>
  <Property name="link" type={"DetourLink"} typeHref="#detourlink">
    Resolved link data, or `null` if no link was detected. Persists until `clearLink()` is called.
  </Property>
  <Property name="clearLink" type={"() => void"}>
    Resets `link` to `null`. Call after handling navigation to prevent repeated redirects.
  </Property>
</PropertyList>

## DetourAnalytics

Analytics module exported from the package root. Requires an active `DetourProvider` in the component tree. Events are silently dropped if no provider is mounted.

### Methods

#### `logEvent`

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

Records a user action or custom event and sends it to the Detour backend. Pass one of the predefined [`DetourEventNames`](#detoureventnames) or a custom string. The optional `data` parameter accepts arbitrary metadata (e.g. `{ itemId: '123', price: 49.99 }`).

#### `logRetention`

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

Records a retention/lifecycle event for user engagement tracking. The SDK automatically logs an `app_open` retention event when `DetourProvider` mounts for the first time in a session.

## Expo Router helper

Available under subpath import:

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

### Signature

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

### Options

#### `fallbackPath`

| | |
| --- | --- |
| **Type** | `string` |
| **Default** | `''` |

The in-app route path returned when an incoming URL matches a Detour host but resolve mode is not enabled or resolution fails. Set this to the route you want users to land on as a safe default, for example `''` for the home screen or `'/welcome'` for an onboarding screen.

#### `hosts`

| | |
| --- | --- |
| **Type** | `Array<string \| RegExp>` |
| **Default** | `[/\.godetour\.link$/i]` |

Host-matching patterns that determine which incoming URLs the handler should process. Only URLs whose hostname matches at least one entry are intercepted. All other URLs pass through unchanged to Expo Router's default routing.

Use plain strings for exact domain matches, strings beginning with `*.` for suffix wildcards (`*.example.com` matches any subdomain of `example.com`), or regular expressions for anything else. The default pattern matches any subdomain of `godetour.link` (e.g. `abc123.godetour.link`).

:::caution[`hosts` replaces the default]
The default value is `[/\.godetour\.link$/i]`. Passing `hosts` replaces that value, it does not add to it. An app that passes only its [custom domain](https://detour.swmansion.com/docs/platform/advanced/custom-domain) stops matching `.godetour.link` links. Keep the default pattern in the list as well: if the custom domain is removed, or the paid plan lapses, Detour serves that app's links from `.godetour.link` again, and a build that dropped the pattern ignores them.

```ts
hosts: ["links.yourdomain.com", /\.godetour\.link$/i],
```
:::

#### `config`

| | |
| --- | --- |
| **Type** | `DetourNativeIntentResolveConfig` |
| **Default** | `undefined` |

Providing this object **enables resolve mode**. In resolve mode the handler resolves Detour short links (e.g. `https://abc123.godetour.link/xyz`) to their full destination URLs before routing to the matched in-app screen. Without `config`, the handler operates in **intercept mode**, which matches Detour hosts and returns `fallbackPath` without resolving the link.

<PropertyList>
  <Property name="apiKey" type={"string"} required>
    Publishable API key from the Detour Dashboard (same value used in `DetourProvider` config)
  </Property>
  <Property name="appID" type={"string"} required>
    App identifier from the Detour Dashboard (same value used in `DetourProvider` config)
  </Property>
  <Property name="timeoutMs" type={"number"} default={"1200"}>
    Maximum time in milliseconds to wait for short-link resolution. If exceeded, `fallbackPath` is returned.
  </Property>
  <Property name="onResolveError" type={"(error, context) => void"}>
    Callback invoked when resolution fails (e.g. network error, invalid link). Useful for logging or error reporting.
  </Property>
</PropertyList>

:::tip[DetourProvider configuration]
When using resolve mode, set `linkProcessingMode: 'deferred-only'` in your `DetourProvider` config so the provider only handles deferred links while `+native-intent.tsx` handles Universal Links and App Links. See [Configure DetourProvider for native intent](https://detour.swmansion.com/docs/sdk/react-native/sdk-usage#configure-detourprovider-for-native-intent).
:::

#### `mapToRoute`

| | |
| --- | --- |
| **Type** | `(value: DetourNativeIntentResolvedValue) => string` |
| **Default** | Built-in mapper that strips the first path segment (app hash) from multi-segment web URLs |

Custom function that transforms a resolved URL into an in-app route string. The function receives a `DetourNativeIntentResolvedValue` object containing the `originalPath`, `initial` flag, and the `resolvedUrl`.

Use this when your Detour link destinations do not map directly to your app's route structure, for example if your link URLs contain a prefix segment that does not correspond to an in-app screen.

## Types

### LinkProcessingMode

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

Controls which link sources `DetourProvider` processes:

| Value | Behavior |
| --- | --- |
| `'all'` (default) | Processes all link sources: deferred links from the Detour API, runtime Universal Links (iOS) / App Links (Android), the initial URL that launched the app, and custom scheme deep links (e.g. `myapp://path`) |
| `'web-only'` | Same as `'all'` but filters out custom scheme links. Only HTTP/HTTPS URLs (Universal Links and App Links) and deferred links are processed |
| `'deferred-only'` | Only processes deferred links obtained from the Detour API. Disables the runtime link listener and skips the initial URL check. Recommended when Expo Router's `+native-intent.tsx` already handles runtime and initial URLs |

### LinkType

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

Describes how the link arrived in the app:

| Value | Meaning |
| --- | --- |
| `'deferred'` | The link was obtained from the Detour deferred-link API. This happens when a user who does not have the app installed clicks a Detour link, installs the app, and opens it. The SDK retrieves the original link from the backend on first launch |
| `'verified'` | The link arrived as a Universal Link (iOS) or App Link (Android), an HTTP/HTTPS URL that the OS verified belongs to your app and delivered directly to it |
| `'scheme'` | The link arrived via a custom URL scheme (e.g. `myapp://path`). These are non-HTTP URLs that the OS routes to your app based on the registered scheme |

### DetourLink

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

Resolved link data, or `null` if no link was detected.

<PropertyList>
  <Property name="url" type={"string | URL"}>
    Original URL as parsed by the `URL` constructor, or raw string if parsing failed.
  </Property>
  <Property name="route" type={"string"}>
    Full in-app route including query string (e.g. `/details?utm=1`). For web URLs, the first path segment (app hash) is stripped.
  </Property>
  <Property name="pathname" type={"string"}>
    Path without query string (e.g. `/details`). For web URLs, the first path segment (app hash) is stripped.
  </Property>
  <Property name="params" type={"Record<string, string>"}>
    Query string parameters as a key-value record. 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;
};
```

Shape of the value returned by [`useDetourContext`](#usedetourcontext).

<PropertyList>
  <Property name="isLinkProcessed" type={"boolean"}>
    `true` once the SDK has finished all link detection attempts. `false` during cold start processing.
  </Property>
  <Property name="link" type={"DetourLink"} typeHref="#detourlink">
    Resolved link data or `null`. Persists until `clearLink()` is called.
  </Property>
  <Property name="clearLink" type={"() => void"}>
    Resets `link` to `null`. Call after navigating to prevent repeated redirects.
  </Property>
</PropertyList>

### 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 custom storage adapters. The SDK persists a first-entrance flag (used for deferred link matching, which only runs on first app install) and a stable device ID (used for analytics). Methods can be synchronous or asynchronous.

By default, `@react-native-async-storage/async-storage` is used. Provide a custom adapter if you use a different storage solution (e.g. MMKV, Expo SecureStore). See [Custom Storage](https://detour.swmansion.com/docs/sdk/react-native/custom-storage) for examples.

### DetourNativeIntentArgs

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

Arguments passed by Expo Router to the `redirectSystemPath` handler.

<PropertyList>
  <Property name="path" type={"string"}>
    Incoming system path or URL from Expo Router.
  </Property>
  <Property name="initial" type={"boolean"}>
    `true` when this is the initial URL used to launch the app (cold start), `false` for runtime link events.
  </Property>
</PropertyList>

### DetourNativeIntentHandler

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

Function signature returned by `createDetourNativeIntentHandler`. Takes the incoming path and returns the resolved in-app route (synchronously or as a promise).

### DetourNativeIntentResolveConfig

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

Configuration that enables resolve mode in `createDetourNativeIntentHandler`. See [`config` option](#config) for field descriptions.

### DetourNativeIntentOptions

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

Options for `createDetourNativeIntentHandler`. See [Options](#options) for detailed field descriptions.

### DetourNativeIntentResolvedValue

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

Object passed to the `mapToRoute` callback after short-link resolution.

<PropertyList>
  <Property name="originalPath" type={"string"}>
    The original incoming system path before resolution.
  </Property>
  <Property name="initial" type={"boolean"}>
    `true` if this is the initial URL that launched the app.
  </Property>
  <Property name="resolvedUrl" type={"URL"}>
    The resolved 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` |