API Reference
DetourProvider
DetourProvider is the top-level React component that initializes the deferred-linking session and exposes context for the rest of your app.
Signature
export function DetourProvider(props: {
config: Config;
children: React.ReactNode;
}): JSX.Element;
Props
| Property | Type | Required | Description |
|---|---|---|---|
config | Config | Yes | Configuration object containing authentication and behavioral flags. See Config type for details. |
children | React.ReactNode | Yes | Your app's component tree. |
Config fields
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
API_KEY | string | Yes | - | The publishable API key from your Detour dashboard |
appID | string | Yes | - | App identifier issued by the platform |
shouldUseClipboard | boolean | No | true | Whether to check clipboard for deferred links. iOS-only |
storage | DetourStorage | No | AsyncStorage | Storage adapter for detecting first run. Should implement interface DetourStorage |
Runtime behavior
On mount, DetourProvider initializes the deferred-linking flow. Internally it:
- Ensures single-run matching — Uses persisted state (
AsyncStorage) and an in-memory guard so matching runs only once per fresh install/first entrance - Reads Android install referrer — When available, performs deterministic matching using the
clickId - Builds probabilistic fingerprint — If no referrer is found, collects device model, OS version, screen metrics, locale, timezone, user agent, timestamp, and optional clipboard value
- Posts to match endpoint — Sends fingerprint to
POST /api/link/match-link - Updates context state — Provides result via
useDetourContext()
The provider performs network I/O and requires valid API_KEY and appID. If these are missing or invalid, matching will fail.
Key runtime guarantees
- Single-run: The SDK is designed to attempt matching only once per install/first-open; it will not call the API repeatedly on every app open.
- First-open semantics: The provider checks persisted state (AsyncStorage) to determine whether the device has already been processed; this avoids duplicate attribution attempts.
- Clipboard: If shouldUseClipboard is true the provider checks the clipboard and includes pastedLink in the fingerprint. This behavior applies exclusively to iOS and may trigger the system's paste permission prompt.
- Error handling: If the match API returns an error or network calls fail, provider will set deferredLinkProcessed = true and deferredLink = null so your app can continue. The SDK logs errors to the console for debugging.
Example
import { DetourProvider } from "@swmansion/react-native-detour";
import { NavigationContainer } from "@react-navigation/native";
function App() {
return (
<DetourProvider
config={{
API_KEY: "your-api-key",
appID: "your-app-id",
shouldUseClipboard: true,
}}
>
<NavigationContainer>{/* Your app navigation */}</NavigationContainer>
</DetourProvider>
);
}
useDetourContext()
Signature
export function useDetourContext(): DetourContextType;
Returns
DetourContextType object with the following properties:
| Property | Type | Description |
|---|---|---|
deferredLinkProcessed | boolean | true when the SDK has finished the deferred-link and universal/app link check (either success or failure). While false, your app should wait if you need to route the user based on a link. |
deferredLink | string | URL | null | The raw link returned by the platform if matched. Can be a full URL string (e.g., https://yourorg.godetour.link/app-hash/promo) or a URL object. It can be deferred link, universal/app link or uri-scheme deep link. Returns null if no match was found or an error occurred. |
route | string | null | A normalized path extracted from the deferred link, universal/app link or uri-scheme deep link. Examples: "/promo/123?utm=1" (path with query string) or null if nothing matched. |
Example
import { useDetourContext } from "@swmansion/react-native-detour";
import { useEffect } from "react";
import { useNavigation } from "@react-navigation/native";
function HomeScreen() {
const { deferredLinkProcessed, deferredLink, route } = useDetourContext();
const navigation = useNavigation();
useEffect(() => {
if (deferredLinkProcessed && route) {
// Navigate based on the deferred link route
console.log("Deferred link detected:", deferredLink);
console.log("Route:", route);
// Example: navigate to a specific screen
if (route.startsWith("/promo")) {
navigation.navigate("Promo", { url: deferredLink });
}
}
}, [deferredLinkProcessed, route, deferredLink, navigation]);
if (!deferredLinkProcessed) {
return <LoadingScreen />;
}
return <YourHomeScreen />;
}
Types
Config
export type Config = {
/**
* Your application ID from the Detour dashboard.
*/
appID: string;
/**
* Your API key from the Detour dashboard.
*/
API_KEY: string;
/**
* Optional (only for iOS): A flag to determine if the provider should check the clipboard for a deferred link.
* When true, it displays permission alert to user.
* Defaults to true if not provided.
*/
shouldUseClipboard?: boolean;
/**
* Optional: A custom storage adapter. Defaults to AsyncStorage if not provided.
*/
storage?: DetourStorage;
};
DetourContextType
export type DetourContextType = {
/**
* Boolean indicating if the deferred link or Universal/App Link has been processed.
* This is useful for conditionally rendering UI components.
*/
deferredLinkProcessed: boolean;
/**
* The deferred link or Universal/App Link. This can be a string or a URL object, or null if no link was found.
*/
deferredLink: string | URL | null;
/**
* The detected route based on the deferred link or Universal/App Link, or null if no route was detected.
*/
route: string | null;
};
DetourStorage
Your storage adapter should implement the following methods:
export interface DetourStorage {
getItem(key: string): Promise<string | null> | string | null;
setItem(key: string, value: string): Promise<void> | void;
removeItem?(key: string): Promise<void> | void;
}