Guides · Oct 7, 2026
Universal Links vs Deep Links on iOS: Rules for Implementation and Routing
Summarize this with AI
Open this article in your favorite AI assistant and get a quick summary in seconds.
When you share a link to specific content within your iOS app, you generally have two primary methods: Universal Links or traditional URL Schemes, often called Deep Links. The choice impacts user experience significantly, especially whether your app opens directly or users see an unexpected browser page. This guide will clarify the technical implementation of each, detailing `apple-app-site-association` file formatting, Xcode entitlements, and how the system handles routing when a user doesn't have your app installed. By the end, you'll know exactly which method to use and how to configure it for a seamless user journey.
Universal Links: The Seamless Entry
Universal Links are standard HTTP or HTTPS links that seamlessly open your app if it's installed on the user's device. If your app isn't installed, the same link gracefully opens the corresponding web page in Safari, ensuring a consistent user experience without error messages or an "app picker" dialog. This behavior is key to their superior user experience compared to traditional Deep Links. The magic behind Universal Links is a file called `apple-app-site-association`, or AASA. You host this JSON file on your web server, and iOS periodically fetches it to understand which URLs on your domain should be handled by your app. This file must be served over HTTPS and be accessible at either the root of your domain (e.g., `https://yourdomain.com/apple-app-site-association`) or within the `.well-known` subdirectory (e.g., `https://yourdomain.com/.well-known/apple-app-site-association`). The server must respond with a `200 OK` status code and serve the file with the `application/json` MIME type. Inside Xcode, you must enable the `Associated Domains` capability for your app. You add your domain in the format `applinks:yourdomain.com` (for example, `applinks:focuskit.app` for our hypothetical habit tracker). This tells iOS that your app wants to handle URLs from that specific domain. Without this entitlement, iOS won't even attempt to fetch your AASA file. In App Store Connect, ensure that the `Associated Domains` capability is also enabled for your App ID under `Certificates, Identifiers & Profiles`. Here's a minimal example of an `apple-app-site-association` file for a habit tracker app, let's call it FocusKit:{
"applinks": {
"apps": [],
"details": [
{
"appID": "ABCDEF1234.com.sedat.focuskit",
"paths": [
"/challenge/*",
"/streak/*",
"/share/*",
"NOT /share/private/*"
]
}
]
}
}
In this JSON, `ABCDEF1234` is your Apple Team ID, and `com.sedat.focuskit` is your app's bundle identifier. The `paths` array specifies which URL paths your app should handle. For instance, `https://focuskit.app/challenge/123` would open directly into your app's challenge view, while `https://focuskit.app/share/private/secret` would open in Safari due to the `NOT` prefix. This allows granular control over which URLs your app claims.
Deep Links (URL Schemes): The Classic Routing
Traditional Deep Links rely on custom URL schemes registered by your app (e.g., `focuskit://challenge?id=123`). When a user taps a link with this scheme, iOS attempts to open the app registered to handle it. If multiple apps register the same scheme, iOS presents an "app picker" dialog, which can be disruptive. The primary advantage of Deep Links is their simplicity to implement. You register your custom scheme directly in your app's `Info.plist` file within Xcode. Navigate to `Info` > `URL Types`, add a new type, and specify your scheme (e.g., `focuskit`) under `URL Schemes`. There's no external web server file to manage. For optimal reliability and uniqueness, your URL scheme should be short and descriptive, ideally under 20 characters. For instance, `focuskit` is much better than `myawesometrackingsolution`. However, Deep Links come with significant drawbacks. If the user does not have your app installed, the link will simply fail. The operating system won't know what to do with `focuskit://...`, resulting in an error message or simply nothing happening. This can lead to a broken user experience when sharing links, making them less suitable for general marketing or social media sharing where the app's install status is unknown. They are typically better suited for internal app-to-app communication or specific use cases where app installation is guaranteed.Implementation Checklist: Getting Your Universal Links Right
Implementing Universal Links correctly requires attention to detail across your web server and Xcode project. Follow these steps to ensure a smooth setup for your iOS app.- Create Your
apple-app-site-associationFile:- Structure it as valid JSON, including your `appID` (Team ID + Bundle ID) and an array of `paths` your app will handle.
- Example `appID`: `ABCDEF1234.com.sedat.focuskit`
- Example `paths`: `["/my-feature/*", "/item/A1B2C3D4"]`
- Host the AASA File on Your Web Server:
- Place the file at `https://yourdomain.com/apple-app-site-association` or `https://yourdomain.com/.well-known/apple-app-site-association`.
- Ensure it's served over HTTPS.
- Verify it returns an HTTP `200 OK` status code.
- Confirm the `Content-Type` header is `application/json`. You can check this with `curl -v https://yourdomain.com/apple-app-site-association`.
- The file must not be redirected (e.g., HTTP to HTTPS redirect is fine, but not `https://olddomain.com` to `https://newdomain.com`).
- Configure Xcode for Associated Domains:
- Open your Xcode project, select your target, and go to the `Signing & Capabilities` tab.
- Click `+ Capability` and add `Associated Domains`.
- Add an entry in the format `applinks:yourdomain.com` (e.g., `applinks:focuskit.app`).
- Repeat for all domains that host your AASA file.
- Enable Associated Domains in App Store Connect:
- Log into App Store Connect.
- Go to `Certificates, Identifiers & Profiles` > `Identifiers`.
- Select your App ID and ensure `Associated Domains` is checked under `Capabilities`. If not, edit and enable it.
- Handle Incoming Universal Links in Your App:
- In `AppDelegate.swift` (for UIKit apps using `AppDelegate`): Implement `application(_:continue:restorationHandler:)` to process `NSUserActivity.webpageURL`.
- In `SceneDelegate.swift` (for UIKit apps using `SceneDelegate`): Implement `scene(_:continue:)` to process `NSUserActivity.webpageURL`.
- In SwiftUI apps: Use the `.onOpenURL` view modifier or handle `NSUserActivity` in the `App` struct.
- Parse the URL to extract parameters (e.g., `id=123`) and route the user to the correct view.
- Test Thoroughly:
- Test with your app installed and uninstalled.
- Test by tapping links from Safari, Mail, Messages, and other apps.
- Test specific paths in your `apple-app-site-association` file, including those with `NOT` prefixes.
Fallback Behavior and Routing Logic
The core difference between Universal Links and Deep Links lies in their fallback behavior and how iOS routes them. Understanding this is crucial for a robust linking strategy. With Universal Links, the system's routing logic is intelligent. If your app is installed and configured correctly, tapping a Universal Link will open your app directly to the specified content, bypassing Safari entirely. If the app is *not* installed, the exact same URL will open in Safari, displaying the corresponding web page. This provides a seamless experience for the user regardless of their installation status. For example, if a user clicks `https://focuskit.app/challenge/456` in an email:- If FocusKit is installed, the app opens to challenge ID 456.
- If FocusKit is not installed, Safari opens to `https://focuskit.app/challenge/456`.
FAQ
Can I use both Universal Links and Deep Links for the same content?
Yes, you can configure both Universal Links and Deep Links (URL Schemes) for your app. However, Universal Links are generally preferred as they offer a superior user experience, including graceful fallback to a web page if the app isn't installed. iOS prioritizes Universal Links when both are present and applicable.My Universal Links aren't working. How do I debug them?
Start by verifying your `apple-app-site-association` file: ensure it's at the correct path (`/.well-known/` or root), served over HTTPS with a `200 OK` status, and has the `application/json` MIME type. Double-check your Xcode `Associated Domains` entitlement (`applinks:yourdomain.com`) matches your domain and that the capability is enabled in App Store Connect. On a device, you can use `log stream --predicate 'subsystem == "com.apple.SafariServices"'` in Xcode's Console or Terminal to see if iOS is attempting to fetch and process your AASA file.Do I need a specific web server configuration for the AASA file?
Yes, the AASA file must be served from an HTTPS URL and be directly accessible without redirects (other than the initial HTTP to HTTPS redirect). It needs to return a `200 OK` status and have a `Content-Type` header of `application/json`. Some servers might require specific configurations to handle files without extensions or within the `.well-known` directory correctly.What if my app gets uninstalled, then reinstalled? Do Universal Links still work?
Yes, Universal Links should still work. iOS periodically re-fetches the `apple-app-site-association` file to keep its associations up to date. After an app reinstall, the system will re-establish the association with your domain, although there might be a slight delay before the link works perfectly, depending on when iOS next fetches the file.Next Steps: Testing Your Link Strategy
Getting your Universal Links and Deep Links right is critical for a smooth user experience. Once you've implemented your chosen strategy, rigorous testing is non-negotiable. Test your links from various sources (email, social media, other apps) and on devices with and without your app installed. This helps catch any configuration issues before they impact real users. As you refine your app's presence, consider how users first encounter it. Tools like the App Store Listing Preview can help you visualize your app's entry points, ensuring every detail works together to convert interest into installs.Was this helpful?
Thanks — that helps me decide what to write next.
Questions or ideas?
I read every suggestion — drop yours on the feedback board.
Open feedback board →
Make your App Store screenshots free
LaunchShots is a free, in-browser screenshot maker. No signup, no watermark.
Open the app →
Comments (0)