Implementing iOS Universal Links for Enhanced App-Web Navigation

Implementing iOS Universal Links for Enhanced App-Web Navigation

iOSSwift
Fix bugs faster! Log Collection Made Easy
START NOW!

Universal Links are an iOS feature allowing seamless integration between web content and native iOS apps. With iOS Universal Links we can intelligently configure a specific web URL, associating it with our iOS app so it will open directly when the URL is clicked.

Universal Links offer multiple benefits when compared to the deep linking and custom URL scheme methods required prior to their introduction by Apple, including:

  • User experience: Seamlessly transitioning between a website and native app is much smoother and provides a greatly enhanced user experience
  • Engagement and retention: The ability to direct users to an app without interrupting their experience brings the app’s features and capabilities into play to increase engagement and retention.
  • Analytics and insight: Universal Links increase the opportunities for tracking user interactions with an app to gain valuable insight into behaviour.

There’s no question Universal Links are a powerful tool for integrating web and app content but ensuring they work as they should requires careful configuration and that’s what we’ll be looking at in this article. Let’s get started…

Setting up Universal Links

We’ll begin with a walkthrough of how Universal Links work and the steps we need to follow to use them in our projects. For Universal Links to work properly we’ll need to configure both the iOS app and website to support them, starting by:

  • Creating an AASA file: Step one is to create an Apple App Site Association (AASA) file. This is a JSON file which is hosted on the website server and is crucial as it declares which custom URL schemes are associated with the app.
  • Uploading the AASA file to the website: Once the AASA file has been created, step two is to upload the file to the root of the associated website server. It’s essential the file is hosted at the root of the server so a secure connection between the associated domain and the iOS app can be maintained.
  • Configuring associate domains: As each Apple Universal Link must correspond to a specific domain and path on the website, step three is to configure the Xcode project settings accordingly. It’s crucial this be configured correctly as, when the link is clicked, iOS will check and return an error if not.

To create the AASA file, you need to upload a JSON file called apple-app-site-association (without any file extensions). The file should be accessible in https://<mydomain>/apple-app-site-association and be sure that the content type of the file is application/json. The file should have the following content:

{
  "applinks": {
    "apps": [],
    "details": [
      {
        "appID": "TEAM_ID.APP_BUNDLE_ID",
        "paths": [ "/path/to/content/*", "/another/path/*" ]
      }
    ]
  }
}

In the file you will need to put TEAM_ID which is your Apple Developer ID, then the BUNDLE_ID that corresponds to you app bundle identifier and finally all the paths associated to the app (you can use wildcards in the paths). The apps field it’s a legacy field that should be present and you should use an empty array.

Great, once the above steps are complete and the app is installed, iOS will open the app directly to the specified content when the app link is clicked, without needing to open the link in Safari or prompt the user.

But what about handling Universal Linking inside the app? We’ll look at that next…

Handling Universal Links inside the app

Inside the app, Universal Links can be handled by implementing the app delegate specificUIApplicationDelegate method – application:continueUserActivity:restorationHandler:. iOS will call this method when the app is launched from a Universal Link and responds to the user’s interaction.

Let’s demonstrate with an example:

//AppDelegate methods to handle the universal links
func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
    // Handle the Universal Links when app is launched
		print(userActivity)
    return true
}

Once implemented, we can take control of the flow of the application when a Universal Link is clicked, customizing the behaviour and redirection based on the incoming user activity.

Extracting data from UserActivity

Having implemented the application:continueUserActivity:restorationHandler: method, the app is now able to extract the relevant data from the Universal Link. This includes the parameters, paths and other essential information to direct the user to the required screen or feature.

Let’s look at an example:

//Reading the data from redirected URL
func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
    // Extract the data from userActivity
    if let incomingURL = userActivity.webpageURL {
        let params = incomingURL.queryParameters 
        let path = incomingURL.path
				print(params)
				print(path)
        // We can now use extracted data to navigate or perform actions in the app
    }
    return true
}

It’s vital to ensure the app responds properly to the Universal Links by extracting and processing the data from userActivity variable.

Now, you might be wondering what happens if a user clicks a Universal Link associated with an app which isn’t installed on their device…

Setting up a fallback mechanism

In the event a user clicks a Universal Link for an app they don’t have installed, it’s important to implement a fallback mechanism to handle such situations.

Let’s take a look:

//Check if app is installed and then handle this case. 
func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
    // handle the Universal Link
    if let incomingURL = userActivity.webpageURL {
        if appIsInstalled {
            // Handle the Universal Link in the app and perform desired activity
            handleUniversalLink(url: incomingURL)
        } else {
            // Fallback mechanism for when the app is not installed in device, take user to app store
            redirectToAppStore()
        }
    }
    return true
}

Here we’ve checked whether the app is installed before attempting to process the Universal Link provided a fallback redirecting the users to the App Store to download the app.

Testing Universal Links

Of course, when using Universal Links (or any other tool for that matter) it’s crucial we test them to detect and fix any issues before going into production. Let’s take a look at some ways we can test Universal Links.

Apple Validation Tool

We can use the Apple Validation Tool to check the format, structure, and validity of our Apple App Site Association (AASA) file. To do this we simply follow these steps:

  1. Upload the AASA file to the Apple Validation Tool
  2. Verify the file is in the correct format and conforms to Apple’s specifications
  3. Confirm the file is accessible from the web by checking its availability and status

Once validation is complete we’ll need to check the file is ready to be utilised by iOS devices to establish associations between the web and the iOS app.

Testing on physical devices

Universal Links should be tested on physical devices to ensure they behave as expected in real-world scenarios. We should carry out testing with app both installed and uninstalled to make sure both the links and fallbacks are working properly.

Installed testing:

To test with the app installed, follow these steps:

  1. Install the app on a real iOS device
  2. Trigger the Universal Link from the web page and verify if the app launches and handles the links properly
  3. Check if the data extraction from the Universal Link is working as expected

Uninstalled testing:

And to test with the app not installed, it’s these steps:

  1. Confirm the app is not installed on your test device
  2. Trigger the Universal Link from web and confirm that the fallback mechanism is working and redirecting the users to the App Store or a relevant web page
  3. Test the deep linking scenarios to confirm if users are directed to specific screen within your app when not installed

Fantastic, now we can set up Universal Links and test them, let’s take a look at some of the common issues and how they can be resolved.

Troubleshooting

As Universal Links have multiple dependencies within both the website and app, there are more possibilities for issues to arise affecting the performance of the links. We’ll take a look at some of the most common issues now.

Redirects

Redirects in our URL might cause problems for Universal Links so it’s important they are properly handled in our app. Some redirects may interfere with the Universal Link flow which will lead to some unexpected behaviour.

To protect against this we can implement a logic to follow the redirects and ensure that the final destination URL is handled properly, as demonstrated below:

//Code to handle the redirects 
func handleRedirections(for url: URL) {
    // Follow the redirects and obtain the final destination URL
    let finalURLs = resolveRedirects(for: url)

    // Now Handle the final URL properly
    handleUniversalLinks(url: finalURLs)
}

App IDs and Team IDs

We’ll need to confirm the App IDs and Team IDs are correct to ensure Universal Links work in application. We should also verify that the specified App ID and Team ID match those assigned in the Xcode project settings in the Apple Developer portal and the AASA file.

To do this, follow these steps:

  1. In Xcode: check the Bundle id and Team in General Settings
  2. In the AASA file: ensure that the App ID and Team ID fields are correct

If there’s a mismatch or incorrect IDs the Universal Links will not function correctly, leading to failures in navigation between the web page and the app.

Case Sensitivity of URLs

URLs are case sensitive, and if there is any inconsistencies in the URL scheme configuration will lead to errors and the URL will not function as expected.

It’s vital to check all URLs and associated ids, like Bundle Id, App id, and TeamID, are in the correct case across all configuration files, including the AASA file and Xcode project settings. See the example below:

// Example how AASA looks in JSON format
{
    "applinks": {
        "apps": [],
        "details": [
            {
                "appID": "DFGS12345.com.bugfender.app",
                "paths": ["/paths"]
            }
        ]
    }
}

Privacy and permissions

User privacy is and incredibly important consideration when implementing Universal Links and it’s crucial to explicitly ask for permission before opening the mobile app from a tapped Universal Link. By asking permission in advance we’re respecting the user’s privacy and creating a more trustworthy and user friendly experience.

We’ll need to present a permission popup when a Universal Link is tapped, explaining the action our app will take with an action button for to grant or deny the permission. It’s important to clearly communicate the benefits of the Universal Link and that improves the user experience.

Here’s a demonstration:

// show a permission prompt to the user when link is clicked.
func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
    // Display permission prompt in App
    showPermissionsPrompt { granted in
        if granted {
            // Handle the Universal Link
            handleUniversalLinks(url: userActivity.webpageURL)
        } else {
            // Handle the denial or fallback
            redirectToWebPage()
        }
    }
    return true
}

Using clear language and a simple flow will increase our chances of gaining the users permission.

We also need to enable users to manage their preferences regarding Universal Links in the app settings, allowing them to revoke or grant permission at any point and time.

Best Practices

Let’s now take a look at some best practice when using Universal Links.

User experience

Here are some things to consider to ensure a smooth and satisfying user experience:

  • Loading time: Loading time for both the web and app screens should be kept to a minimum to provide a smooth and responsive experience.
  • Design language: A consistent look and feel (e.g. color schemes and branding) should be maintained between the web and app screens to provide a seamless transition between the two
  • Navigation: As with the look and feel, navigation should be consistent between the web and app so users can progress easily in the new environment.

AASA file updates

The AASA file is the most essential component of a Universal Link and should be regularly checked and updated. This is to ensures any new domains are appropriately associated with the app and any configuration changes are reflected properly:

  • Web domains: If a new web domain is introduced that should be linked to the app we’ll need to update the AASA file accordingly to ensure the Universal Links continue to function as they should.
  • Configuration: Changes to system configuration (e.g. updates to the web functionality or adding sub domains) will also need to be reflected in the AASA file.
  • Version control: It’s a good idea to keep a record of different versions of the AASA file to help in troubleshooting and rollback if any issues arise after changes are made.

Advanced resources and further reading

Hungry for more? Detailed information on Universal Links in iOS apps is available on Apple’s official documentation which provides comprehensive guidance, best practices and technical details related to the Universal Links.

It’s important to regularly check the documentation for updates or additional features for Universal Links that may be introduced from time-to-time. Additionally we can find valuable insights and troubleshooting tips in the community forums, developer blogs, and related iOS development resources on web.

To sum up

We’ve looked at the multiple benefits Universal Links, how a Universal Link differs from a deep link and what they can offer to app developers including:

  • User experience
  • App engagement and retention
  • Analytics and insight

We’ve also worked through setting up Universal Links, including:

  • Creating and hosting an AASA file
  • Configuring associated domains
  • Handling Universal Links and extracting data from UserActivity
  • Setting up fallback mechanisms
  • Testing, both simulated and real-world

We also looked at some of the other crucial things to understand about Universal Links, including:

  • Privacy and permissions
  • Best practice

We hope you’ve found this guide to Universal Links informative and have confidence to experiment with them in your projects.

Expect the Unexpected! Debug Faster with Bugfender
START FOR FREE

Trusted By

/assets/images/svg/customers/cool/continental.svg/assets/images/svg/customers/highprofile/disney.svg/assets/images/svg/customers/projects/taxify.svg/assets/images/svg/customers/cool/ubiquiti.svg/assets/images/svg/customers/highprofile/dolby.svg/assets/images/svg/customers/highprofile/intel.svg/assets/images/svg/customers/highprofile/deloitte.svg/assets/images/svg/customers/projects/vorwerk.svg

Already Trusted by Thousands

Bugfender is the best remote logger for mobile and web apps.

Get Started for Free, No Credit Card Required