Implementation of Universal Links for iOS Application
Universal Links is a mechanism where link like https://example.com/product/123 opens app directly on right screen, bypassing browser. If app not installed — opens website. No custom schemes (myapp://product/123) that don't work in Safari and blocked by corporate MDM.
How it works and where it breaks
AASA file. On server at https://example.com/.well-known/apple-app-site-association must be JSON without file extension, with header Content-Type: application/json, accessible via HTTPS without redirects. Apple parses file on app install and caches on CDN — update may take up to 24 hours.
Most common error: server returns file with redirect from http to https, or with 301 to www-version domain. Apple doesn't follow redirects when downloading AASA. Check via curl -v https://example.com/.well-known/apple-app-site-association — must return 200 with correct Content-Type.
Format for iOS 13+ (applinks with details):
{
"applinks": {
"details": [{
"appIDs": ["TEAMID.com.example.app"],
"components": [
{ "/": "/product/*", "comment": "Product pages" },
{ "/": "/order/*" }
]
}]
}
}
App Entitlements. In Entitlements.plist need com.apple.developer.associated-domains with entry applinks:example.com. Forgotten entitlement — app simply doesn't receive universal link callback.
Handling in code. In AppDelegate or SceneDelegate implement application(_:continue:restorationHandler:) (UIKit) or onOpenURL (SwiftUI). Get NSUserActivity with type NSUserActivityTypeBrowsingWeb and webpageURL. Parse path, determine right screen, build navigation stack.
URL parsing should be robust: webpageURL may come with query parameters, fragments, uppercase. Use URLComponents instead of manual string parsing.
Testing. In simulator universal links work via xcrun simctl openurl booted 'https://example.com/product/123'. On real device — via Safari (long tap link → "Open in App"). Xcode → Diagnostics won't show AASA problem — need swcutil on Mac and Console.app for logs swcd (Apple's universal links daemon).
Scenarios and edge cases
Associated Domains Alternate Mode. For enterprise apps or staging environments add applinks:example.com?mode=developer to entitlements. In developer mode iOS doesn't cache AASA and requests file directly from server — convenient during development.
Multiple domains. App can handle multiple domains — just add multiple entries to entitlements. AASA needed on each domain separately.
Links from email clients. Gmail and Outlook apps on iOS wrap links through their redirect service. Universal link in this case doesn't work — Apple sees redirect URL, not target. This is platform limitation, not implementation bug.
What's included
- AASA file setup on server with needed path patterns
- Entitlements and Xcode configuration for all targets and schemes (Debug, Release, Staging)
- Handler implementation in
SceneDelegate/AppDelegatewith routing to right screens - Testing on real devices and via simulator
- Verification via Apple's validator (AASA Validator)
Timeline
Implementation with several path patterns and integration into existing navigation: 1–2 days. With multiple domains support and custom routing logic — 2–3 days. Cost calculated individually.







