Locked Icon

Universal Links is a powerful tool for bridging the gap between web and app content, offering a unified experience for users across iOS and Android platforms. By enabling direct links to specific app content from your website, Universal Links empower developers to enhance user engagement and streamline the transition between the web and mobile app.

In this comprehensive guide, we will delve into the intricacies of setting up Universal Links for both iOS and Android. Whether you're seeking to boost user retention, increase conversions, or simply provide a smoother user journey, understanding Universal Links is the key to achieving these goals.

What Are Universal Links?

Universal links are HTTPS URLs representing your content on the web product and in your app.

When users tap or click a universal link, the system redirects the link directly to your app without routing through Safari or your website, allowing you to provide a richer experience. If the user has not installed your app, the system opens the URL in Safari, allowing your website to handle it.

When users install your app, the system checks a file stored on your web server to verify that your website allows your app to open URLs on its behalf. Only you can store this file on your server, securing the association of your website and your app.

Why Do You Need Universal Links?

Universal Links serve as a bridge connecting your website and mobile app. Here's why you need them:

  • Seamless User Experience: Universal Links eliminate the jarring transitions between a website and a mobile app. When a user taps on a link to your content, it intelligently opens the app if it's installed, or directs them to the App Store or Google Play Store if it's not, ensuring a seamless, uninterrupted experience.
  • Improved User Engagement: By effortlessly guiding users to your app, Universal Links increase the likelihood of users engaging with your app's content. This can lead to higher user retention rates, more interactions, and, ultimately, a stronger connection with your brand.
  • Enhanced Conversion Rates: Universal Links streamline the path from discovery to action. Users are more likely to complete desired actions within your app, such as making a purchase, signing up, or sharing content, as the transition from web to app is frictionless.

The Advantages of Using Universal Links for Your App

Universal Links offer a host of advantages for both developers and businesses:

  • Cross-Platform Compatibility: They work seamlessly on both iOS and Android, making them a versatile solution for reaching a wide audience.
  • Boosted Discoverability: Universal Links can drive organic traffic to your app by allowing search engines to index app content, making it more discoverable in web search results.
  • Enhanced Security: Universal Links are more secure than traditional deep linking methods, reducing the risk of phishing attacks and ensuring users are directed to legitimate app content.
  • Analytics and Tracking: Developers can gain valuable insights into user behavior by tracking Universal Link interactions, helping refine app features and marketing strategies.

How Do Universal Links Work?

Universal Links leverage a combination of technologies to seamlessly connect web content with the corresponding app. In this guide, we will dive deeper into the setup and implementation of Universal Links for iOS and Android, equipping you with the knowledge and tools to harness this powerful feature for your app's benefits.

Setting up Universal Links for iOS

Universal Links in the context of iOS refer to a feature that allows seamless integration between web and mobile experiences. Specifically, Universal Links enable iOS apps to open web content directly, bypassing the need to launch Safari or any other web browser. In the case of Flutter Universal Links iOS, a popular open-source UI software development toolkit, incorporating Universal Links into your iOS app involves a few key steps.

Custom URL schemes have been widely used in the past to establish communication between apps and launch specific functionalities within them. However, there are several reasons why custom URL schemes are not recommended:

- They are not secure by design. Any app can register and use a custom URL scheme, which can potentially lead to security vulnerabilities, such as phishing attacks or opening malicious URLs in unintended apps.

- Custom URL schemes are limited in terms of functionality. They can only trigger a specific action within an app or open it, but they cannot pass complex data or context between apps.

- There is no guarantee that a custom URL scheme is unique across all apps. Conflicts may arise if multiple apps use the same custom URL scheme, causing unpredictable behavior or unintended launches.

Thus, Universal Links provide a more standardized and secure way of linking to specific app content. Implementing Flutter iOS Universal Links ensures a seamless and integrated experience for users, allowing smooth navigation between web and native app content on iOS devices. By incorporating React Native iOS Universal Links, developers also can create a cohesive user experience, enabling smooth transitions between web and native app content on iOS devices.

Have a project in mind?

Share your idea and we will contact you within 24 hours.

Contact us

Creating and uploading the Association file

To create a secure connection between your website and your app, you establish a trust relationship between them. You establish this relationship in two parts:

  • An apple-app-site-association file that you add to your website
  • A entitlement that you add to your app

When a user installs your app, the system attempts to download the associated domain file and verify the domains in your entitlement.

To add the associated domain file to your website, create a file named apple-app-site-association (without an extension). Update the JSON code in the file for the services you support on the domain.

You need to supply a separate apple-app-site-association file for each domain with unique content your app supports. For example, and  need separate apple-app-site-association files, because these domains serve different content. The uncompressed size of the apple-app-site-association file must be no greater than 128 KB.

   "applinks": {
       "apps": [],
       "details": [
               "appID": "TeamID.BundleID",
               "paths": ["*"]

The apps key in an apple-app-site-association file must be present, and its value must be an empty array. The value of the details key is an array of dictionaries, one dictionary per app that your website supports. The order of the dictionaries in the array determines the order the system follows when looking for a match, so you can specify an app to handle a particular part of your website.‍

Each app-specific dictionary contains an appID key and a paths key. The value of the appID key is the team ID or app ID prefix, followed by the bundle ID. For example:

The value of the paths key is an array of strings that specify the parts of your website that are supported by the app and the parts of your website that you don’t want to associate with the app. To specify an area that should not be handled as a universal link, add “NOT ” (including a space after the T) to the beginning of the path string. Keep the list of paths fairly short and rely on wildcard matching to match larger sets of paths.

For example, the apple-app-site-association file can prevent the /xyz/* area of the website from being handled as a universal link by updating the paths array as shown here:

"paths": [ "/abc/def/", "NOT /xyz/*"]

After you construct the association file, upload it to the root of your HTTPS web server or to the .well-known subdirectory. The file’s URL should match the following format:

https://<fully-qualified-domain>/apple-app-site-association or https://<fully-qualified-domain>/.well-known/apple-app-site-association

You must host the file using https:// with a valid certificate and no redirects.

Apple’s content delivery network requests the apple-app-site-association file for your domain within 24 hours. Devices check for updates approximately once per week after app installation.

Configuring your app

Open your Xcode project.

In the "Signing & Capabilities" section, add the "Associated Domains" capability.

To add your domain to the entitlement, click Add (+) at the bottom of the Domains table to add a placeholder domain. Replace the placeholder with the appropriate prefix for the service your app supports and your site’s domain. Make sure to only include the desired subdomain and the top-level domain. Don’t include path and query components or a trailing slash (/).

Add the domains that share credentials with your app. Each domain you specify uses the following format:

< service>:< fully qualified domain>

Starting with macOS 11 and iOS 14, apps no longer send requests for apple-app-site-association files directly to your web server. Instead, they send these requests to an Apple-managed content delivery network (CDN) dedicated to associated domains.

Handling Universal Links in your app

When a user taps a universal link, iOS launches your app and sends it an NSUserActivity object that you can query to find out how your app was launched. Basically, you need to modify two functions of your AppDelegate class.

In your app's AppDelegate class, implement the application(_:continue:restorationHandler:) method. This method is used when the app is already running in the background or suspended state. The user interacts with a universal link.

func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {

func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
        // Handle universal links when the app is already running or in the background

        guard userActivity.activityType == NSUserActivityTypeBrowsingWeb,
          let url = userActivity.webpageURL else {
             return false // Return false if the user activity is not a web browsing activity
        handleUniversalLink(url: url)

        return true

Create a function for handling universal links.

private func handleUniversalLink(url: URL) {
        // Implement your logic to process the universal link here

Include different cases in your implementation based on the path of the universal link, present a certain screen from window?.rootViewController, or start a new flow. You can create a separate Universal Link manager to handle this. For example,

import UIKit

class UniversalLinkManager {
    static let shared = UniversalLinkManager()
    func handleUniversalLink(url: URL) {
        guard let host = else { return }

        switch url.path {
        case "/product":
            guard let productId = url.queryParameters["id"] else { return }
                // Handle opening a specific product using the product ID
        case "/profile":
            guard let username = url.lastPathComponent else { return }
            // Handle opening a user profile using the username
            // Navigate to the user's profile screen

When the app is launched for the first time via a universal link, the application(_:continue:restorationHandler:) method is not called, so the application(_:didFinishLaunchingWithOptions:) method is the one that will handle the link and perform any necessary setup.

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    // Check if the app was launched via a universal link
    guard let userActivity = launchOptions?[.userActivityType] as? NSUserActivity,
          userActivity.activityType == NSUserActivityTypeBrowsingWeb,
          let url = userActivity.webpageURL else {
        return true
    // Handle the universal link
    handleUniversalLink(url: url)
    return true

Testing and debugging Universal Links

First, on your iOS device, enable "Universal Links Debug Mode" to aid testing by navigating to Developer Settings > Domain URLs.

Next, install your app on a device and click on a Universal Link that matches the configured domain. The app should open directly to the expected content without prompting for a selection.

For detailed testing, handle scenarios where the app is already running or in the background and cases where the app is not installed. Test different Universal Link paths and verify that they route correctly.

You can also use tools like the "apple-app-site-association" file validator (for example, and various online tools to validate your domain association.

Best practices for implementing Universal Links

  • Use HTTPS: Ensure your web URLs use the HTTPS protocol to support universal links. Apple requires universal links to be served over HTTPS for security reasons.
  • Verify Domain Association: Register your app's association with the domains that will use universal links using the Apple Site Association (ASA) file. Make sure to verify the domain association to enable universal link support.
  • Handle All Scenarios: Implement universal link handling in your app for all relevant scenarios, including when the app is already running, when the app is launched via a universal link, and when a user interacts with a universal link while the app is suspended or terminated.
  • Fallback Mechanism: Provide a fallback mechanism when a universal link cannot be opened, such as displaying an error message or offering an alternative action. This helps prevent a poor user experience.
  • User Context: If your app requires user authentication, consider preserving the user's context when handling a universal link. Users should land on the relevant content even after being prompted to log in.
  • Avoid Redirects: Avoid redirecting users to a landing page before opening the app. This adds an extra step and may lead to a poor user experience.
  • Error Handling: Handle potential errors, such as network failures or invalid links. Display meaningful error messages to users to guide them through troubleshooting steps.
  • User Privacy: Respect user privacy and provide clear information about how universal links are used in your app. Ensure that users understand the purpose of universal links and their impact on the app's behavior.
  • Universal Link Manager: Consider creating a separate manager or handler to centralize the logic for processing different universal link paths. This promotes code modularity and easier maintenance.
  • Regular Updates: As your app evolves, make sure to update your universal link handling to accommodate any changes in your app's navigation structure or URL schemes.

Setting up Universal Links for Android

Android Universal Links, also known as Universal Linking on Android, have become a pivotal feature in modern mobile app development. These intelligent links seamlessly connect web content to mobile applications, enhancing user experiences and streamlining interactions. We explored the concept of Android Universal Links, highlighting their significance in the Android ecosystem and their role in deepening user engagement.

We delve into the technical intricacies of implementing Universal Links for Android, shedding light on best practices and strategies to optimize Android Universal Links functionality. Whether you're a developer aiming to harness the power of Android Universal Links or a business seeking to improve user retention and interaction, this abstract offers valuable insights into this vital aspect of mobile app development.

Creating a deep link for a destination

Android Universal Links streamline the user experience by allowing seamless navigation between web content and native Android apps, providing a cohesive and integrated journey for users.

In the context of Universal Link, Android implies that a deep link is a link that takes you directly to a specific destination within an app.

The Navigation component lets you create two different types of deep links: explicit and implicit.

Creating an explicit deep link

Universal Link in Android implies an explicit deep link. An explicit deep link is a single instance of a deep link that uses a PendingIntent to take users to a specific location within your app. For example, you might surface an explicit deep link as part of a notification or an app widget.

When a user opens your app via an explicit deep link, the task back stack is cleared and replaced with the deep link destination. When nesting graphs, the start destination from each level of nesting — that is, the start destination from each <navigation> element in the hierarchy—is also added to the stack. This means that when a user presses the Back button from a deep link destination, they navigate back up the navigation stack just as though they entered your app from its entry point.

You can use the NavDeepLinkBuilder class to construct a PendingIntent, as shown in the example below. Note that if the provided context is not an Activity, the constructor uses PackageManager.getLaunchIntentForPackage() as the default activity to launch, if available.

val pendingIntent = NavDeepLinkBuilder(context)

By default, NavDeepLinkBuilder launches your explicit deep link into the default launch Activity that is declared in your app's manifest. If your NavHost is in another activity, you must specify its component name when creating the deep link builder.

val pendingIntent = NavDeepLinkBuilder(context)

If you have a ComponentName, you can pass it directly to the builder:

val componentName = ...

val pendingIntent = NavDeepLinkBuilder(context)

If you have an existing NavController, you can also create a deep link by using NavController.createDeepLink().

Creating an implicit deep link

For Universal Link in Android, an implicit deep link refers to a specific destination in an app. When the deep link is invoked—for example, when a user clicks a link—Android can then open your app to the corresponding destination.

Deep links can be matched by URI, intent actions, and MIME types. You can specify multiple match types for a single deep link, but note that URI argument matching is prioritized first, followed by action, and then MIME type.

Here's an example deep link that contains a URI, an action, and a MIME type:

<fragment android:id="@+id/a"
        <deepLink app:uri=""

You can also use the Navigation Editor to create an implicit deep link to a destination as follows:

1. In the Design tab of the Navigation Editor, select the destination for the deep link.

2. Click + in the Deep Links section of the Attributes panel.

3. In the Add Deep Link dialog that appears, enter the info for your deep link.
Note the following:

  • URIs without a scheme are assumed as either http or https. For example, matches both and
  • Path parameter placeholders in the form of {placeholder_name} match one or more characters. For example,{id} matches The Navigation component attempts to parse the placeholder values into appropriate types by matching placeholder names to the defined arguments that are defined for the deep link destination. If no argument with the same name is defined, a default String type is used for the argument value. You can use the .* wildcard to match 0 or more characters.
  • Query parameter placeholders can be used instead of or in conjunction with path parameters. For example,{id}?myarg={myarg} matches
  • Query parameter placeholders for variables defined with default or nullable values are not required to match. For example,{id}?arg1={arg1}&arg2={arg2} matches or This is not the case with path parameters. For example, does not match the above pattern because the required path parameter is not supplied.
  • Extraneous query parameters do not affect deep link URI matching. For example,{id} matches, even though extraneousParam is not defined in the URI pattern.

4. (optional) Check Auto Verify to require Google to verify that you are the owner of the URI. For more information, see Verify Android App Links.

5. Click Add. A link icon appears above the selected destination to indicate that the destination has a deep link.

6. Click the Code tab to toggle to the XML view. A nested <deepLink> element has been added to the destination:

< deepLink app:uri="" />

To enable implicit deep linking, you must also make additions to your app's manifest.xml file. Add a single <nav-graph> element to an activity that points to an existing navigation graph, as shown in the following example:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android=""

    <application ... >

        <activity name=".MainActivity" ...>

            <nav-graph android:value="@navigation/nav_graph" />



When building your project, the Navigation component replaces the <nav-graph> element with generated <intent-filter> elements to match all of the deep links in the navigation graph.

When triggering an implicit deep link, the state of the back stack depends on whether the implicit Intent was launched with the Intent.FLAG_ACTIVITY_NEW_TASK flag:

  • If the flag is set, the task back stack is cleared and replaced with the deep link destination. As with explicit deep linking, when nesting graphs, the start destination from each level of nesting—that is, the start destination from each <navigation> element in the hierarchy—is also added to the stack. This means that when a user presses the Back button from a deep link destination, they navigate back up the navigation stack just as though they entered your app from its entry point.
  • If the flag is not set, you remain on the task stack of the previous app where the implicit deep link was triggered. In this case, the Back button takes you back to the previous app, while the Up button starts your app's task on the hierarchical parent destination within your navigation graph.

Handling deep links

It is strongly recommended to always use the default launchMode of standard when using Navigation. When using standard launch mode, Navigation automatically handles deep links by calling handleDeepLink() to process any explicit or implicit deep links within the Intent. However, this does not happen automatically if the Activity is re-used when using an alternate launchMode such as singleTop. In this case, it is necessary to manually call handleDeepLink() in onNewIntent(), as shown in the following example:

override fun onNewIntent(intent: Intent?) {

We know how to make it faster, here’s why

Our estimations

Axon takes pride in offering cutting-edge solutions and services underpinned by agile project management methodologies. We recognize the paramount significance of precise estimations in meeting client expectations and project deadlines.

Our approach to estimations revolves around close collaboration with our clients. We understand that every project is unique, and client preferences play a crucial role in defining the scope and scale of software development initiatives. By actively engaging with our clients, we gain deep insights into their specific requirements, priorities, and budgetary constraints. Leave your contacts, and we will provide you with estimations in 24 hours.

Our experience

At Axon, we have extensive expertise in setting up Universal Links into a wide range of mobile development projects. We have worked with clients from diverse industries with unique requirements and consistently delivered robust solutions tailored to their needs. Whether it's ensuring a smooth transition from a website to an app or enhancing user engagement through deep linking, our experience in setting up Universal Links has resulted in improved user retention, increased user interactions, and ultimately, higher customer satisfaction. With our proven track record in Universal Links implementation, you can trust us to make your mobile app not just functional but also user-friendly and responsive, contributing to the overall success of your project.

Our team

Throughout the software engineering process, our team has demonstrated a well-established track record of collaboration and professionalism when working with our esteemed partners.

Our team's agility enables us to embrace change and tackle complex challenges with confidence. We approach each project with a flexible mindset, tailoring our methodologies to suit the unique requirements and goals of our clients. Through agile project management, we ensure that our solutions are scalable, maintainable, and adaptable to future needs.

Check out the latest blog post of Axon’s CEO - How Axon works on delivering extra benefits to the clients


In conclusion, setting up Universal Links on your mobile development project, whether for Android or iOS, is critical in enhancing user experiences and eliminating app engagement problems. While the process may seem complex, partnering with an experienced software engineering company can make all the difference. At Axon, we bring a wealth of knowledge and expertise to the table, ensuring that your Universal Links implementation is seamless and tailored to your specific needs.

So, if you're working on a mobile development project and wish to leverage the benefits of Universal Links, don't hesitate to reach out to our team of dedicated professionals.

Software Development Team

When it comes to creating software solutions that not only meet but exceed your business objectives, partnering with a proven expert is paramount. That's where Axon, your trusted ally in software engineering, steps in. Our comprehensive services and dedicated team are here to streamline your development process, providing you with top-notch solutions while keeping a watchful eye on your budget.

Need estimation?

Are you ready to elevate your software development to the next level? Contact Axon today to discuss your project, and let's work together to design an application that not only meets your budget but also propels your business to new heights.

Software development Team


related cases


Need estimation?

Leave your contacts and get clear and realistic estimations in the next 24 hours.

Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.
coin image
Estimate Your Mobile App
Take a quick poll and get a clear price estimation