11 min di letturaFunzionalità

Deep Link Senza SDK: Universal Links e App Links

Apri la tua app da un link con due file JSON e senza SDK. Come funzionano Universal Links iOS e App Links Android con un dominio di link brevi, e i limiti.

Marius Voß
DevRel · edge infra

Un deep link è un URL che il sistema operativo passa a un'app invece che a un browser. Toccalo con l'app installata e l'app si apre. Senza l'app, il browser carica la pagina web. Su iOS si chiama Universal Links, su Android App Links, e nessuno dei due richiede un SDK.

La configurazione è di due file JSON su un dominio che controlli, più un entitlement o un intent filter nell'app. Qui sotto: entrambi i file, come si inserisce un dominio di link brevi, la parte che la maggior parte delle guide salta (l'app riceve l'URL breve, non la destinazione del redirect) e i tre compiti che un SDK svolge ancora meglio.

Oggi conta più di prima. Google ha chiuso Firebase Dynamic Links il 25 agosto 2025, e le sue FAQ ora restituiscono HTTP 404 per quei link (FAQ di supporto Firebase, consultate il 2026-10-24). Quelle FAQ elencano un vendor per la piena parità di funzioni, e App Links più Universal Links per le app che devono solo aprirsi quando installate. Per il caso dalla stampa all'installazione, un QR code per i download di app mette lo stesso routing dietro un codice scansionabile.

In breve

  • Android App Links (Android 6, API 23, e successivi) e iOS Universal Links coprono "apri nell'app se installata, pagina web se no" senza alcun SDK di terze parti.
  • Ognuno richiede un dominio che controlli, servito su HTTPS, con un file di associazione sotto /.well-known/.
  • Su un dominio di link brevi, l'app viene avviata con l'URL breve. Il codice della tua app deve risolverlo in una schermata. Il 302 non viene mai eseguito.
  • Gli SDK si guadagnano ancora il loro costo per il deferred deep linking, l'attribuzione delle installazioni e lo stitching dell'identità. Saltali se non ti servono.

Come il sistema operativo decide di aprire la tua app

Entrambi i sistemi asseriscono una relazione verificata tra un dominio e un'app. La documentazione di Android dice che gli App Links permettono agli URL verificati di un sito web di "immediately open corresponding content in your Android app, without requiring the user to select your app from a disambiguation dialog", e che gli utenti senza l'app "go to your website instead - no 404s, no errors" (developer.android.com/training/app-links/about, consultato il 2026-10-24).

Android verifica al momento dell'installazione. Quando un intent filter porta android:autoVerify="true", un dispositivo con Android 6 o successivo controlla gli host dichiarati rispetto a https://hostname/.well-known/assetlinks.json mentre l'app viene installata (developer.android.com/training/app-links/verify-android-applinks, consultato il 2026-10-24). Attendi almeno 20 secondi per quel controllo prima di testare. Su Android 15 e successivi, la riverifica viene eseguita anche periodicamente, e le modifiche al file possono impiegare fino a sette giorni a propagarsi. Android 14 e precedenti recepiscono le modifiche solo all'installazione o all'aggiornamento.

Le pagine sviluppatori di Apple (developer.apple.com, Supporting associated domains e Supporting universal links) non si sono visualizzate nel mio fetch del 2026-10-24, quindi non cito il comportamento di Apple oltre ciò che mostrano i suoi esempi pubblicati: il file sta in /.well-known/apple-app-site-association, l'app dichiara applinks:your-domain nel suo entitlement Associated Domains, e un Universal Link raggiunge l'app come user activity di navigazione web che porta l'URL. Controlla la pagina Apple attuale prima di rilasciare, soprattutto per la cache e il comportamento in modalità sviluppo.

La conseguenza per i link brevi ne discende direttamente. Il sistema operativo decide in base all'URL toccato. Ciò avviene prima di qualsiasi richiesta al tuo server. Se il dominio di quell'URL è verificato per la tua app, l'app si apre con quell'URL. Non avviene alcuna richiesta HTTP al link breve, quindi nessun redirect viene eseguito.

I due file

Un file per piattaforma, ciascuno in un percorso fisso sullo stesso dominio.

apple-app-site-association

Il file AASA deve essere servito a https://yourdomain.example/.well-known/apple-app-site-association. Servilo su HTTPS con una catena di certificati valida, uno stato 200 e Content-Type: application/json, e senza redirect.

Il riferimento di formato di Apple è Supporting associated domains; la sua pagina non si è visualizzata per me il 2026-10-24, quindi considera l'esempio qui sotto come la forma comunemente pubblicata e verificalo su quella pagina.

Una forma 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 del bundle identifier della tua app, separati da un punto. L'array components controlla quali percorsi attivano il routing verso l'app; tutto ciò che non corrisponde a un componente ricade sul 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 da dire chiaramente: "/" con un pattern wildcard come /spring-* è una corrispondenza di prefisso del percorso. La sintassi dei pattern nello stesso riferimento include * (qualsiasi sottostringa), ? (qualsiasi singolo carattere) e oggetti di esclusione. Se vuoi far corrispondere ogni percorso del dominio, usa "/" : "/*". Se vuoi escludere un percorso specifico dal routing verso l'app - diciamo che la tua pagina /account/delete deve aprirsi sempre nel browser - aggiungi un oggetto di esclusione prima del wildcard:

{
  "/": "/account/delete",
  "exclude": true
}

Le regole vengono valutate dalla prima all'ultima, quindi metti le esclusioni prima dei wildcard.

assetlinks.json

Il file Digital Asset Links di Android sta in https://yourdomain.example/.well-known/assetlinks.json. Google documenta il formato 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 nel Play Store. sha256_cert_fingerprints contiene le impronte SHA-256 del certificato di firma della tua app (la pagina di Google dice che i target delle app mobile sono identificati da hash del certificato e nome del pacchetto). Ottienila con keytool -list -v -keystore your.keystore, oppure dalle impostazioni di firma della tua Play Console se è Play a firmare l'app per te. Elenca ogni certificato con cui installi build, debug compreso.

A differenza del file AASA, il file Android non porta regole di percorso. La corrispondenza dei percorsi per gli App Links si fa nell'AndroidManifest.xml tramite <intent-filter> con android:pathPrefix, android:pathPattern. Il file assetlinks.json asserisce la proprietà del dominio; il manifest dichiara quali percorsi gestisce l'app.

Sequenza di risoluzione AASA: tocco sul link breve, fetch del sistema operativo alla prima installazione, cache hit nei tocchi successivi

Un link come go.acme.example/spring-launch è semplicemente un URL su un dominio. Dai a go.acme.example i due file di associazione e dichiaralo nell'app, e un tocco su quel link apre l'app sui dispositivi in cui è installata. È il trucco, ed è anche l'insidia. L'app riceve https://go.acme.example/spring-launch, non la pagina a cui il link reindirizza.

Il codice della tua app ha allora due opzioni. Una: far corrispondere il percorso da sé (/spring-launch significa la schermata di primavera), il che funziona quando controlli gli slug. Due: chiedere a un server a cosa punta il link breve e instradare in base alla risposta. Elido non ha un endpoint documentato con cui un'app possa risolvere uno slug nella sua destinazione. Il redirect pubblico risponde semplicemente con un 302. Oggi la prima opzione è quella affidabile, e la lacuna è nel nostro backlog.

Sui dispositivi senza l'app, o quando il tocco avviene in un posto che non passa i link al sistema operativo, il link breve si comporta come sempre. L'edge risponde con il redirect (302 per impostazione predefinita; un link può essere impostato su 301 o 307), e il browser lo segue. Le regole di targeting di Elido possono corrispondere al sistema operativo, quindi un solo link può mandare i visitatori iOS a una pagina dell'App Store e i visitatori Android a Google Play quando l'app non c'è.

Ecco cosa Elido fa e non fa oggi per questo, verificato sul codice:

CapacitàStatoDove
Servire apple-app-site-association per un dominio personalizzatoSìIncolla il JSON per dominio nella dashboard
Servire assetlinks.json per un dominio personalizzatoSìStesso pannello
Restituire 404 quando un dominio non ha un file configuratoSìI domini senza app non espongono nulla
Instradare i visitatori iOS e Android a URL diversiSìRegole di targeting (corrispondenza OS)
Deferred deep linking dopo l'installazioneNoUsa un SDK di un vendor
Attribuzione delle installazioni per clicNoConsole degli store o un vendor

Elido memorizza il JSON che scrivi e lo serve invariato sotto i percorsi /.well-known/ del dominio stesso. Elido non genera per te il Team ID, il bundle ID o l'impronta del certificato di firma; arrivano dal tuo account Apple Developer e dalla tua chiave di firma. La configurazione del dominio in sé (CNAME e TLS) è la stessa di link brevi con dominio personalizzato, e la pagina della funzione deep link mostra il flusso nella dashboard. Per i team di prodotto che usano link brevi per l'onboarding, questo schema copre i link di invito e referral senza aggiungere un SDK al binario. La metà del problema in cui non è ancora installato nulla è ciò che affrontano gli App Clip Codes su iOS.

Cosa fa ancora meglio un SDK

Tre cose stanno fuori da ciò che ti dà il sistema operativo.

Deferred deep linking. Un utente tocca prima di installare. Il sistema operativo non ha un'app a cui passare l'URL, quindi il tocco va al browser e l'intento si perde. I vendor lo recuperano con un abbinamento probabilistico sui dati della richiesta o con un passaggio tramite appunti. Il prompt di consenso al tracciamento di Apple rende brutti i casi limite. Elido oggi non lo fa.

Attribuzione delle installazioni. Senza un SDK puoi comunque vedere le installazioni in App Store Connect e Play Console, ma non puoi collegarne una a un tocco specifico su un link. I segnali relativi sopravvivono: esegui esperimenti con smart link e confronta le installazioni per campagna. L'attribuzione per singolo dispositivo richiede un vendor.

Stitching dell'identità. Collegare un tocco a un indirizzo email o a un contatto CRM è un progetto sui dati. I vendor mantengono un device graph per questo.

Se nessuna di queste tre cose ti interessa, le primitive del sistema operativo bastano. Se una sì, assumi il vendor solo per quel compito.

Matrice delle funzioni: le primitive native del sistema operativo e un SDK a pagamento aprono entrambi l'app e ripiegano sul web, ma solo l'SDK aggiunge deferred deep linking, attribuzione delle installazioni per clic e un identity graph cross-platform

Ricettario di configurazione

Tre posti da fare bene: il server, il progetto iOS e il manifest Android.

Requisiti di HTTPS e percorso

Servi entrambi i file su HTTPS con un certificato che risale a una CA radice pubblica. La pagina Digital Asset Links di Google dice che l'elenco di dichiarazioni "must" stare in /.well-known/assetlinks.json e che elenchi altrove o con altri nomi non sono validi (developers.google.com/digital-asset-links/v1/getting-started, consultato il 2026-10-24). Quella pagina non dice se i redirect vengano seguiti, quindi servi il file direttamente con un 200 e non scommettere. Lo stesso consiglio vale per il file di Apple.

iOS: entitlement Associated Domains

In Xcode, sotto Signing & Capabilities, aggiungi la capability Associated Domains con il valore applinks:go.acme.example. Apple documenta un suffisso ?mode=developer per le build di sviluppo che fa recuperare al dispositivo il file dal tuo server invece di passare dalla cache di Apple; non ho potuto ricontrollare quella pagina il 2026-10-24, quindi confermalo nella documentazione Apple. Gestisci il link in arrivo come user activity di navigazione web (SwiftUI onContinueUserActivity(NSUserActivityTypeBrowsingWeb), oppure il delegate UIKit continue userActivity) e leggi webpageURL.

All'interno dell'activity che deve gestire i 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 considera per l'autoverifica i filtri con l'azione VIEW, entrambe le categorie sopra e uno schema http o https. Su Android 11 e precedenti, il sistema rende la tua app il gestore predefinito solo se trova un file Digital Asset Links per ogni host nel manifest, quindi un host sbagliato li rompe tutti. Su un dato dispositivo solo un'app alla volta può essere associata a un dominio.

Verificare che funzioni

Su Android, concedi alla verifica almeno 20 secondi dopo l'installazione, poi esegui adb shell pm get-app-links com.example.acme (Android 12 e successivi) e cerca verified. Puoi forzare una nuova esecuzione con adb shell pm verify-app-links --re-verify com.example.acme. Risultati come none, denied o legacy_failure significano che il file o l'impronta sono sbagliati.

Per il file in sé, l'API Digital Asset Links di Google elenca le dichiarazioni che riesce a leggere per un sito: https://digitalassetlinks.googleapis.com/v1/statements:list?source.web.site=https://go.acme.example&relation=delegate_permission/common.handle_all_urls. Una risposta vuota significa che Android non verificherà l'app.

Per entrambe le piattaforme, recupera il file come farebbe un crawler:

curl -si https://go.acme.example/.well-known/assetlinks.json | head -20
curl -si https://go.acme.example/.well-known/apple-app-site-association | head -20

Vuoi un 200 e un corpo JSON. Elido invia application/json su entrambi i file. Gli errori abituali sono un refuso nel Team ID o nel bundle ID, una build di release il cui certificato di firma non è nell'elenco delle impronte, e un file che esiste solo sull'apex mentre i link usano un sottodominio.

Il compromesso, detto chiaramente

Eliminare l'SDK di deep link toglie una dipendenza dal binario dell'app e una relazione di condivisione dei dati dalla tua informativa privacy. Non metterò una cifra sulla dimensione; varia per vendor e non ne ho misurata una. Il costo: un tocco prima dell'installazione non può essere collegato all'installazione.

Per i team in fase iniziale in cui il costo per installazione per canale non guida ancora il budget, parti dalle primitive del sistema operativo e aggiungi un vendor di attribuzione quando i dati diventano azionabili.

Correlati sul Blog

Domande frequenti

Posso fare deep linking senza Firebase o un SDK di terze parti?

Sì, per il caso in cui l'app è già installata. Universal Links di iOS e App Links di Android richiedono un dominio che controlli, un file di associazione JSON su quel dominio e poche righe nell'app. Le FAQ di Firebase Dynamic Links di Google indicano questi due meccanismi come opzione per il deep linking verso app installate. Ciò a cui rinunci è il deferred deep linking, cioè aprire la schermata giusta dopo una nuova installazione.

Universal Links e App Links funzionano con un dominio di link brevi?

Sì, se il dominio dei link brevi serve i file di associazione e l'app dichiara quel dominio. L'insidia è che il sistema operativo apre l'app con lo stesso URL breve toccato, quindi l'app deve trasformare quell'URL in una schermata. Non può contare sul fatto che il redirect sia stato eseguito. Quando l'app non è installata, lo stesso tocco si carica nel browser e vale il normale redirect.

Dove vanno i file di associazione?

Android legge https://your-domain/.well-known/assetlinks.json, e la documentazione Digital Asset Links di Google dice che è l'unica posizione valida. Il file di Apple va in https://your-domain/.well-known/apple-app-site-association senza estensione. Servili entrambi su HTTPS con un certificato che risale a una CA pubblica.

Perché la mia app Android mostra un selettore invece di aprirsi direttamente?

L'apertura diretta richiede un App Link verificato. Android controlla il dominio rispetto ad assetlinks.json quando l'app viene installata, e solo quando un intent filter porta android:autoVerify="true". Se il file manca, è sbagliato o elenca un certificato di firma diverso da quello della build installata, il link si comporta come un normale deep link.

Cos'è il deferred deep linking e posso farne a meno?

Il deferred deep linking porta la destinazione di un link attraverso l'installazione di un'app, così un utente che tocca prima di installare atterra comunque sulla schermata giusta al primo avvio. Universal Links e App Links in quel caso non fanno nulla perché l'app non è presente per ricevere il tocco. Puoi farne a meno per i flussi di onboarding in cui atterrare sulla home va bene, e aggiungere un vendor solo se il routing al primo avvio sposta i tuoi numeri.

Quali parti di tutto questo gestisce Elido?

Elido serve i file apple-app-site-association e assetlinks.json per i domini personalizzati, usando il JSON che incolli nelle impostazioni del dominio nella dashboard. Instrada inoltre i visitatori iOS e Android verso destinazioni diverse con regole di targeting. Non offre deferred deep linking né attribuzione delle installazioni, quindi usa un SDK di un vendor se ti servono.

Prova Elido

Incolla un URL, ottieni un link breve

Senza registrazione. Il link vive 30 giorni. Iscriviti per conservarlo.

Senza registrazione. Crea un account gratuito per 50 link al mese.

Prova Elido

Accorciatore di URL ospitato nell'UE: domini personalizzati, analisi approfondite e API aperta. Piano gratuito - senza carta di credito.

Tag
mobile deep linking
universal links
app links android
deep linking without sdk
apple app site association
digital asset links

Continua a leggere