React Native SDK Expo Integration

Prev Next

Overview

This guide outlines how to integrate the Branch React Native SDK into an Expo-based app using the @config-plugins/react-native-branch plugin. The plugin is maintained in Expo's config-plugins repository.

This guide covers an Expo-managed workflow. If you need full native control, see the React Native SDK Basic Integration guide.

Before you begin

Before you begin this integration, make sure you:

  • Have an Expo-managed or prebuild workflow using Expo SDK 54 or higher (run npx expo install expo to install or update)

  • Use a development build. Expo Go doesn't support the plugin because it adds native code.

  • Understand which Branch products you are implementing:        

    • Attribution and deep linking

    • Paid ads

    • Other advanced features

You will also need:

Set up Branch in your Expo app

1. Configure Branch

Configure Branch for your application:

Make sure to configure your default link settings as part of the setup process.

2. Install Branch

Install the Branch React Native SDK. Use the version listed for your Expo SDK in the plugin's version table.

npx expo install react-native-branch@<version>

3. Add plugin

Add the plugin, using the version listed for your Expo SDK in the same table.

npx expo install @config-plugins/react-native-branch@<version>

4. Configure plugin

Set environment variables using EAS.

If you don’t have an app.config.js or app.config.ts in your project, start by manually creating one. Then, add the following code:

export default {
  plugins: [
    [
      '@config-plugins/react-native-branch',
      {
        apiKey: process.env.BRANCH_API_KEY, // Required
        iosUniversalLinkDomains: [
          process.env.BRANCH_DOMAIN_LINK,
          process.env.BRANCH_DOMAIN_LINK_ALT,
        ],
      },
    ],
  ],
  ios: {
    associatedDomains: [
      `applinks:${process.env.BRANCH_DOMAIN_LINK}`,
      `applinks:${process.env.BRANCH_DOMAIN_LINK_ALT}`,
    ],
  },
  android: {
    intentFilters: [
      {
        action: "VIEW",
        autoVerify: true,
        category: ["BROWSABLE", "DEFAULT"],
        data: [
          { scheme: 'https', host: `${process.env.BRANCH_DOMAIN_LINK}` },
          { scheme: 'https', host: `${process.env.BRANCH_DOMAIN_LINK_ALT}` },
        ],
      },
    ],
  },
}

If your build is failing in local development after configuring the plugin, see the Troubleshooting section.

iosUniversalLinkDomains

The iosUniversalLinkDomains option registers your Branch domains as iOS associated domains for Universal Links. Include both your primary and alternate (-alternate) link domains if your app uses both.

This is separate from ios.associatedDomains, which establishes a secure association between your domains and your app.

Universal Links requires both iosUniversalLinkDomains and ios.associatedDomains to work.

The plugin handles native Branch initialization automatically. For details on native Branch initialization, see the React Native SDK Basic Integration guide.

To listen for deep link data, subscribe in your app's entry point:

import branch from 'react-native-branch'

branch.subscribe(({ error, params }) => {
  if (error) {
    console.error('Branch error:', error)
    return
  }

  console.log('Branch params:', params)
})

6. Configure permissions on Android and iOS

Android

Add the Google Advertising ID (GAID) and Google Play Install Referrer permissions so Branch can accurately match clicks to installs and downstream events. In the app.json file, add the following:

{
  "expo": {
    "android": {
      "permissions": [
        "com.google.android.gms.permission.AD_ID",
        "com.android.vending.INSTALL_REFERRER"
      ]
    }
  }
}

iOS

To use Branch's NativeLink™ feature, add the following entry to your Branch.json file to allow the SDK to check the pasteboard for the Branch Link:

{
  "checkPasteboardOnInstall": true
}

7. (Optional) Set up paid ads

If you're using Branch for paid ad attribution, additional setup is required.

See the following guides to set up and test your paid ads implementation:

8. Validate integration

Before testing on device, use the Link Validator in Branch to confirm your links are configured correctly and preview the expected user flow across different platforms and click sources.

Then validate your integration using the three scenarios below. In each case, your subscribe callback should receive and log the link data.

  1. Test Universal Link opening: Open a Branch Link from Safari (iOS) and Chrome (Android). The app should open directly without extra dialogs or browser redirects.

  2. Test cold-start deep link behavior: Force quit the app, then open a Branch Link. The app should launch and take you to your content.

  3. Test background resume behavior: With the app backgrounded, tap a Branch Link. The app should resume and take you to your content.

For additional validation and testing, use the following guides:

iOS

Android

Next steps

Once you’ve integrated Branch into your Expo app, you can use any of the features documented in the React Native SDK Full Reference guide, including creating Branch Links, tracking Branch Events, and handling Branch Universal Objects.

Troubleshooting

For general iOS and Android troubleshooting suggestions, use the following guides:

Plugin version errors

Version errors mean your Expo SDK, the Branch React Native SDK, and the plugin don't match. Install the versions listed for your Expo SDK in the plugin's version table. Avoid --legacy-peer-deps. It skips the version check and can leave you with versions that don't work together.

Build fails without BRANCH_API_KEY in local development

If BRANCH_API_KEY is not set in your environment, the plugin will fail the build, even if you're not testing Branch functionality. To avoid this, conditionally load the plugin only for production builds:

export default {
  plugins: IS_DEV
    ? [...plugins, ...devPlugins]
    : [...plugins, ...prodPlugins],
}

Place the @config-plugins/react-native-branch plugin inside prodPlugins.

Prebuild fails

If prebuild fails after adding the @config-plugins/react-native-branch plugin, try running a clean prebuild:

npx expo prebuild --clean

Unable to use both Test and Live Branch Keys

On Expo SDK 55 or later, you can add testApiKey to the plugin configuration alongside apiKey. On Android, setting enableTestEnvironment to true makes a build use the test key. The iOS SDK doesn't read enableTestEnvironment, so it has no effect on iOS.

On iOS, and on Expo SDK 54, use one of these workarounds:

  • Use separate builds for Test and Live

  • Use only your Branch Live Key across all your environments

  • Implement custom built-time logic

If your deep links are not properly opening your app:

SKAdNetwork attribution is unclear

If your SKAdNetwork attribution data is not showing up or doesn’t look correct in Branch:

  • Confirm SKAdNetwork IDs are registered

  • Validate Branch reporting

  • Test install flow from paid campaign

For SKAdNetwork setup and validation, see our Enable SKAdNetwork guide.

Branch analytics fields are empty after removing Firebase

If you migrated away from the Firebase SDK and Branch analytics fields like $~campaign are unpopulated, you may need to explicitly install expo-tracking-transparency. On Android, this library was previously bundled with Firebase in Expo environments.

npx expo install expo-tracking-transparency

Also confirm that your Proguard -keep rules are correctly configured for the Branch React Native SDK.