SDK Usage
Initialize provider in root of your app
import { DetourProvider, type Config } from '@swmansion/react-native-detour';
const config: Config = {
API_KEY: '<REPLACE_WITH_YOUR_API_KEY>',
appID: '<REPLACE_WITH_APP_ID_FROM_PLATFORM>',
shouldUseClipboard: true,
};
export default function RootLayout() {
return (
<DetourProvider config={config}>
<RootNavigator />
</DetourProvider>
);
}
Keep your API_KEY and appID in .env
Links module
Use values from context (Expo Router)
SDK exposes useDetourContext() hook that returns object containing information about link and processing status. Our recommendation is to use the hook before you application renders navigation container.
The SDK only looks for a deferred link during the application's first launch after installation. Subsequent launches should be handled by Universal Links for iOS and App Links for Android. Deep links based on uri-scheme are also supported.
import { useDetourContext } from '@swmansion/react-native-detour';
import * as SplashScreen from 'expo-splash-screen';
import { Stack, usePathname, useRouter } from 'expo-router';
SplashScreen.preventAutoHideAsync();
const normalizePath = (route: string) => route.split('?')[0] || '/';
export function RootNavigator() {
const { isLinkProcessed, linkRoute, clearLink } = useDetourContext();
const pathname = usePathname();
const router = useRouter();
useEffect(() => {
if (isLinkProcessed) {
SplashScreen.hide();
}
}, [isLinkProcessed]);
useEffect(() => {
if (!isLinkProcessed || !linkRoute) return;
if (pathname !== normalizePath(linkRoute)) {
router.replace(linkRoute);
return;
}
clearLink(); // avoid redirecting again when returning to this screen
}, [clearLink, isLinkProcessed, linkRoute, pathname, router]);
if (!isLinkProcessed) {
return null;
}
return <Stack />;
}
linkRoute format
linkRoute is a ready-to-use path (including query string if present).
Example:
URL: https://example-organization.godetour.link/Ar8UqUjGzG/segment1?param1=value1
route: /segment1?param1=value1
Short links
If the incoming link path has a single segment (for example
https://example-organization.godetour.link/Ar8UqUjGzG), the SDK resolves it
to the full link before computing linkRoute.
Custom schemes
For custom scheme links, the route is computed from the host + pathname + query.
Example: myapp://promo/123?utm=1 → /promo/123?utm=1.
Implementation & lifecycle details
- On first app launch after install, the SDK checks whether this is the first entrance and attempts deferred matching once per session.
- If the app is opened via a Universal/App Link on first launch, the SDK handles that link immediately and skips deferred matching.
useDetourContext()exposes the final state; wait forisLinkProcessedbefore routing.- Treat matching as asynchronous; show a splash/loading state if you need a seamless UX.
- Clipboard matching (iOS) can be controlled via
Config.shouldUseClipboard. - After handling a route, call
clearLink()to prevent repeated redirects. - On subsequent launches the SDK checks only for Universal/App Links and processes them.
Universal and App Links with Expo Router
Expo Router handles Universal/App Links on its own and may redirect to a route before the SDK finishes processing the link. The detected route can include the hash fragment Detour uses for link identification, so either match such routes in your navigation or add a catch-all.
Links resolve asynchronously, so without a catch-all Expo Router may show Not Found route for unknown paths while Detour resolves the final destination. Use a catch-all route to keep the user on a loading screen until Detour provides linkRoute:
// app/[...link].tsx
import { useDetourContext } from '@swmansion/react-native-detour';
import { useEffect } from 'react';
import { useRouter } from 'expo-router';
export default function CatchAllRoute() {
const { isLinkProcessed, linkRoute } = useDetourContext();
const router = useRouter();
useEffect(() => {
if (!isLinkProcessed) return;
if (linkRoute) {
router.replace(linkRoute);
} else {
router.replace('/');
}
}, [isLinkProcessed, linkRoute, router]);
return null;
}
This keeps the UX consistent and avoids a flash of the Not Found screen.
Analytics module
You can log specific user behaviors using the DetourAnalytics module. This allows you to
track the user journey through your conversion funnel.
Events are emitted via a global internal system and handled by the DetourProvider.
Example usage
import { DetourAnalytics } from '@software-mansion-labs/react-native-detour';
// Simple event logging
DetourAnalytics.logEvent("login");
// Event logging with custom metadata
DetourAnalytics.logEvent('purchase', {
item: 'subscription_premium',
currency: 'USD',
});
To ensure accurate event tracking and avoid duplicate logs, make sure your application is wrapped in exactly one DetourProvider.
Check the list of defined events here