Usage
Initialize provider in app root
Section titled “Initialize provider in app root”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> );}If you want complete, runnable integrations for each navigation style, go to Examples.
Handle resolved links with useDetourContext()
Section titled “Handle resolved links with useDetourContext()”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
Section titled “link structure”useDetourContext() returns a link object (or null):
-
link.route -
Full in-app route with query string (e.g.
/details?utm=1). -
link.pathname -
Path without query (e.g.
/details). -
link.params -
Parsed query params record.
-
link.url -
Original URL or raw value.
-
link.type
Use clearLink() after handling navigation to avoid repeated redirects.
Choose linkProcessingMode
Section titled “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
Section titled “Expo Router integration”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
Section titled “Basic setup”Create a +native-intent.tsx file in your app directory (e.g. src/app/+native-intent.tsx):
import { createDetourNativeIntentHandler } from "@swmansion/react-native-detour/expo-router";
export const redirectSystemPath = createDetourNativeIntentHandler();Resolve mode
Section titled “Resolve mode”To resolve Detour short links to their full destination URLs at the router level, pass a config object:
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 for the full list of options (custom hosts, fallback path, timeout, route mapping, etc.).
Configure DetourProvider for native intent
Section titled “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:
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
Section titled “Advanced examples”The SDK repository includes examples for common native intent scenarios:
-
expo-router-native-intent— Full resolve mode setup with a custommapToRoutefunction 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.
Alternative: catch-all route without +native-intent.tsx
Section titled “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:
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
Section titled “Analytics module”DetourAnalytics emits events that are sent by the active DetourProvider.
import { DetourAnalytics, DetourEventNames,} from "@swmansion/react-native-detour";
DetourAnalytics.logEvent(DetourEventNames.Purchase, { item: "subscription_premium", currency: "USD",});
DetourAnalytics.logRetention("home_screen_opened");Automatic events
Section titled “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.