Universal Link is een Apple-mechanisme (iOS 9+) waarmee webkoppelingen rechtstreeks in de app kunnen worden geopend, zonder Safari. Als de app niet is geïnstalleerd, wordt de koppeling naadloos in de browser geopend. De term is geïntroduceerd door Apple in 2015 op WWDC als onderdeel van Handoff en het Continuity-ecosysteem. Volgens Apple Developer biedt Universal Link een uniforme gebruikerservaring tussen web en native app zonder selectiedialogen.
Belangrijkste punten
Universal Link is een standaard HTTPS-koppeling van de vorm https://example.com/page die bij het klikken vanaf een iOS-apparaat de geïnstalleerde app opent in plaats van Safari. Het belangrijkste verschil met Custom URL Scheme: Universal Link vereist geen registratie van een aangepast schema (myapp://) — er wordt een gewoon domein gebruikt. Dit elimineert het probleem van URL Scheme hijacking, waarbij elke app hetzelfde schema kan registreren.
Apple introduceerde Universal Link op WWDC 2015 in het kader van iOS 9. Het mechanisme werd onderdeel van het Handoff- en Spotlight-ecosysteem: Universal Link werkt niet alleen in de browser, maar ook in Spotlight-zoekresultaten, in Mail, Messages en andere systeemapps. Bovendien wordt Universal Link ondersteund in watchOS en macOS — de gebruiker kan de app op de iPhone openen via een koppeling op de Mac.
Het belangrijkste voordeel: unieke URL. De ontwikkelaar beheert niet twee verschillende koppelingen (één voor web, één voor de app). Universal Link is dezelfde https-koppeling. Als de app is geïnstalleerd — wordt deze geopend. Zo niet — dan wordt dezelfde koppeling in Safari geopend als een gewone webpagina. Dit biedt een ideale fallback zonder verlies van verkeer.
Het Universal Link-mechanisme bestaat uit drie fasen: associatieverificatie, verwerking van de koppeling en fallback naar de browser. Elke fase is cruciaal voor een correcte werking. Als de associatie niet is geconfigureerd, behandelt iOS de koppeling als een gewone overgang naar Safari. Laten we elke fase in detail bekijken.
Bij de eerste klik op de koppeling downloadt iOS het bestand apple-app-site-association van de server op https://example.com/.well-known/apple-app-site-association. Het bestand bevat JSON met de Team ID en Bundle ID van de app, en een lijst met paden die de app moet openen. iOS cached dit bestand en controleert periodiek de actualiteit ervan (bij het bijwerken van de app, herstarten van het apparaat).
Het JSON-bestand apple-app-site-association moet via HTTPS toegankelijk zijn zonder omleidingen. De server moet Content-Type: application/json teruggeven. Belangrijk: het bestand heeft geen .json-extensie — iOS zoekt het strikt op het pad /.well-known/apple-app-site-association. Apple raadt ook aan om ondersteuning voor Universal Link in CDN toe te voegen en te controleren of het bestand niet wordt geblokkeerd door robots.txt.
// apple-app-site-association — minimale configuratie
{
"applinks": {
"apps": [],
"details": [
{
"appID": "TEAMID.com.example.app",
"paths": ["/product/*", "/profile/*", "/search"]
}
]
}
}
appID wordt gevormd als Team ID + Bundle ID (TEAMID.com.example.app). paths — een array van URL-patronen die de app moet verwerken. Je kunt *, ? en NOT-notatie gebruiken: ["NOT /admin/*", "/product/*"]. Paden worden in de volgorde van opsomming gecontroleerd: de eerste overeenkomst bepaalt het gedrag. Als het pad niet overeenkomt — wordt de koppeling in Safari geopend.
Na succesvolle verificatie van de associatie geeft iOS de koppeling door aan de app. De verwerking vindt plaats in AppDelegate via de methode application(_:continue:restorationHandler:) voor NSUserActivity of in SceneDelegate via scene(_:continue:). De ontwikkelaar ontvangt een NSUserActivity-object met het type NSUserActivityTypeBrowsingWeb, extraheert de URL en navigeert naar het juiste scherm.
// Verwerking van Universal Link in AppDelegate
func application(
_ application: UIApplication,
continue userActivity: NSUserActivity,
restorationHandler: @escaping UIUserActivityRestorationHandler
) -> Bool {
guard userActivity.activityType == NSUserActivityTypeBrowsingWeb,
let url = userActivity.webpageURL
else { return false }
// Navigatie naar scherm volgens URL
DeepLinkRouter.navigate(to: url)
return true
}
DeepLinkRouter in het bovenstaande voorbeeld is een aangepaste klasse die de URL parseert en de juiste navigatiecoördinator aanroept. Voor SwiftUI gebeurt de verwerking via de methode onOpenURL of de modifier environment(\.openURL). Het is belangrijk om niet alleen de voorgrondstart (foreground) te verwerken, maar ook het geval waarin de app niet is gestart (cold start): Universal Link opent in dit geval de app via de opstartopties.
Als de app niet is geïnstalleerd, opent iOS automatisch de Universal Link in Safari. Dit is het belangrijkste verschil met Custom URL Scheme: de gebruiker ziet geen foutmelding. Fallback is een standaard webpagina van hetzelfde domein. De ontwikkelaar kan op deze pagina een koppeling naar de App Store, productinformatie of alternatieve inhoud plaatsen.
Belangrijk: fallback kan niet worden aangepast op iOS-niveau. iOS opent gewoon de URL in Safari. Om verschillende inhoud te tonen aan gebruikers met en zonder geïnstalleerde app, gebruik je Smart App Banner (een meta-tag voor Safari die voorstelt de app te openen) of JavaScript-detectie van app-installatie. Apple biedt ook SKAdNetwork voor attributie van installaties via Universal Link.
Universal Link en traditionele Deep Link (Custom URL Scheme) lossen dezelfde taak op, maar verschillen fundamenteel in architectuur en veiligheid. Custom URL Scheme — een aangepast protocol (myapp://) dat wordt geregistreerd in Info.plist. Elke app kan hetzelfde schema (myapp://) registreren en iOS kan niet bepalen welke "echt" is. Dit wordt URL Scheme hijacking genoemd.
Universal Link lost het hijacking-probleem op door domeinverificatie. Alleen de domeineigenaar kan apple-app-site-association op zijn server plaatsen en de koppeling met een specifieke Bundle ID bevestigen. Twee apps kunnen niet dezelfde Universal Link registreren: als er een conflict ontstaat, geeft iOS prioriteit aan de laatst geïnstalleerde app of opent Safari.
Een ander verschil: Fallback. Custom URL Scheme heeft geen fallback — als de app niet is geïnstalleerd, toont de browser een foutmelding. Universal Link opent de website. Unieke URL betekent dat de SEO-waarde van de koppeling behouden blijft (de koppeling wordt geïndexeerd door Google) en de gebruiker met elk apparaat relevante inhoud ontvangt. Universal Link is een evolutionaire stap van deep link naar unified link.
| Kenmerk | Custom URL Scheme | Universal Link |
|---|---|---|
| Formaat | myapp://path | https://domain/path |
| Verificatie | Nee | apple-app-site-association |
| Veiligheid | Kwetsbaar voor hijacking | Alleen domeineigenaar |
| Fallback | Foutmelding | Website in Safari |
| iOS-versie | iOS 3+ | iOS 9+ |
Configuratie van Universal Link omvat een server- en clientgedeelte. Servergedeelte — plaatsing van het bestand apple-app-site-association op https://domain/.well-known/apple-app-site-association. Clientgedeelte — registratie van het domein in Associated Domains in Xcode (Capabilities → Associated Domains → applinks:example.com). Hierna ontvangt de app automatisch alle Universal Links voor het opgegeven domein.
Configuratiestappen:
Debuggen van Universal Link — een veelvoorkomende hoofdpijn voor iOS-ontwikkelaars. Belangrijkste oorzaken van niet-werkende koppelingen: bestand apple-app-site-association niet toegankelijk via HTTPS, onjuiste appID, Content-Type niet application/json, omleiding vanaf het pad /.well-known, caching van een oude versie (reset via Settings → Developer → Associated Domains Development). Apple biedt de tool "Validation Checker" in Apple Developer Console voor het testen van de associatie.
Branch en andere MMP-platforms vereenvoudigen de configuratie van Universal Link: ze genereren apple-app-site-association automatisch en hosten het op hun eigen domein. De ontwikkelaar hoeft alleen het Branch-domein toe te voegen aan Associated Domains en de SDK te integreren. Dit is vooral handig voor startups die geen eigen serverinfrastructuur hebben voor het hosten van het AASA-bestand.
Universal Link heeft verschillende beperkingen. Ten eerste: het bestand apple-app-site-association moet strikt via HTTPS toegankelijk zijn (HTTP wordt niet ondersteund). Ten tweede: de koppeling moet naar hetzelfde domein leiden dat is opgegeven in Associated Domains. Cross-domein Universal Links werken niet — voor elk domein is een aparte vermelding in Capabilities en een apart AASA-bestand nodig. Ten derde: Universal Link werkt niet in WKWebView — alleen in Safari en systeemcomponenten.
Compatibiliteit: iOS 9.0+ (Universal Link), watchOS 6.0+ (Handoff Universal Link), macOS 10.15+ (Catalyst en Mac-apps). In oudere versies van iOS wordt de koppeling in Safari geopend. Dit betekent dat op iOS 8 (minder dan 1% van de apparaten) Universal Link niet werkt. Het wordt aanbevolen om ook Custom URL Scheme te ondersteunen als fallback voor oudere apparaten, als het publiek gebruikers met verouderde versies omvat.
iOS 16+ wijzigingen: Apple heeft de verwerking van Universal Link voor SwiftUI verbeterd. Er is een nieuwe modifier environment(\.openURL) verschenen met de mogelijkheid van uitgestelde verwerking. iOS 16 maakt het ook mogelijk om Universal Link in de app te openen via SFSafariViewController. Voor iOS 16-gebruikers wordt aanbevolen om volledig over te stappen op SwiftUI-verwerking van Universal Link, waarbij AppDelegate-code alleen voor achterwaartse compatibiliteit behouden blijft.
Veelgestelde vragen
Universal Link gebruikt een standaard HTTPS-URL en wordt geverifieerd via een bestand op de server. Custom URL Scheme gebruikt een aangepast protocol (myapp://) zonder verificatie, wat het kwetsbaar maakt voor overname door een andere app die hetzelfde schema heeft geregistreerd.
Het bestand wordt in de hoofdmap van de HTTPS-server geplaatst op /.well-known/apple-app-site-association (zonder .json-extensie). De server moet Content-Type: application/json teruggeven. Belangrijk: geen omleidingen, het bestand moet direct toegankelijk zijn.
Belangrijkste oorzaken: onjuiste Team ID of Bundle ID in het AASA-bestand, bestand niet toegankelijk via HTTPS, omleiding, onjuiste Content-Type, caching van een oude versie. Controleer via Developer → Associated Domains Development en reset de cache door het apparaat opnieuw op te starten.
Nee — Universal Link vereist een HTTPS-server waarop apple-app-site-association is geplaatst. Zonder domein werkt Universal Link niet. Alternatief: Custom URL Scheme (minder veilig) of externe diensten (Branch, Firebase) met een eigen domein.
Nee — Universal Link is exclusieve Apple-technologie voor iOS, iPadOS, watchOS en macOS. Op Android heet de tegenhanger App Link (Android 6.0+), die Digital Asset Links (assetlinks.json) gebruikt in plaats van apple-app-site-association.
Samenvatting
We ontwikkelen een mobiele applicatie turnkey
IT Sectr creëert sinds 2017 iOS- en Android-applicaties voor startups en bedrijven. We adviseren u en stellen de beste oplossing voor.
Lees ook