iOS Universal Links
Universal Links are Apple's way of connecting websites to apps. When configured correctly, tapping a link opens your app directly — no browser, no redirect, no "Open in App?" prompt.
What you'll learn
- How iOS Universal Links work under the hood
- Configuring your apple-app-site-association file
- Troubleshooting common Universal Links issues
How Universal Links work
When a user taps a Universal Link:
- iOS checks the domain — Has this domain been associated with an app?
- AASA file verified — iOS cached the apple-app-site-association file when the app was installed
- App opens directly — No Safari, no interstitial, just your app
- Deep link data passed — Your app receives the full URL to handle
Universal Links are the gold standard for iOS deep linking. Unlike custom URL schemes (yourapp://), they work even if the app isn't installed (falling back to your website) and can't be hijacked by other apps.
The apple-app-site-association file
The AASA file tells iOS which URLs your app can handle. It lives at:
https://yourdomain.com/.well-known/apple-app-site-association
Example AASA file:
{
"applinks": {
"apps": [],
"details": [
{
"appID": "TEAMID.com.yourcompany.app",
"paths": ["*"]
}
]
}
}
Key fields
| Field | Description |
|---|---|
appID | Your Team ID + Bundle ID (e.g., ABC123.com.example.app) |
paths | URL paths your app handles (* for all, or specific patterns) |
The AASA file must be served over HTTPS with no redirects. iOS fetches it when your app is installed and periodically afterward. Changes can take 24-48 hours to propagate to all devices.
ULink handles AASA for you
When you configure your iOS app in ULink:
- Enter your Bundle ID and Team ID
- ULink automatically generates and serves the AASA file
- Your custom domain (or
ulink.to) is ready for Universal Links
No need to host the file yourself — ULink manages it.
App-side configuration
In your Xcode project:
1. Enable Associated Domains
Go to your target → Signing & Capabilities → Add "Associated Domains"
2. Add your domain
Add an entry for each domain:
applinks:yourdomain.com
applinks:links.yourdomain.com
For ULink's shared domain, add:
applinks:ulink.to
3. Handle incoming links
Implement the delegate method:
func application(_ application: UIApplication,
continue userActivity: NSUserActivity,
restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
guard userActivity.activityType == NSUserActivityTypeBrowsingWeb,
let url = userActivity.webpageURL else {
return false
}
// Handle the URL
return handleDeepLink(url)
}
onOpenURL modifier on your root view to handle incoming links. Works seamlessly with UIKit delegate methods.Testing Universal Links
On device (required)
Universal Links only work on physical devices, not simulators.
- Long-press a link in Notes or Safari
- You should see "Open in [Your App]" option
- Tapping the link directly should open your app
Debug with Apple's tools
Use the Associated Domains Diagnostics profile:
- Install from Apple's developer site
- Go to Settings → Developer → Associated Domains Diagnostics
- Enter your domain to see AASA fetch status
Verify AASA is correct
curl -I https://yourdomain.com/.well-known/apple-app-site-association
Should return 200 OK with Content-Type: application/json.
Troubleshooting
"Open in Safari" instead of app
- AASA file may not be cached yet — wait 24 hours after app install
- Check that Associated Domains entitlement matches your domain exactly
- Ensure AASA has no redirects and is served over HTTPS
Works in some places, not others
- Universal Links don't work when pasting into Safari's address bar
- They work from: Mail, Messages, Notes, social apps, other apps
- Safari has special behavior — it respects the user's choice to open in browser
Links stopped working
- Apple's CDN caches AASA files. Changes take time to propagate
- Check that your AASA file is still valid JSON
- Ensure your Team ID and Bundle ID haven't changed
If a user taps the breadcrumb to open a link in Safari, iOS remembers this preference. Future taps will open Safari until the user long-presses and chooses "Open in App" again.
Quick recap
- Universal Links provide seamless app opening without browser interstitials
- ULink automatically generates and serves your AASA file
- Add Associated Domains entitlement in Xcode
- Test on physical devices only — simulators don't support Universal Links
- Changes to AASA can take 24-48 hours to propagate