Deep Linking with Expo - Universal/App Links

Recently I had to add Deep Linking with App Links to an Expo app and found myself stuck when following the official documentation. While it’s not wrong, I believe some important details are missing. Therefore, I decided to group everything I found online to make it work!

What is Deep Linking?

Deep Linking refers to the practice of creating hyperlinks that send the user to a specific page or content in our websites/apps. We do this all the time on our web pages, this isn’t very straightforward for mobile apps, since there isn’t a “URL” for them

So, in this case, deep linking will allow us to create such hyperlinks that automatically launch the app and redirect the users to specific routes when clicked! We already do this all the time when using tel:, mailto:, or sms on our pages. For our own apps, we can even create custom URL schemes (instead of https, tel, etc) to link directly to our app. I won’t talk about this here but you can learn how to do this on Expo on the official docs.

But what about App Links (or Universal Links)?

💡

App Links (Android) and Universal Links (iOS) are the same thing. I will use the term App Links in the rest of the article since I’ll be dealing with Android.

Simply put, app links are a special type of deep links, which instead of custom URL schemes, we use plain old https:// links to redirect users to our app.

For example, if you send an email to the user with the link to a product they might be interested in your online store e.g. https://www.my-cool-store.com/products/1, instead of opening the browser (which is the default behavior), it would automatically open your app on the “Product 1” page - and if the app isn’t installed, the browser will be opened instead! Cool right? I didn’t even know it was possible.

Making it work

So, after this short introduction let’s get to it. There are a lot of details that we could delve into here, but I’ll make this as clean as possible and link extra resources if you’re interested in learning more.

  1. On your Expo Project - Add intentFilters to your app.json:
    1. The action, autoVerify, and category should be left as is
    2. In the data array, you should add the URLs that will launch the app. For multiple subdomains, you may use wildcards (*.myapp.io)
    app.json

  2. On your website - Add assetlinks.json:
    1. {package_name} is the application ID you set for the app
    2. {sha256_cert_fingerprints} should be found at your Google Play Store developer account, All Apps > Select the app in question > Setup > App integrity > App signing On this page, you will find the whole Digital Asset Links JSON you need.
      1. At this point, the Expo docs also say you can get the SHA by running eas credentials -p android but this value didn’t work for me. You can set both on the array if you want
    [
      {
        "relation": ["delegate_permission/common.handle_all_urls"],
        "target": {
          "namespace": "android_app",
          "package_name": "{package_name}",
          "sha256_cert_fingerprints": [
            // Supports multiple fingerprints for different apps and keys
            "{sha256_cert_fingerprints}"
          ]
        }
      }
    ]

    🔥

    After you deploy this file, test ALL the domains from the intentFilters on this page Statement List Generator and Tester and make sure all of them succeed. Try them out and fix the intentFilters data if necessary.

    This is the part that is overlooked in the official documentation. If you want the linking to work you must add the assetlinks.json file and make it accessible on EVERY domain you listed on the intentFilters. Failing to do so won’t enable the linking (the user would still be able to do it manually on the app settings, but it is just something that he would probably never do)

  3. Configure your app to handle the links

    This last step depends on how you built your app, but remember to handle the incoming links on the application. If you’re using React Navigation, for example, you can take a look at their documentation.

    🔥

    One important thing to keep in mind is that the links must be clicked somehow for this to work - just typing them on the browser won’t open your app. Maybe send yourself an email or a message with the URLs you’ll need to test and click them from the testing device

Some caveats

  • Sometimes redirects won't work, but that may depend on how your DNS is configured - maybe www.mydomain.com works but mydomain.com doesn't so test them on the website before setting them on the intent filters
  • If you’re not linking to a website of your own (and therefore cannot add the asset links file) you should set the autoVerify field to false on the intentFilters - some people say it doesn't work though and you would need to activate the links manually
  • In my project, there was an expo plugin react-native-fbsdk-next which inadvertently added extra data to the intents I set for deep linking which may break the flow
withAndroidVerifiedLinksPlugin

Testing it

While developing you’ll probably want to (and should) test if your routing is correct. This is how you can do it.

  • All this works on development builds - just run expo android and launch the app on a physical device or an emulator.
  • If you added the development SHA to the sha256_cert_fingerprints it will probably work out of the box. Even so, the auto-linking may fail, but you can enable it manually on the app settings:
    • Go to the App Settings → Find the Open by default settings → Enable the Open supported links option → Click on “Add links” or “Supported web addresses” → enable the links you recognize (these values come from the intentFilters we set later)
    • If no links are showing up, go to your expo project folder, find in the build /android/src/main/AndroidManifest.xml, and check if there are all the data tags with your domains. Sometimes running expo android doesn’t overwrite your Android folder, so you should make a clean build
image
image
image
image

Resources