Skip to content
Documentation menu

Set up your app

React Native and Expo

Set up DL2App deep links in a React Native or Expo app: the config plugin, configure, and one listener for direct and deferred links.

For React Native 0.74 or newer, with or without Expo (SDK 51 or newer). The native code is a plain React Native module, so a React Native app does not need Expo or Expo Modules. With Expo you need a development build: Expo Go does not work, because the SDK has native code and your app needs its own associated domains.

Install (Expo)

npx expo install @dl2app/react-native
app.json
{
  "expo": {
    "plugins": [
      ["@dl2app/react-native", { "subdomain": "myapp", "domains": ["go.myapp.com"] }]
    ]
  }
}

The plugin adds the associated domains on iOS and the verified intent filters on Android for myapp.dl2.app, myapp-alt.dl2.app and your custom domains. It keeps entries you already have. Rebuild the native app afterwards (npx expo prebuild --clean, or a new EAS build).

Install (React Native without Expo)

npm install @dl2app/react-native
cd ios && pod install

Autolinking registers the native module on both platforms; there is nothing to add to MainApplication or the Podfile. Then:

  1. Add the hosts by hand as described for iOS (Associated Domains) and Android (the intent filter in the manifest).
  2. On iOS, pass incoming links to React Native. The React Native template does not do this for you.
  3. Rebuild the app. A Metro reload is not enough after adding native code.
AppDelegate.swift
import React

// Inside your AppDelegate class. Write "override func" if it subclasses RCTAppDelegate.
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey: Any] = [:]) -> Bool {
  return RCTLinkingManager.application(app, open: url, options: options)
}

func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
  return RCTLinkingManager.application(application, continue: userActivity, restorationHandler: restorationHandler)
}

Use

App.tsx
import DL2 from "@dl2app/react-native";

// Once, as early as possible, outside any component.
DL2.configure({
  publishableKey: "pk_live_xxx",
  linkDomains: ["myapp.dl2.app", "myapp-alt.dl2.app", "go.myapp.com"],
});

// One listener for direct links and for the deferred link after an install.
const unsubscribe = DL2.onLink((event) => {
  navigation.navigate(event.path, event.data);
});

With Expo Router, also add app/+native-intent.ts so the router does not try to route the short link itself.

Also available

  • DL2.getInitialLink(): the link that opened the app, once the first-launch check has finished.
  • DL2.track(name, { value, currency, props }): report an in-app event against the link that brought the user.
  • DL2.createLink({ path, data }): make a share link from inside the app, if the project allows it.
  • deferred.useClipboard: opt in to the iOS clipboard hand-off.

What the SDK does for you

  • Delivers one event for all three cases: a link that cold-starts the app, a link while it is running, and a deferred link on first launch.
  • Queues links that arrive before your listener is registered, so a cold-start link is never lost.
  • Falls back to the URL’s own path and query if our API cannot be reached within 3 seconds, so the app still navigates.
  • Never throws into your app: errors go to an onError callback.
  • Reads no advertising identifier. See Privacy and App Store disclosure.
React Native and Expo · Docs · DL2App