Universal Link è un meccanismo Apple (iOS 9+) che consente di aprire i link web direttamente nell'app, saltando Safari. Se l'app non è installata, il link si apre perfettamente nel browser. Il termine è stato introdotto da Apple nel 2015 al WWDC come parte di Handoff e dell'ecosistema Continuity. Secondo Apple Developer, Universal Link offre un'esperienza utente unificata tra web e app nativa senza finestre di dialogo di scelta.
Punti chiave
Universal Link è un link HTTPS standard come https://example.com/page che, quando toccato su un dispositivo iOS, apre l'app installata invece di Safari. La differenza principale da Custom URL Scheme: Universal Link non richiede la registrazione di uno schema personalizzato (myapp://) — utilizza un dominio normale. Questo elimina il problema dell'URL Scheme hijacking, dove qualsiasi app può registrare lo stesso schema.
Apple ha presentato Universal Link al WWDC 2015 come parte di iOS 9. Il meccanismo è diventato parte dell'ecosistema Handoff e Spotlight: Universal Link funziona non solo nel browser, ma anche nei risultati di ricerca Spotlight, Mail, Messages e altre app di sistema. Inoltre, Universal Link è supportato su watchOS e macOS — l'utente può aprire un'app sull'iPhone tramite un link sul Mac.
Il vantaggio chiave: URL unico. Lo sviluppatore non gestisce due link diversi (uno per il web, uno per l'app). Universal Link è lo stesso link https. Se l'app è installata — si apre l'app. Altrimenti — lo stesso link si apre in Safari come una normale pagina web. Questo offre un fallback ideale senza perdita di traffico.
Il meccanismo di Universal Link consiste in tre fasi: verifica dell'associazione, gestione del link e fallback al browser. Ogni fase è critica per il corretto funzionamento. Se l'associazione non è configurata, iOS tratta il link come un normale reindirizzamento a Safari. Esaminiamo ogni fase in dettaglio.
Al primo tocco su un link, iOS scarica il file apple-app-site-association dal server all'indirizzo https://example.com/.well-known/apple-app-site-association. Il file contiene JSON con il Team ID e Bundle ID dell'app, insieme a un elenco di percorsi che l'app deve aprire. iOS memorizza nella cache questo file e ne verifica periodicamente la freschezza (all'aggiornamento dell'app, al riavvio del dispositivo).
Il file JSON apple-app-site-association deve essere accessibile via HTTPS senza reindirizzamenti. Il server deve restituire Content-Type: application/json. È importante che il file non abbia estensione .json — iOS lo cerca rigorosamente in /.well-known/apple-app-site-association. Apple raccomanda anche di aggiungere il supporto Universal Link nel CDN e di verificare che il file non sia bloccato da robots.txt.
// apple-app-site-association — configurazione minima
{
"applinks": {
"apps": [],
"details": [
{
"appID": "TEAMID.com.example.app",
"paths": ["/product/*", "/profile/*", "/search"]
}
]
}
}
appID è formato come Team ID + Bundle ID (TEAMID.com.example.app). paths è un array di modelli URL che l'app deve gestire. Si possono utilizzare *, ? e la notazione NOT: ["NOT /admin/*", "/product/*"]. I percorsi vengono controllati nell'ordine di enumerazione: la prima corrispondenza determina il comportamento. Se il percorso non corrisponde — il link si apre in Safari.
Dopo la verifica positiva dell'associazione, iOS passa il link all'app. La gestione viene effettuata in AppDelegate tramite il metodo application(_:continue:restorationHandler:) per NSUserActivity, o in SceneDelegate tramite scene(_:continue:). Lo sviluppatore riceve un oggetto NSUserActivity di tipo NSUserActivityTypeBrowsingWeb, estrae l'URL e naviga alla schermata corrispondente.
// Gestione di 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 }
// Navigare alla schermata secondo l'URL
DeepLinkRouter.navigate(to: url)
return true
}
DeepLinkRouter nell'esempio sopra è una classe personalizzata che analizza l'URL e chiama il coordinatore di navigazione corrispondente. Per SwiftUI, la gestione viene effettuata tramite il metodo onOpenURL o il modificatore environment(\.openURL). È importante gestire non solo l'avvio in primo piano, ma anche il caso in cui l'app non era in esecuzione (cold start): Universal Link apre l'app tramite le opzioni di avvio in questo caso.
Se l'app non è installata, iOS apre automaticamente Universal Link in Safari. Questa è una differenza fondamentale da Custom URL Scheme: l'utente non vede un errore. Il fallback è la pagina web standard dello stesso dominio. Lo sviluppatore può inserire un link all'App Store, informazioni sul prodotto o contenuti alternativi su questa pagina.
Importante: il fallback non può essere personalizzato a livello iOS. iOS apre semplicemente l'URL in Safari. Per mostrare contenuti diversi per utenti con e senza l'app installata, utilizzare Smart App Banner (un meta tag per Safari che propone di aprire l'app) o il rilevamento dell'installazione tramite JavaScript. Apple fornisce anche SKAdNetwork per l'attribuzione delle installazioni tramite Universal Link.
Universal Link e il Deep Link tradizionale (Custom URL Scheme) risolvono lo stesso problema, ma differiscono fondamentalmente per architettura e sicurezza. Custom URL Scheme è un protocollo personalizzato (myapp://) registrato in Info.plist. Qualsiasi app può registrare lo stesso schema (myapp://), e iOS non può determinare quale sia quello “reale”. Questo si chiama URL Scheme hijacking.
Universal Link risolve il problema dell'hijacking attraverso la verifica del dominio. Solo il proprietario del dominio può posizionare apple-app-site-association sul proprio server, confermando la connessione con un Bundle ID specifico. Due app non possono registrare lo stesso Universal Link: se sorge un conflitto, iOS dà priorità all'app installata più recentemente o apre Safari.
Un'altra differenza: Fallback. Custom URL Scheme non ha fallback — se l'app non è installata, il browser mostra un errore. Universal Link apre il sito web. Un URL unico significa che il valore SEO del link viene preservato (Google indicizza il link) e un utente con qualsiasi dispositivo riceve contenuti pertinenti. Universal Link è un passo evolutivo dal deep link al link unificato.
| Caratteristica | Custom URL Scheme | Universal Link |
|---|---|---|
| Formato | myapp://path | https://domain/path |
| Verifica | No | apple-app-site-association |
| Sicurezza | Vulnerabile a hijacking | Solo il proprietario del dominio |
| Fallback | Errore | Sito web in Safari |
| Versione iOS | iOS 3+ | iOS 9+ |
La configurazione di Universal Link include la parte server e la parte client. La parte server — posizionare il file apple-app-site-association all'indirizzo https://domain/.well-known/apple-app-site-association. La parte client — registrare il dominio in Associated Domains in Xcode (Capabilities → Associated Domains → applinks:example.com). Dopo di che, l'app riceve automaticamente tutti gli Universal Link per il dominio specificato.
Passaggi di configurazione:
Il debug di Universal Link è un mal di testa comune per gli sviluppatori iOS. Cause principali di link non funzionanti: file apple-app-site-association non accessibile via HTTPS, appID errato, Content-Type diverso da application/json, reindirizzamento dal percorso /.well-known, memorizzazione nella cache della versione vecchia (reimpostare tramite Settings → Developer → Associated Domains Development). Apple fornisce lo strumento Validation Checker in Apple Developer Console per testare l'associazione.
Branch e altre piattaforme MMP semplificano la configurazione di Universal Link: generano automaticamente apple-app-site-association e lo ospitano sul proprio dominio. Lo sviluppatore deve solo aggiungere il dominio Branch in Associated Domains e integrare l'SDK. Ciò è particolarmente conveniente per le startup che non hanno la propria infrastruttura server per ospitare il file AASA.
Universal Link ha diverse limitazioni. Prima: il file apple-app-site-association deve essere accessibile rigorosamente via HTTPS (HTTP non è supportato). Seconda: il link deve puntare allo stesso dominio specificato in Associated Domains. Gli Universal Link tra domini diversi non funzionano — ogni dominio richiede una voce separata in Capabilities e un file AASA separato. Terza: Universal Link non funziona in WKWebView — solo in Safari e componenti di sistema.
Compatibilità: iOS 9.0+ (Universal Link), watchOS 6.0+ (Handoff Universal Link), macOS 10.15+ (Catalyst e app Mac). Sulle versioni precedenti di iOS, il link si apre in Safari. Ciò significa che su iOS 8 (meno dell'1% dei dispositivi) Universal Link non funzionerà. Si raccomanda di supportare anche Custom URL Scheme come fallback per i dispositivi vecchi se il pubblico include utenti con versioni obsolete.
Modifiche in iOS 16+: Apple ha migliorato la gestione di Universal Link per SwiftUI. È stato introdotto un nuovo modificatore environment(\.openURL) con capacità di elaborazione differita. iOS 16 consente anche di aprire Universal Link nell'app tramite SFSafariViewController. Per gli utenti iOS 16, si raccomanda di passare completamente alla gestione di Universal Link con SwiftUI, mantenendo il codice AppDelegate solo per la compatibilità all'indietro.
Domande frequenti
Universal Link utilizza un URL HTTPS standard e viene verificato tramite un file sul server. Custom URL Scheme utilizza un protocollo personalizzato (myapp://) senza verifica, rendendolo vulnerabile all'intercettazione da parte di un'altra app che ha registrato lo stesso schema.
Il file viene posizionato nella radice del server HTTPS in /.well-known/apple-app-site-association (senza estensione .json). Il server deve restituire Content-Type: application/json. Importante: nessun reindirizzamento, il file deve essere direttamente accessibile.
Cause principali: Team ID o Bundle ID errati nel file AASA, file non accessibile via HTTPS, reindirizzamento, Content-Type errato, cache della versione vecchia. Verificare tramite Developer → Associated Domains Development e riavviare il dispositivo per svuotare la cache.
No — Universal Link richiede un server HTTPS che ospiti apple-app-site-association. Senza un dominio, Universal Link non funziona. Alternative: Custom URL Scheme (meno sicuro) o servizi di terze parti (Branch, Firebase) con il proprio dominio.
No — Universal Link è una tecnologia esclusiva Apple per iOS, iPadOS, watchOS e macOS. Su Android, l'equivalente si chiama App Link (Android 6.0+), che utilizza Digital Asset Links (assetlinks.json) invece di apple-app-site-association.
Riepilogo
Svilupperemo un'applicazione mobile chiavi in mano
IT Sectr crea applicazioni iOS e Android per startup e aziende dal 2017. Ti consulteremo e ti proporremo la soluzione migliore.
Leggi anche