# Deep Linking

This guide covers deep linking into a chat app, extracting a channel ID from the URL, and opening the corresponding conversation.

## Best Practices

- Define a single URL pattern and document it for both web and app.
- Validate channel IDs before navigating to avoid empty screens.
- Handle both cold start (`getInitialURL`) and foreground events.
- Use App Links/Universal Links in production for verified routing.
- Keep deep link parsing isolated so it’s easy to test.

### Step 1 - Native Setup

<admonition type="note">

Prerequisite: an app with the Stream Chat React Native SDK integrated.

</admonition>

<tabs>

<tabs-item value="android" label="Android">

For Android deep linking, follow [this guide](https://developer.android.com/training/app-links/deep-linking#adding-filters).

#### Creating Intent Filters

Add an intent filter to your `AndroidManifest.xml` at `/android/app/src/main/AndroidManifest.xml`.

- `action` - Specify ACTION_VIEW so the intent filter can be reached from Google Search.

```xml
<action android:name="android.intent.action.VIEW" />
```

- `data` - Add one or more `<data>` tags. Each represents a URI format and must include `android:scheme`.

```xml
<data android:scheme="http" />
<data android:scheme="https" />
<!-- The URL here must exclude the scheme -->
<data android:host="`YOUR URL HERE`" />
```

- `category` - Include `DEFAULT` and `BROWSABLE` so links from a browser resolve to your app.

```xml
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
```

Combined:

```xml
<intent-filter android:autoVerify="true">
    <action android:name="android.intent.action.VIEW" />
    <category android:name="android.intent.category.DEFAULT" />
    <category android:name="android.intent.category.BROWSABLE" />
    <data android:scheme="http" />
    <data android:scheme="https" />
    <!-- Example: "stream-calls-dogfood.vercel.app” -->
    <data android:host="`YOUR URL HERE`" />
</intent-filter>
```

#### Adding Asset Links

Android App Links open your app directly from website URLs. They use the [Digital Asset Links API](https://developers.google.com/digital-asset-links) to verify domain ownership and automatically route matching URLs to your app.

To verify that you own both your app and the website URLs, complete the following steps:

- Add intent filters with the `autoVerify` attribute (as above).

- [Declare the association](https://developer.android.com/training/app-links/verify-android-applinks#web-assoc) by hosting a Digital Asset Links JSON file at:

```text
https://domain.name/.well-known/assetlinks.json
```

Use [this tool](https://developers.google.com/digital-asset-links/tools/generator) to generate `assetlink.json`. Enter the hosting site name, app package name, and package fingerprint (SHA256).

- Hosting site name is the URL of the website which we will use for deep linking in our app.
- App package name can be easily found in the first line of your `MainActivity.java` file as a value to `package`.
- To get your app package fingerprint (SHA256), follow [this guide](https://developers.google.com/android/guides/client-auth).

</tabs-item>

<tabs-item value="ios" label="iOS">

#### Adding deep linking support in AppDelegate

To add deep linking support on iOS:

1. Link `RCTLinking` to handle incoming links. In `AppDelegate.m` or `AppDelegate.mm`, add:

```objc
#import <React/RCTLinkingManager.h>

- (BOOL)application:(UIApplication *)application
   openURL:(NSURL *)url
   options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options
{
  return [RCTLinkingManager application:application openURL:url options:options];
}

- (BOOL)application:(UIApplication *)application continueUserActivity:(nonnull NSUserActivity *)userActivity
 restorationHandler:(nonnull void (^)(NSArray<id<UIUserActivityRestoring>> * _Nullable))restorationHandler
{
 return [RCTLinkingManager application:application
                  continueUserActivity:userActivity
                    restorationHandler:restorationHandler];
}
```

#### Setting up a URL scheme

To add a URI scheme, open `YOUR_APP_NAME/ios/app-name.xcworkspace` in Xcode. Select the project, go to **Info** > `URL types`, click `+`, then add:

1. Your app's bundle id.
2. A scheme name that acts as the URL prefix.
3. Leave the role as `Editor`.

![Xcode Info URL Types](@chat-sdk/react-native/v8/_assets/guides/deeplinking/xcode-info-url-types.png)

#### Setting up Universal schemes

<admonition type="note">

If you use [Universal Links](https://developer.apple.com/ios/universal-links/), add the following code as well.

</admonition>

```objc
- (BOOL)application:(UIApplication *)application continueUserActivity:(nonnull NSUserActivity *)userActivity
 restorationHandler:(nonnull void (^)(NSArray<id<UIUserActivityRestoring>> * _Nullable))restorationHandler
{
 return [RCTLinkingManager application:application
                  continueUserActivity:userActivity
                    restorationHandler:restorationHandler];
}
```

##### Adding Associated Domains Entitlement

In Xcode, add the Associated Domains entitlement under Signing & Capabilities.

![Xcode Signing Capabilities](@chat-sdk/react-native/v8/_assets/guides/deeplinking/xcode-signing-capabilitites.png)

Click the `+` under Signing & Capabilities, search for `Associated Domains`, and add it.

In the new field, click `+` and insert `applinks:` followed by your domain.

_The `applinks:` prefix tells Xcode this domain is used for Universal Links._

Once you complete this step, a `.entitlements` file is created in `ios/YOUR_APP_NAME`.

Now add the AASA (Apple App Site Association) file to your web project:

- Create `apple-app-site-association` in the `.well-known` directory so it’s served at `https://domain.name/.well-known/apple-app-site-association`.

- Now, Paste the following snippet:

```json
{
  "applinks": {
    "apps": [],
    "details": [
      {
        "appID": ["<TeamID>.com.example.myapp"],
        "paths": ["*"]
      }
    ]
  }
}
```

Notes:

- `appID` expects your Team ID (from the [Membership page](https://developer.apple.com/account/#/membership)) plus your Bundle ID.
- The `paths` array lists supported URLs; use `*` for wildcards.
- Leave `apps` empty.

That’s all you need for iOS setup.

</tabs-item>

</tabs>

### Step 2 - Using the `Linking` API

After Android and iOS setup, use the React Native [Linking](https://reactnative.dev/docs/linking) API to handle links and navigate.

If the app isn’t open, it launches and the URL is provided as the initial URL.

Use `getInitialURL()` to read the initial URL (it returns a Promise).

Parse the URL and act accordingly.

If the app is already open, a `url` event fires. Use `addEventListener('url', callback)` to receive `callback({ url })`.

Example:

```tsx title="App.tsx"
const App = () => {
  useEffect(() => {
    const parseAndSetChannelID = (url: string | null) => {
      const matchResponse = url?.match(`YOUR REGEX HERE`); // To match the paths and handle them accordingly
      if (matchResponse?.length) {
        // Your custom setup here.
      }
    };
    const { remove } = Linking.addEventListener("url", ({ url }) => {
      parseAndSetChannelID(url);
    });
    const configure = async () => {
      const url = await Linking.getInitialURL();
      parseAndSetChannelID(url);
    };
    configure();
    return remove;
  }, []);
};
```

Extract the channel ID from the URL, open the conversation, and navigate to the appropriate screen.


---

This page was last updated at 2026-04-17T17:33:45.625Z.

For the most recent version of this documentation, visit [https://getstream.io/chat/docs/sdk/react-native/v8/guides/deeplinking/](https://getstream.io/chat/docs/sdk/react-native/v8/guides/deeplinking/).