Is there support for Universal Links?

Base on the documentation of React Native’s Linking module, some specifc native code is required. Is this already setup within Expo?

Also, In our current setup, we are attempting to call Linking.getInitialUrl() to grab a potential app link to preparation to send the user to the correct app view. However, we have two issues with this:

  1. Many times, the Linking.getInitialUrl() will never receive the external link.
  2. When we do receive the link, we never retrieve the actually url. More of a default my-app://

Any help would be greatly appreciated!

1 Like

Yes, linking is supported.
Is the app foregrounded? You might need Linking.addEventListener

Docs for deep linking in Expo are available here

Our app does have event listeners. Component code:

import { Component } from 'react';
import PropTypes from 'prop-types';
import { Linking } from 'react-native';

import linkingUri from '@utils/linkingUri';

class DeepLinking extends Component {
  static propTypes = {
    children: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.node), PropTypes.node]),
    handleUniversalLink: PropTypes.func,
  };

  static defaultProps = {
    children: null,
  };

  static contextTypes = {
    router: PropTypes.shape({
      history: PropTypes.shape({
        push: PropTypes.func.isRequired,
      }).isRequired,
    }).isRequired,
  };

  componentDidMount() {
    Linking.getInitialURL().then(url => this.push(url));
    Linking.addEventListener('url', this.handleChange);
  }

  componentWillUnmount() {
    Linking.removeEventListener('url', this.handleChange);
  }

  handleChange = (e) => {
    this.push(e.url);
  };

  push = async (url = '') => {
    let baseUrl = linkingUri;
    if (baseUrl.endsWith('/+')) {
      baseUrl = baseUrl.slice(0, -2);
    }

    let pathname = url.replace(baseUrl, '');

    if (pathname.startsWith('/+')) {
      pathname = pathname.substr(2);
    }

    if (!url.startsWith(linkingUri) && this.props.handleUniversalLink) {
      this.props.handleUniversalLink({ url });
    } else if (pathname && pathname.length && pathname !== '/') {
      this.context.router.history.push(pathname);
    }
  };

  render() {
    return this.props.children;
  }
}

export default DeepLinking;

I’m working with @isaachardy on this one…

Essentially what’s going on is we’ve set up associated domains in the app.json as outlined here: https://docs.expo.io/versions/v26.0.0/workflow/configuration#associateddomainsan-array-that-contains-associated-domains-for-the-standalone-app

Now on a standalone distributed build clicking on links with that proper domain cause the app to open. However, Linking.getInitiaulUrl() still resolves to just the Expo linkingUri, instead of the universal link that was tapped on. This is contradictory to Facebook’s guide in their Linking docs. So, it looks like Expo’s implementation is incompatible.

However…if I eject to ExpoKit (with CRNA), everything works as expected, without any changes to the native project code (other then setting up the associated domains in the relevant plist file). The same appears to go for Android as well.

1 Like

I’m also seeing just a blank scheme-only url returned on getInitialURL.
Then nothing triggered by listening.

This is only for the standalone app, not the dev or published version.

Any ideas how to fix this without ejecting?

expo sdk 26

Thanks

This topic was automatically closed 15 days after the last reply. New replies are no longer allowed.