09 giu 2025·8 min di lettura

Deep link per app mobile native: rotte, token, apertura in app

Impara i deep link per app mobile native: pianifica le rotte, gestisci “apri nell'app” e trasferisci token in modo sicuro per Kotlin e SwiftUI senza routing personalizzato disordinato.

Deep link per app mobile native: rotte, token, apertura in app

Quando qualcuno tocca un link sul telefono, si aspetta una cosa: che lo porti immediatamente nel posto giusto. Non in un posto simile. Non nella schermata principale con una barra di ricerca. Non in una schermata di login che dimentica il motivo per cui sono arrivati.

Una buona esperienza di deep link assomiglia a questa:

  • Se l'app è installata, si apre esattamente sulla schermata che il link implica.
  • Se l'app non è installata, il tap è comunque utile (per esempio apre un fallback web o la pagina dell'app store e può riportare la persona alla stessa destinazione dopo l'installazione).
  • Se la persona deve effettuare il login, lo fa una sola volta e atterra sulla schermata prevista, non sull'avvio predefinito dell'app.
  • Se il link porta con sé un'azione (accetta invito, vedi ordine, conferma email), l'azione è chiara e sicura.

La maggior parte della frustrazione deriva da link che “funzionano più o meno” ma rompono il flusso. Le persone vedono la schermata sbagliata, perdono quello che stavano facendo o restano bloccate in un loop: tocca link, effettua login, atterra sulla dashboard, tocca di nuovo il link, effettua di nuovo il login. Anche un passo in più può far desistere gli utenti, soprattutto per azioni una tantum come inviti o reset della password.

Prima di scrivere qualsiasi codice Kotlin o SwiftUI, decidete cosa devono significare i link. Quali schermate si possono aprire dall'esterno? Cosa cambia se l'app è chiusa rispetto a quando è già in esecuzione? Cosa dovrebbe succedere quando l'utente è disconnesso?

La pianificazione è ciò che evita la maggior parte dei dolori dopo: rotte chiare, comportamento “apri nell'app” prevedibile e un modo sicuro per passare codici usa e getta senza mettere segreti direttamente nell'URL.

Non tutti i "link che aprono un'app" si comportano allo stesso modo. Trattarli come intercambiabili porta ai fallimenti classici: il link apre il posto sbagliato, apre un browser invece dell'app, o funziona solo su una piattaforma.

Tre categorie comuni:

  • Custom schemes (per esempio uno schema specifico come myapp:). Facili da configurare, ma molte app e browser li trattano con cautela.
  • Universal Links (iOS) e App Links (Android). Usano normali link web e possono aprire l'app quando installata, oppure fare fallback su un sito quando non lo è.
  • Link in browser integrati nelle app. I link aperti dentro un'app di posta o il browser interno di un messenger spesso si comportano diversamente rispetto a Safari o Chrome.

“Apri nell'app” può significare cose diverse a seconda di dove avviene il tap. Un link toccato in Safari può saltare direttamente nell'app. Lo stesso link toccato dentro un'email o un messenger può aprire prima una web view incorporata, e la persona deve premere un ulteriore pulsante “apri” (o non lo vede mai). Su Android, Chrome può rispettare gli App Links mentre il browser interno di un'app social può ignorarli.

Cold start vs app già in esecuzione è il prossimo problema.

  • Cold start: il sistema operativo lancia la tua app, la tua app si inizializza e solo dopo ricevi il deep link. Se il flusso di avvio mostra una splash, verifica l'autenticazione o carica config remota, il link può perdersi se non lo salvi e lo riproduci quando l'app è pronta.
  • Già in esecuzione: ricevi il link mentre l'utente è in una sessione. Lo stack di navigazione esiste, quindi la stessa destinazione può richiedere un trattamento diverso (push di una schermata vs resettare lo stack).

Un esempio semplice: un link di invito toccato da Telegram spesso apre prima un browser in-app. Se la tua app presume che il sistema operativo passi sempre il link direttamente, gli utenti vedranno una pagina web e penseranno che il link sia rotto. Pianifica questi ambienti dall'inizio e scriverai meno glue specifico per piattaforma in seguito.

Pianifica le rotte prima di implementare qualsiasi cosa

La maggior parte dei bug dei deep link non sono problemi di Kotlin o SwiftUI. Sono problemi di pianificazione. Il link non mappa chiaramente a una schermata, o porta troppi parametri “forse”.

Inizia con un unico schema di rotte coerente che corrisponda a come le persone pensano alla tua app: lista, dettaglio, impostazioni, checkout, invito. Mantienilo leggibile e stabile, perché lo riutilizzerai in email, codici QR e pagine web.

Un set di rotte semplice potrebbe includere:

  • Home
  • Lista ordini e Dettaglio ordine (orderId)
  • Impostazioni account
  • Accettazione invito (inviteId)
  • Ricerca (query, tab)

Poi definisci i parametri:

  • Usa ID per oggetti singoli (orderId).
  • Usa parametri opzionali per stato UI (tab, filtro).
  • Decidi valori di default così ogni link ha una destinazione migliore.

Decidi anche cosa succede quando il link è sbagliato: dati mancanti, ID non valido o contenuto non accessibile. Il default più sicuro è aprire la schermata stabile più vicina (come la lista) e mostrare un messaggio breve. Evita di buttare le persone su una schermata vuota o su una login senza contesto.

Infine, pianifica in base alla sorgente. Un codice QR di solito richiede una rotta corta che si apra rapidamente e tolleri connettività precaria. Un link via email può essere più lungo e includere contesto extra. Un link su una pagina web dovrebbe degradare con grazia: se l'app non è installata, la persona deve comunque atterrare da qualche parte che spiega cosa fare dopo.

Se usi un approccio guidato dal backend (per esempio generando endpoint API e schermate con una piattaforma come AppMaster), questo piano di rotte diventa un contratto condiviso: l'app sa dove andare e il backend sa quali ID e stati sono validi.

Passaggio sicuro dei token senza mettere segreti nelle URL

Un deep link spesso viene trattato come una busta sicura. Non lo è. Qualsiasi cosa nell'URL può finire nella cronologia del browser, negli screenshot, nelle anteprime condivise, nei log di analytics o essere copiata in una chat.

Evita di mettere segreti nel link. Ciò include token di accesso a lunga durata, refresh token, password, dati personali o qualsiasi cosa permetterebbe a qualcuno di agire come l'utente se il link venisse inoltrato.

Un pattern più sicuro è un codice monouso a breve durata. Il link porta solo quel codice e l'app lo scambia con una sessione reale dopo l'apertura. Se qualcuno ruba il link, il codice dovrebbe essere inutile dopo un minuto o due, o dopo il primo riscatto.

Un flusso di passaggio semplice:

  • Il link contiene un codice monouso, non un token di sessione.
  • L'app si apre e chiama il backend per riscattare il codice.
  • Il backend valida la scadenza, controlla che non sia già stato usato, poi lo marca come usato.
  • Il backend restituisce una sessione autenticata normale per l'app.
  • L'app cancella il codice dalla memoria una volta riscattato.

Anche dopo un riscatto riuscito, conferma l'identità dentro l'app prima di eseguire azioni sensibili. Se il link serve ad approvare un pagamento, cambiare email o esportare dati, richiedi un rapido controllo come biometria o un login recente.

Conserva la sessione risultante in modo sicuro. Su iOS ciò tipicamente significa Keychain. Su Android, usa uno storage protetto da Keystore. Conserva solo ciò che ti serve e cancellalo al logout, alla rimozione dell'account o quando rilevi riusi sospetti.

Un esempio concreto: invii un link di invito a unirsi a un workspace. Il link contiene un codice monouso che scade in 10 minuti. L'app lo riscatta, poi mostra una schermata che dichiara chiaramente cosa succederà (a quale workspace ci si unirà). Solo dopo che l'utente conferma, l'app completa l'unione.

Se stai costruendo con AppMaster, questo si mappa pulitamente su un endpoint che riscatta codici e ritorna una sessione, mentre la UI mobile gestisce il passaggio di conferma prima di qualsiasi azione d'impatto.

Autenticazione e “continua da dove eri rimasto”

Distribuisci senza cambiare architettura
Distribuisci su AppMaster Cloud o sul tuo setup AWS, Azure o Google Cloud.
Distribuisci App

I deep link spesso puntano a schermate che contengono dati privati. Comincia decidendo cosa può essere aperto da chiunque (pubblico) e cosa richiede una sessione autenticata (protetto). Questa singola decisione evita la maggior parte delle sorprese del tipo “funzionava nei test”.

Una regola pratica: deep link a uno stato di atterraggio sicuro prima, poi naviga verso la schermata protetta solo dopo aver confermato che l'utente è autenticato.

Decidi cosa è pubblico vs protetto

Tratta i deep link come potenzialmente inoltrabili alla persona sbagliata.

  • Pubblico: pagine marketing, articoli di help, inizio reset password, inizio accettazione invito (nessun dato mostrato ancora)
  • Protetto: dettagli ordine, messaggi, impostazioni account, schermate admin
  • Misto: una schermata di anteprima può andare bene, ma mostra solo segnaposti non sensibili finché non avviene il login

“Continua dopo il login” che torna nel posto giusto

L'approccio affidabile è: analizza il link, memorizza la destinazione prevista, poi instrada in base allo stato auth.

Esempio: un utente tocca un link “apri nell'app” a un ticket supporto specifico mentre è disconnesso. La tua app dovrebbe aprirsi su una schermata neutra, chiedere di effettuare il login e poi portarlo automaticamente a quel ticket.

Per mantenerlo affidabile, memorizza localmente un piccolo “return target” (nome rotta più un ticket ID) con una breve scadenza. Dopo che il login è completato, leggilo una sola volta, naviga e poi cancellalo. Se il login fallisce o il target scade, ricadi su una schermata home sicura.

Gestisci i casi limite con rispetto:

  • Sessione scaduta: mostra un messaggio breve, richiedi un nuovo login e poi continua.
  • Accesso revocato: apri l'involucro della destinazione, poi mostra “Non hai più accesso” e offri un passo sicuro successivo.

Evita anche di mostrare dati privati nelle anteprime della schermata di blocco, negli screenshot dello switcher o nelle anteprime di notifica. Mantieni le schermate sensibili vuote finché i dati non sono caricati e la sessione verificata.

Un approccio di routing che evita lo spaghetti di navigazione personalizzata

Crea app pronte per i deep link
Crea app native iOS e Android con rotte condivise e flussi deep link più sicuri.
Prova AppMaster

I deep link diventano complicati quando ogni schermata analizza gli URL a modo suo. Questo sparge piccole decisioni (cosa è opzionale, cosa è richiesto, cosa è valido) in tutta l'app e diventa difficile cambiare in sicurezza.

Tratta il routing come tubature condivise. Mantieni una sola tabella di rotte e un solo parser, e fai ricevere alla UI input puliti.

Usa una sola tabella di rotte condivisa

Fai concordare iOS e Android su una lista unica e leggibile di rotte. Pensala come un contratto.

Ogni rotta mappa su:

  1. una schermata, e
  2. un piccolo modello di input.

Per esempio, “Dettaglio ordine” mappa su una schermata Order con un input tipo OrderRouteInput(id). Se una rotta necessita di valori extra (come una fonte di riferimento), questi appartengono al modello di input, non sparsi nel codice della view.

Centralizza parsing e validazione

Mantieni parsing, decodifica e validazione in un unico posto. L'UI non dovrebbe chiedersi “Questo token è presente?” o “Questo ID è valido?” Dovrebbe ricevere o un input di rotta valido o uno stato di errore chiaro.

Un flusso pratico:

  • Ricevi l'URL (tap, scansione, condivisione)
  • Parsealo in una rotta conosciuta
  • Valida i campi richiesti e i formati consentiti
  • Produci una destinazione di schermata più un modello di input
  • Naviga attraverso un unico punto di ingresso

Aggiungi una schermata di fallback per “link sconosciuto”. Rendila utile, non un vicolo cieco: mostra cosa non si è potuto aprire, spiega il motivo in linguaggio semplice e offri azioni successive come tornare Home, cercare o effettuare l'accesso.

I deep link funzionano quando sono noiosi nel modo migliore. Le persone toccano e atterrano nella schermata giusta, sia che l'app sia installata o no.

Passo 1: scegli i punti di ingresso che contano

Elenca i primi 10 tipi di link che la gente usa davvero: inviti, reset password, ricevute d'ordine, link “vedi ticket”, link promozionali. Mantienilo volutamente piccolo.

Passo 2: scrivi i pattern come un contratto

Per ogni punto di ingresso, definisci un pattern canonico e i dati minimi necessari per aprire la schermata giusta. Preferisci ID stabili ai nomi. Decidi cosa è richiesto vs opzionale.

Regole utili:

  • Uno scopo per rotta (invito, reset, ricevuta).
  • I parametri richiesti sono sempre presenti; quelli opzionali hanno default sicuri.
  • Usa gli stessi pattern su iOS (SwiftUI) e Android (Kotlin).
  • Se prevedi cambiamenti, riserva una semplice versione (es. v1).
  • Definisci cosa succede quando mancano parametri (mostra una schermata di errore, non una pagina vuota).

Passo 3: decidi il comportamento di login e il target post-login

Scrivi, per ogni tipo di link, se il login è richiesto. Se lo è, conserva la destinazione e continua dopo il login.

Esempio: un link a una ricevuta può mostrare un'anteprima senza login, ma toccare “Scarica fattura” può richiedere il login e dovrebbe riportare l'utente esattamente a quella ricevuta.

Passo 4: definisci le regole per il passaggio dei token (mantieni i segreti fuori dagli URL)

Se il link ha bisogno di un token monouso (accettazione invito, reset, magic sign-in), definisci per quanto è valido e come può essere usato.

L'approccio pratico: l'URL contiene un codice monouso a breve durata e l'app lo scambia con il backend per ottenere una sessione reale.

Passo 5: testa i tre stati reali

I deep link si rompono ai margini. Testa ogni tipo di link in queste situazioni:

  • Cold start (app chiusa)
  • Warm start (app in memoria)
  • App non installata (il link deve comunque portare da qualche parte di sensato)

Se tieni rotte, controlli auth e regole di scambio token in un unico posto, eviterai di spargere logica di routing personalizzata su Kotlin e SwiftUI.

Dai potenza ai link con integrazioni
Collega email, SMS, Telegram, Stripe e altro per azioni guidate da link.
Aggiungi integrazioni

I deep link falliscono per motivi banali: un'assunzione piccola, una schermata rinominata o un token “temporaneo” che finisce ovunque.

I fallimenti che vedi (e le correzioni)

  • Mettere token di accesso nell'URL (e perderli nei log). Le query string vengono copiate, condivise, salvate nella cronologia e catturate da analytics e log di crash. Correzione: metti solo un codice monouso nel link, riscattalo dentro l'app ed espiralo rapidamente.

  • Presumere che l'app sia installata (nessun fallback). Se un link apre una pagina di errore o non fa nulla, gli utenti mollano. Correzione: fornisci una pagina web di fallback che spieghi cosa succede e offra un percorso di installazione. Anche una semplice pagina “Apri l'app per continuare” è meglio del silenzio.

  • Non gestire più account su un dispositivo. Aprire la schermata giusta con l'utente sbagliato è peggio che avere un link rotto. Correzione: quando l'app riceve un link, controlla quale account è attivo, chiedi conferma o cambio di account e poi continua. Se l'azione richiede uno specifico workspace, includi un identificatore workspace (non un segreto) e validalo.

  • Rottura dei link quando cambiano schermate o rotte. Se la tua rotta è legata ai nomi UI, i link vecchi smettono di funzionare quando rinomini una tab. Correzione: progetta rotte stabili basate sull'intento (invito, ticket, ordine) e mantieni funzionanti le versioni precedenti.

  • Nessuna tracciabilità quando qualcosa va male. Senza modo di riprodurre cosa è successo, il supporto può solo indovinare. Correzione: includi un ID richiesta non sensibile nel link, loggalo sul server e nell'app e mostra un messaggio d'errore che include quell'ID.

Un rapido reality check: immagina un link di invito inviato in una chat di gruppo. Qualcuno lo apre su un telefono di lavoro con due account, l'app non è installata sul tablet e il link viene inoltrato a un collega. Se il link contiene solo un codice invito, supporta fallback, chiede il giusto account e logga un request ID, quello stesso link può funzionare in tutte quelle situazioni senza esporre segreti.

Gestisci i deep link durante il cold start
Genera app Kotlin e SwiftUI che gestiscono correttamente cold start e warm start.
Crea Mobile

Gli inviti sono un classico deep link: qualcuno invia a un collega un link in un messenger, e il destinatario si aspetta che con un tap arrivi alla schermata invito, non a una home generica.

Scenario: un manager invita un nuovo agente di supporto a unirsi al workspace “Support Team”. L'agente tocca l'invito in Telegram.

Se l'app è installata, il sistema dovrebbe aprire l'app e passare i dettagli dell'invito. Se l'app non è installata, l'utente dovrebbe atterrare su una semplice pagina web che spiega l'invito e offre un percorso di installazione. Dopo l'installazione e il primo avvio, l'app dovrebbe comunque riuscire a completare il flusso d'invito così l'utente non deve cercare di nuovo il link.

Dentro l'app, il flusso è lo stesso su Kotlin e SwiftUI:

  • Leggi il codice invito dal link entrante.
  • Controlla se l'utente è loggato.
  • Verifica l'invito con il backend, poi instrada alla schermata corretta.

La verifica è il punto chiave. Il link non dovrebbe contenere segreti come un token di sessione a lunga durata. Dovrebbe portare un codice invito monouso che diventa utile solo dopo la validazione server.

L'esperienza utente dovrebbe essere prevedibile:

  • Non loggato: si vede la schermata di login, poi si ritorna all'accettazione dell'invito dopo il login.
  • Loggato: si vede una conferma “Unisciti al workspace” e poi si entra nel workspace corretto.

Se l'invito è scaduto o già usato, non buttare l'utente su una pagina di errore vuota. Mostra un messaggio chiaro e una prossima azione: richiedere un nuovo invito, cambiare account o contattare un admin. “Questo invito è già stato accettato” è meglio di “Token non valido.”

Checklist rapida e prossimi passi

I deep link sembrano "completi" solo quando si comportano allo stesso modo ovunque: cold start, warm start e quando l'utente è già autenticato.

Checklist rapida

Prima di rilasciare, testa ogni voce su dispositivi reali e versioni OS reali:

  • Il link apre la schermata corretta su cold start e warm start.
  • Nulla di sensibile è nell'URL. Se devi passare un token, fallo breve e monouso.
  • Link sconosciuti, scaduti o già usati cadono su una schermata chiara con un messaggio utile e un'azione successiva sicura.
  • Funziona da app di posta, browser, scanner QR e anteprime messenger (alcune aprono i link in anticipo).
  • I log dicono cosa è successo (link ricevuto, rotta parsata, auth richiesta, motivo di successo o fallimento).

Un modo semplice per validare il comportamento è scegliere una manciata di link critici (invito, reset password, dettaglio ordine, ticket supporto, promo) e testarli con lo stesso flusso: tocca da email, da chat, scansiona un QR, apri dopo la reinstallazione.

Prossimi passi (mantieni manutenibile)

Se i deep link iniziano a spargersi nelle schermate, tratta routing e auth come tubature condivise, non codice per-schermata. Centralizza il parsing delle rotte in un posto e fai accettare a ogni destinazione parametri puliti (non URL grezzi). Fai lo stesso per l'auth: un solo gate che decide “continua ora” vs “effettua il login prima, poi continua”.

Se vuoi ridurre il codice glue personalizzato, può aiutare costruire backend, auth e app mobili insieme. AppMaster (appmaster.io) è una piattaforma no-code che genera backend pronti per la produzione e app native, il che può rendere più semplice mantenere allineati nomi di rotta ed endpoint di riscatto dei codici monouso man mano che i requisiti cambiano.

Se fai una cosa la prossima settimana, fallo così: scrivi le tue rotte canoniche e il comportamento di fallback esatto per ogni caso di errore, poi implementa quelle regole in un unico layer di routing.

FAQ

What should a deep link do when someone taps it?

Un deep link dovrebbe aprire esattamente la schermata che il link indica, non una home generica o una dashboard. Se l'app non è installata, il tap dovrebbe comunque essere utile, portando l'utente in un posto sensato e guidandolo a tornare alla stessa destinazione dopo l'installazione.

Should I use Universal Links/App Links or a custom URL scheme?

Universal Links (iOS) e App Links (Android) usano normali URL web e possono aprire l'app quando installata, offrendo un fallback elegante quando non lo è. Gli schemi personalizzati sono più facili da configurare ma possono essere bloccati o gestiti in modo incoerente dai browser e da altre app, quindi è meglio usarli come opzione secondaria.

Why does “open in app” work in Safari/Chrome but fail in email or messenger apps?

Molte app di posta e messenger aprono i link dentro un browser incorporato, che potrebbe non passare l'URL al sistema come fanno Safari o Chrome. Prevedi questo comportamento mostrando un fallback web chiaro e gestendo i casi in cui l'utente atterra prima su una pagina web.

How do I prevent deep links from getting lost on cold start?

All'avvio a freddo l'app potrebbe mostrare una splash screen, eseguire controlli o caricare configurazioni prima di essere pronta a navigare. La soluzione affidabile è memorizzare subito l'obiettivo del link, completare l'inizializzazione e poi "riprodurre" la navigazione quando l'app è pronta.

What data should I never put in a deep link URL?

Non mettere token di accesso a lunga durata, refresh token, password o dati personali nell'URL: gli URL possono essere registrati, condivisi o memorizzati nei log. Usa un codice monouso a breve durata nel link e scambialo con il backend dopo l'apertura dell'app.

How can I make users land on the intended screen after they log in?

Analizza il link, memorizza la destinazione prevista, poi instrada in base allo stato di autenticazione in modo che il login avvenga una sola volta e l'utente arrivi alla schermata corretta dopo. Mantieni il "target di ritorno" piccolo, con scadenza, e cancellalo dopo l'uso.

How do I avoid deep link handling turning into navigation spaghetti?

Tratta le rotte come un contratto condiviso e centralizza parsing e validazione in un unico punto, poi passa alle schermate input puliti invece che URL grezzi. Così eviti che ogni schermata inventi le proprie regole su parametri opzionali, ID mancanti ed errori.

How should deep links behave on devices with multiple accounts logged in?

Controlla quale account è attivo e se corrisponde allo spazio di lavoro o tenant implicato dal link, poi chiedi all'utente di confermare o cambiare account prima di mostrare contenuti privati. Meglio un breve passaggio di conferma che aprire la schermata giusta con l'account sbagliato.

What should happen if a deep link is invalid, expired, or missing data?

Di default apri la schermata stabile più vicina, come una pagina di elenco, e mostra un messaggio breve che spiega cosa non è stato possibile aprire. Evita schermate vuote, errori silenziosi o reindirizzare gli utenti a una login page senza contesto.

What’s the minimum testing I should do before shipping deep links?

Testa ogni link importante in tre stati: app chiusa, app già in esecuzione e app non installata, e fai i test da fonti reali come email, chat e scanner QR. Se usi AppMaster, puoi mantenere allineati nomi di rotta e endpoint per il riscatto dei codici monouso tra backend e app native, riducendo il lavoro di integrazione da mantenere.

Facile da avviare
Creare qualcosa di straordinario

Sperimenta con AppMaster con un piano gratuito.
Quando sarai pronto potrai scegliere l'abbonamento appropriato.

Iniziare