Deep linking in React Native

Introduction

Deep linking and Universal links are used to make the user experience more smooth. It helps to gather more loyal users. Also used to run campaigns and promotions within your application. After users discover your application and install it, deep linking can be used as a perfect tool to retain newly acquired users in your app

Deep links are used to bring the user back to your application from a web source like your web platform. Suppose you have an e-commerce web app and a mobile app. Let's say you're running some ad campaign. When the user interacts with your ad. These ads have deep links or universal links so these links open in the browser and your mobile app has set up deep links then the user gets redirected to the mobile app and a specific route. If deep links are not configured properly then the user gets redirected to a web app.

Project Setup

You can find the full source code for this project available on Github

To configure your android project you need to create a new intent in the manifest. If you want to add it manually, open up /android/app/src/main/AndroidManifest.xml. Make this adjustments.

1.Set launchMode of MainActivity to singleTask in order to receive intent on existing MainActivity (this is the default, so you may not need to actually change anything). 2.Add the new intent-filter inside the MainActivity entry with a VIEW type action:

<activity
        android:name=".MainActivity"
        android:label="@string/app_name"
        android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode"
        android:launchMode="singleTask"
        android:windowSoftInputMode="adjustResize">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
        <intent-filter>
           <action android:name="android.intent.action.VIEW" />
           <category android:name="android.intent.category.DEFAULT" />
           <category android:name="android.intent.category.BROWSABLE" />
           <data android:scheme="deeplink" android:host="app" />
        </intent-filter>
        <intent-filter>
           <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" />
           <data android:host="www.example.com" />
    </intent-filter>
      </activity>

Then, you need to declare the association between your website www.example.com and your intent filters by hosting a Digital Asset Links JSON file.

[{
  "relation": ["delegate_permission/common.handle_all_urls"],
  "target": {
   "namespace": "android_app",
    "package_name": "com.deeplink",
    "sha256_cert_fingerprints":["A4:A6:74:15:F1:3E:38:3F:93:0F:EF:E3:A6:86:8E:7C:25:45:E8:80:5B:5E:35:70:49:20:DB:F8:CB:D4:FC:E0"] //your app keystore
  }
}]

If you haven't created keystore for your app you can generate it with following command

 keytool -list -v -keystore my-release-key.keystore

Navigation and deep linking

If your using @react-navigation you can use its routes for deep link. In production app you will have multiple routes to different screens so, you can declare routes in app and use them for deep linking purpose. Create linking.js file in folder src according to your navigation routes.



const config = {
  screens: {
    Main: {
      path: 'Main',
      initialRouteName: 'Home',
      screens: {
        Home: {
          path: 'Home',
          initialRouteName: 'Home',
          screens: {},
        },
        Profile: {
          path: 'Profile',
          initialRouteName: 'Profile',
          screens: {
            Settings: 'Settings',
          },
        },
      },
    },
    Feed: 'Feed',
  },
};

const linking = {
  prefixes: ['deeplink://app', 'https://www.example.com'],
  config,
};

export default linking;

Add prefixes from AndroidManifest.xml i.e scheme://app in may case linking://app

 <data android:scheme="deeplink" android:host="app" />

create RootNavigation.js and export navigationRef

import * as React from 'react';

export const navigationRef = React.createRef();

export function navigate(name, params) {
  navigationRef.current?.navigate(name, params);
}

Pass ref={navigationRef} and linking={linking} to NavigationContainer

import {NavigationContainer} from '@react-navigation/native';
import React from 'react';
import {StyleSheet, View, Text} from 'react-native';
import linking from './src/navigation/linking/linking';
import MainNavigation from './src/navigation/MainNavigation';
import {navigationRef} from './src/navigation/RootNavigation';
const App = () => {
  return (
    <NavigationContainer ref={navigationRef} linking={linking}>
      <MainNavigation />
    </NavigationContainer>
  );
};

const styles = StyleSheet.create({});

export default App;

To configure deep linking in ios you need to add following lines in AppDelegate.m in your project.

// Add the header at the top of the file:
#import <React/RCTLinkingManager.h>

// Add this inside `@implementation AppDelegate` above `@end`:
- (BOOL)application:(UIApplication *)application
   openURL:(NSURL *)url
   options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options
{
  return [RCTLinkingManager application:application openURL:url options:options];
}

If your app have universal links then you have to add following line too.


// Add this inside `@implementation AppDelegate` above `@end`:
- (BOOL)application:(UIApplication *)application continueUserActivity:(nonnull NSUserActivity *)userActivity
 restorationHandler:(nonnull void (^)(NSArray<id<UIUserActivityRestoring>> * _Nullable))restorationHandler
{
 return [RCTLinkingManager application:application
                  continueUserActivity:userActivity
                    restorationHandler:restorationHandler];
}

Let's configure the native iOS app to open based on the deeplink:// URI scheme. Open project path SimpleApp/ios/SimpleApp.xcworkspace in Xcode. Go info tab and to "URL Types" and add one. In the new URL type, set the identifier and the URL scheme to your desired URL scheme.

To debug deep links, rebuild and install the app in your emulator/simulator/device.

If you're testing on iOS, run:

npx react-native run-ios

If you're testing on Android, run:

npx react-native run-android

1. ios

Testing with xcrun commands
xcrun simctl openurl booted [your deep link]

In my case:

xcrun simctl openurl booted "deeplink://app/Main/Profile/Settings"

2. Android

Testing with adb commands
adb shell am start -W -a android.intent.action.VIEW -d [your deep link] [your android package name]

In my case:

adb shell am start -W -a android.intent.action.VIEW -d "deeplink://app/Main/Profile/Settings" com.deeplink

3. Testing with npx uri-scheme

uri-scheme is a package that is used to test deep links in ios And Android. Its usage is as follows:

npx uri-scheme open [your deep link] --[ios|android]

For example :

npx uri-scheme open "mychat://chat/jane" --ios

This is all you need to build a production-level deep linking feature in your React-native application. You can find the full source code for this project available on Github . I hope you find this article helpful. If you have any queries regarding deep links or any sort drop some comments. Happy reading😃!