Un deep link è semplicemente un URL che il sistema operativo consegna a un'app invece che a un browser. Tocca il link su un dispositivo che ha l'app installata e l'app si apre alla schermata giusta. Toccalo su un dispositivo senza l'app e il browser segue il redirect verso il fallback web. Un URL, due esiti, nessuno shim JavaScript, nessun SDK di terze parti richiesto nella maggior parte dei setup.
I team tendono spesso ad acquistare troppo qui. Branch.io, Adjust, AppsFlyer - i loro materiali di marketing puntano sul deferred deep linking: tocchi il link prima di installare l'app, installi, e l'app si apre esattamente al contenuto che avevi cliccato. Questa funzionalità è genuinamente complessa e richiede un trucco di fingerprinting lato server o di corrispondenza tramite clipboard, perché il routing OS dei link è dormiente finché l'app non è installata. Ma il deferred deep linking è una fetta del problema. Il caso più comune, "il link si apre nell'app già installata", è interamente risolto dalle primitive native del sistema operativo che Apple e Google hanno reso disponibili rispettivamente nel 2015 e nel 2015–16, e che funzionano senza nulla più di un dominio che controlli e due file JSON.
Questo post parla di quei due file JSON.
TL;DR#
- Apple Universal Links (iOS 9+) e Android App Links (Android 6.0+) gestiscono il flusso "apri nell'app se installata, fallback web se non lo è" senza SDK di terze parti.
- Entrambi richiedono un dominio che controlli, servito su HTTPS, con un file di associazione validato in
/.well-known/. Il sistema operativo recupera e mette in cache il file all'installazione dell'app, non a ogni tocco. - Uno shortener di URL con un dominio personalizzato come
go.acme.exampleserve entrambi i file e diventa il link che attiva il routing dell'app - il link breve è il deep link. - Cosa aggiunge l'SDK che le primitive del sistema operativo non forniscono: deferred deep linking, attribuzione probabilistica delle installazioni e stitching dell'identità cross-platform. Se ne hai bisogno, il costo dell'SDK è giustificato. Se non ne hai bisogno, stai pagando per funzionalità che non usi.
Le primitive native del sistema operativo#
Apple ha introdotto Universal Links in iOS 9 (2015). Android ha rilasciato App Links in Android 6.0 Marshmallow (sempre nel 2015, distribuito ai dispositivi nel corso del 2016). Entrambi seguono lo stesso modello concettuale: il sistema operativo afferma una relazione verificata tra un dominio e un'app, e quando viene toccato un URL di quel dominio, il sistema operativo lo instrada verso l'app anziché verso il browser.
La verifica è reciproca e offline-first. All'installazione dell'app, il sistema operativo recupera un file di associazione dal tuo dominio e lo mette in cache. Il fetcher di Apple è documentato su developer.apple.com/ios/universal-links/ (consultato il 12-05-2026); quello equivalente di Google è su developer.android.com/training/app-links (consultato il 12-05-2026). Nessuno di questi fetch avviene al momento del tocco su un dispositivo caldo - la cache fa sì che la decisione di routing non costi alcun round trip di rete.
Il redirect stesso è uno standard HTTP 302. Il sistema operativo lo intercetta prima che il browser si carichi, controlla la sua cache locale e consegna l'URL all'app se viene trovata una corrispondenza. Una volta che la cache è calda, l'intera decisione è locale. L'edge che serve il link breve emette il redirect e il sistema operativo prende il controllo.
I due file#
apple-app-site-association#
Il file AASA deve essere servito su https://yourdomain.example/.well-known/apple-app-site-association (Apple controlla anche il percorso apex https://yourdomain.example/apple-app-site-association per compatibilità legacy, ma il percorso .well-known è lo standard attuale). Deve essere servito su HTTPS con una catena di certificati valida e con un header Content-Type: application/json. Il fetcher CDN di Apple rifiuta i file serviti con il Content-Type sbagliato - questo è uno degli errori di configurazione più comuni in produzione.
Il riferimento completo al formato si trova su developer.apple.com/documentation/xcode/supporting-associated-domains.
Una struttura AASA minima:
{
"applinks": {
"details": [
{
"appIDs": ["ABCDE12345.com.example.acme"],
"components": [
{
"/": "/spring-*",
"comment": "Match any path starting with /spring-"
},
{
"/": "/campaigns/*"
}
]
}
]
}
}
appIDs è la concatenazione del tuo Apple Team ID e dell'identificatore del bundle dell'app, separati da un punto. L'array components controlla quali percorsi attivano il routing dell'app; tutto ciò che non corrisponde a un componente ricade nel browser. Puoi registrare più app nell'array details - utile se hai una variante consumer e una enterprise dello stesso prodotto sullo stesso dominio.
Un dettaglio che vale la pena enunciare chiaramente: "/" con un pattern wildcard come /spring-* è una corrispondenza del prefisso del percorso. Il parser AASA di Apple supporta la sintassi dei pattern definita nella documentazione Xcode, inclusi * (qualsiasi sottostringa), ? (qualsiasi singolo carattere) e gli oggetti di esclusione. Se vuoi corrispondere a ogni percorso del dominio, usa "/" : "/*". Se vuoi escludere un percorso specifico dal routing dell'app - diciamo che la pagina /account/delete dovrebbe aprirsi sempre nel browser - aggiungi un oggetto di esclusione prima del wildcard:
{
"/": "/account/delete",
"exclude": true
}
Le regole vengono valutate dall'inizio alla fine. Metti le esclusioni prima dei wildcard.
assetlinks.json#
Il file Digital Asset Links di Android si trova su https://yourdomain.example/.well-known/assetlinks.json. La specifica è mantenuta da Google su developers.google.com/digital-asset-links/v1/getting-started.
[
{
"relation": ["delegate_permission/common.handle_all_urls"],
"target": {
"namespace": "android_app",
"package_name": "com.example.acme",
"sha256_cert_fingerprints": [
"AA:BB:CC:DD:EE:FF:00:11:22:33:44:55:66:77:88:99:AA:BB:CC:DD:EE:FF:00:11:22:33:44:55:66:77:88:99"
]
}
}
]
package_name è l'application ID della tua app sul Play Store. sha256_cert_fingerprints è l'impronta SHA-256 del certificato usato per firmare l'APK - non SHA-1, non MD5. Puoi trovare l'impronta nella Play Console sotto Integrità dell'app, o eseguendo keytool -list -v -keystore your.keystore. Se rilasci sia una build di debug che una di produzione, includi entrambe le impronte nell'array.
A differenza del file AASA, il file di associazione di Android non supporta il filtraggio per percorso a livello di file. La corrispondenza dei percorsi per App Links viene effettuata in AndroidManifest.xml tramite <intent-filter> con android:pathPrefix, android:pathPattern, o il più recente android:pathAdvancedPattern (disponibile da Android 12). Il file assetlinks.json afferma la proprietà del dominio; il manifest dichiara quali percorsi gestisce l'app.
Come si inserisce uno shortener di URL#
Un link breve come go.acme.example/spring-launch è semplicemente un URL su un dominio. Dal punto di vista del sistema operativo, se go.acme.example ha un file AASA o assetlinks.json valido, qualsiasi tocco su un link sotto quel dominio è idoneo per il routing verso l'app.
Questa è la configurazione che supportiamo direttamente sui domini personalizzati con Elido. Quando registri go.acme.example come dominio personalizzato nel tuo workspace, Elido serve il redirect HTTPS per ogni slug sotto quel dominio. Tu servi i due file di associazione dallo stesso dominio - o dal tuo origin dietro un path proxy, o tramite il proprio server HTTPS del dominio. Il redirect edge si attiva; il sistema operativo lo intercetta prima che il browser si carichi, consulta la sua cache AASA/App Links e apre l'app se viene trovata una corrispondenza.
L'architettura è descritta in maggior dettaglio nel post su custom-domains-for-short-links - il setup TLS e CNAME si applicano qui esattamente come descritto lì. Il livello di deep link è aggiuntivo: stesso dominio, stesso redirect, due file JSON in più.
Per i team di prodotto che usano link brevi per l'onboarding mobile - codici referral, link di invito, flussi "condividi una ricetta" - questo pattern copre quasi tutto senza aggiungere dipendenze SDK al binario dell'app.
Cosa aggiunge l'SDK#
Tre capacità che le primitive native del sistema operativo non forniscono:
Deferred deep linking. Un utente tocca il tuo link prima di installare l'app. Al primo avvio dopo l'installazione, l'app si apre al contenuto esatto che aveva cliccato. iOS Universal Links e Android App Links sono silenziosi quando l'app non è installata - l'URL va nel browser, l'intento viene perso. Recuperarlo richiede una corrispondenza di fingerprint lato server (IP + User-Agent + timestamp, probabilistica) o il trucco della clipboard di iOS. Branch, Adjust e AppsFlyer implementano entrambi; i casi limite attorno ai prompt App Tracking Transparency e al comportamento di Safari rendono non banale farlo da soli.
Attribuzione delle installazioni su scala. Il percorso nativo del sistema operativo ti fornisce l'apertura dell'app con il percorso URL, ma se l'app non era installata al primo tocco, la catena di attribuzione è spezzata. Riconciliare i clic con le installazioni tramite SKAN su iOS e Play Install Referrer su Android è fattibile senza un SDK a pagamento, ma richiede il lavoro di integrazione che i vendor di attribuzione hanno già fatto.
Identity stitching cross-platform. Collegare un tocco a un indirizzo email, un contatto CRM o una sessione web. Il percorso nativo del sistema operativo è anonimo dalla prospettiva del servizio di link. I vendor SDK mantengono un device graph persistente. Costruirlo da soli è un progetto sostanziale di infrastruttura dati.
Se nessuno di questi tre casi si applica, le primitive del sistema operativo ti coprono. Se uno è rilevante, definiscine l'ambito con precisione - potresti avere bisogno solo del deferred deep linking, una superficie API, non dell'intero SDK.
Cookbook di configurazione#
Requisiti DNS e HTTPS#
Entrambi i file devono essere serviti su HTTPS dal dominio i cui link si vuole fare deep-link. Il certificato deve concatenarsi a una CA radice pubblica; i certificati self-signed fanno fallire silenziosamente sia il fetcher di validazione di Apple che quello di Google. I certificati Let's Encrypt funzionano bene.
Il TLS del dominio non deve nemmeno reindirizzare il percorso /.well-known/ prima di servire il file. Se il tuo server emette un redirect www. prima che il fetcher di Apple riesca a raggiungere https://yourdomain.example/.well-known/apple-app-site-association, il fetch fallisce. Il fetcher di Apple segue fino a un redirect, ma quello di Google per assetlinks non segue i redirect affatto - il file deve essere esattamente al percorso indicato, senza redirect.
iOS: entitlement Associated Domains#
In Xcode, nella scheda Signing & Capabilities del tuo target, aggiungi l'entitlement Associated Domains con il valore applinks:go.acme.example. Se stai testando su una build di sviluppo (non distribuita tramite TestFlight o App Store), aggiungi ?mode=developer al valore dell'entitlement: applinks:go.acme.example?mode=developer. Questo dice al sistema operativo di effettuare di nuovo il fetch dell'AASA a ogni avvio invece di usare la cache del momento dell'installazione - utile per iterare sui pattern dei percorsi senza dover reinstallare dallo Store ogni volta.
La CDN di Apple che recupera il tuo file AASA è la propria infrastruttura di Apple, non il dispositivo stesso. Apple effettua il pre-fetch e mette in cache i file AASA dal tuo dominio e li consegna ai dispositivi durante l'installazione dell'app, il che significa che il file deve essere raggiungibile dai crawler di Apple, non solo dal dispositivo dell'utente finale. Ciò significa anche che c'è un ritardo di propagazione - le modifiche al tuo file AASA possono impiegare ore per raggiungere tutti i dispositivi tramite la cache di Apple. Per i developer che necessitano di iterare rapidamente sui pattern dei percorsi, l'entitlement ?mode=developer bypassa la CDN di Apple e effettua il fetch direttamente dal tuo server.
Android: App Links nel manifest#
In AndroidManifest.xml, all'interno dell'activity che deve gestire i deep link:
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:scheme="https"
android:host="go.acme.example"
android:pathPrefix="/campaigns/" />
</intent-filter>
android:autoVerify="true" indica ad Android di tentare la verifica del dominio rispetto a assetlinks.json. Senza di esso, l'utente vede un foglio di disambiguazione a ogni tocco invece di un'apertura diretta nell'app. La verifica avviene all'installazione; il dispositivo contatta https://go.acme.example/.well-known/assetlinks.json e controlla che l'impronta del certificato dell'app installata sia nell'elenco.
Validatori ed errori comuni#
Apple fornisce un validatore su search.developer.apple.com/appsearch-validation-tool/ che controlla se la CDN di Apple riesce a recuperare e analizzare il tuo file AASA. Inserisci il tuo dominio e restituisce un risultato di analisi valido o un errore specifico. Fallimenti comuni:
- Content-Type errato. Se il tuo server restituisce
text/plainoapplication/octet-stream, il validatore segnala il file come illeggibile anche se il JSON è valido. ImpostaContent-Type: application/jsonesplicitamente. appIDsmancante o non corrispondente. Il prefisso Team ID inappIDsdeve corrispondere esattamente al Team ID nel tuo account Apple Developer, incluse le maiuscole. Un singolo carattere errato fallisce silenziosamente al momento del tocco.- Problema con la catena di certificati. Se il tuo dominio serve un certificato che non si concatena a una radice pubblica (comune negli ambienti di staging con root CA locali), il fetcher di Apple rifiuta il file.
Il validatore di Google è il Digital Asset Links API: https://digitalassetlinks.googleapis.com/v1/statements:list?source.web.site=https://go.acme.example&relation=delegate_permission/common.handle_all_urls. La risposta JSON elenca tutte le istruzioni che Google ha verificato per il tuo dominio. Se la risposta è vuota o manca il tuo package name, Android non verificherà automaticamente l'app all'installazione. Fallimenti comuni:
- Redirect sul percorso assetlinks. Come indicato: il fetcher di Google non segue i redirect.
- Impronta del certificato errata. L'APK di debug e l'APK di release sono firmati con chiavi diverse. Se hai elencato solo l'impronta di release, le build di debug non vengono verificate. Elenca entrambe.
- File servito con CORS ma header errato per la richiesta di verifica. Il fetcher non si preoccupa del CORS, ma alcune configurazioni CDN restituiscono 403 su
GETda un range IP Google se il percorso non è nella lista consentita della cache. Verifica che/.well-known/assetlinks.jsonrestituisca 200 da un client HTTP esterno, non solo dal tuo browser.
Il compromesso espresso chiaramente#
Rimuovere l'SDK per il deep-linking risparmia circa 150–250KB di dimensione del binario compresso ed elimina una chiamata API per installazione ai server del vendor di attribuzione. Ciò rimuove una relazione di condivisione dati dalla tua informativa sulla privacy e può semplificare i registri del trattamento dei dati GDPR. Guadagni reali, ma modesti.
Il costo è che l'attribuzione al momento dell'installazione diventa approssimativa o assente. Se un utente tocca il tuo link prima di installare l'app, vedrai l'installazione in App Store Connect o Play Console ma non la collegherai al tocco specifico del link. Puoi comunque eseguire esperimenti con smart link per confrontare quali campagne generano più installazioni - i segnali relativi sopravvivono - ma l'attribuzione per dispositivo e per clic richiede il livello di fingerprinting dell'SDK.
Per i team in fase iniziale dove il CPI per canale non guida ancora le decisioni di budget, iniziare con le primitive del sistema operativo è il percorso sensato. Aggiungere un SDK di attribuzione in seguito, quando i dati diventano effettivamente azionabili.
Per la guida di configurazione per i developer sul deep link di Elido, lo schema completo del flusso di verifica del dominio, la configurazione del proxy AASA e le opzioni di serving di assetlinks.json sono documentati lì. La pagina delle soluzioni per i team di prodotto copre i casi d'uso più ampi di smart link e mobile linking.
Marius Voß è DevRel + edge infra di Elido. Si occupa dei servizi edge-redirect e domain-manager.
Prova Elido
Incolla un URL, ottieni un link breve
Senza registrazione. Il link vive 30 giorni. Iscriviti per conservarlo.
Gratis, nessuna registrazione richiesta · 2 al giorno