Skip to main content
Version: 0.6.x

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

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 for isLinkProcessed before 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.

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',
});
warning

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