Flutter
Il pacchetto unolink è un sottile strato sugli SDK nativi per iOS e Android, inclusi al suo interno. Non richiede
permessi oltre a internet e nessuna voce in Info.plist. Pubblicato su pub.dev da unolink.dev. Dal piano Pro in su.
Requisiti
- Flutter 3.22+ (Dart 3.4+).
- Android 6.0+ (
minSdk 23) e iOS 13+. - Una chiave SDK: nella dashboard, apri la tua app → Impostazioni → Chiavi SDK → Nuova chiave. Viene mostrata una sola volta, quindi copiala subito.
Installazione
flutter pub add unolink
Questo aggiunge unolink: ^0.3.3 a pubspec.yaml e lo scarica. Ricompila l’app dopo; un hot reload non basta
dopo aver aggiunto codice nativo.
Se CocoaPods fallisce nella build iOS con un errore di codifica (Ruby 4, o un locale che non è UTF-8), eseguilo tu in UTF-8 e poi ricompila:
cd ios && LANG=en_US.UTF-8 pod install
Configurazione
Chiama configure una sola volta in main(), dopo WidgetsFlutterBinding.ensureInitialized() e prima di runApp:
import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';
import 'package:unolink/unolink.dart';
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await Unolink.configure('ulk_…', debug: kDebugMode);
runApp(const MyApp());
}
Opzioni
| Opzione | Predefinito | Cosa fa |
|---|---|---|
debug | false | Segna questa installazione come dispositivo di test. Passa kDebugMode. Le dashboard nascondono i dispositivi di test a meno che Includi dispositivi di test non sia attivo. |
logLevel | UnolinkLogLevel.warn | Quanto viene scritto nella console di Xcode o in Logcat (tag Unolink): none, error, warn, info, debug. |
baseUrl | https://api.unolink.dev | L’API dell’SDK. Lasciala com’è. |
La chiave è pubblica: viene distribuita dentro la tua app e può solo riportare dati per quell’unica app. Vedi Chiavi SDK.
Eventi del funnel
Aggiungi una riga in ogni momento importante. Diventano i passaggi in Funnel e Percorsi.
Unolink.onboardingCompleted(); // the last onboarding screen is done
Unolink.paywallViewed(placement: 'onboarding'); // a paywall appeared; placement says which one
Unolink.paywallSkipped(placement: 'onboarding'); // closed without buying
Unolink.signUp(method: 'apple'); // an account was created
Unolink.signUpSkipped(); // went on as a guest (0.3.2+)
Senza RevenueCat, riporta tu prove e acquisti. L’importo è una stringa, così non viene mai arrotondato:
Unolink.trialStarted(productId: 'pro_yearly');
Unolink.purchase('49.99', 'USD', productId: 'pro_yearly');
Unolink.purchaseCancelled(productId: 'pro_yearly'); // closed the purchase sheet
Unolink.purchaseFailed(productId: 'pro_yearly', reason: 'payment_failed');
I tuoi eventi accettano un nome e fino a 20 proprietà:
Unolink.track('level_up', {'level': 3});
L’elenco completo, con i nomi che arrivano alla dashboard, è in Eventi.
ID utente e RevenueCat
Se usi RevenueCat, collegalo dalla tua app → Impostazioni → RevenueCat. Poi non chiamare
purchase né trialStarted: RevenueCat invia da solo prove, acquisti, rinnovi, cancellazioni e rimborsi, e
Unolink ignora le chiamate di acquisto dell’app, così nulla conta due volte.
Per collegare quegli acquisti all’installazione, riporta l’app user ID di RevenueCat. Con l’SDK 0.3.2 o successivo,
una riga lo tiene aggiornato. Chiamala una volta all’avvio, prima o dopo configure:
Unolink.connectRevenueCat(
() => Purchases.appUserID,
addListener: Purchases.addCustomerInfoUpdateListener,
removeListener: Purchases.removeCustomerInfoUpdateListener,
);
Unolink legge l’ID una volta configurato, a ogni aggiornamento delle informazioni del cliente (acquisti, logIn,
logOut) e ogni volta che l’app riprende, e lo invia solo quando è cambiato. Se RevenueCat non è ancora configurato,
la lettura fallisce senza errori e viene ritentata più tardi. Restituisce una funzione che scollega. Per questo Unolink.revenueCatUserChanged() di solito non serve su Flutter.
Senza di esso (o prima della 0.3.2), chiama setUserId con l’ID di RevenueCat dopo Purchases.configure, dopo ogni
Purchases.logIn e Purchases.logOut, e a ogni avvio. Usa l’uno o l’altro, non entrambi:
// after Purchases.configure, logIn and logOut, and on every launch
Unolink.setUserId(await Purchases.appUserID);
Per un ospite, è l’ID anonimo di RevenueCat, quindi un acquisto fatto prima della registrazione si collega subito
all’installazione. Dopo logIn, è l’ID dell’account. Ogni ID riportato da un’installazione conta, così l’acquisto
dell’ospite resta collegato. Vedi Ospiti e account.
Unolink non salva mai l’ID in sé, solo un hash unidirezionale diverso per ciascuna delle tue app.
Deep link differiti
Su Android, quando qualcuno installa da un link Unolink che ha un deep link, il listener viene eseguito una volta, alla prima apertura. Su iPhone non viene chiamato: Apple non ha un install referrer, e Unolink non usa mai il fingerprinting.
Unolink.setDeferredDeepLinkListener((link) {
// link.deepLink: '/promo/3for2', link.params: {'offer': '3for2'}
// link.linkSlug: 'tiktok' or null, link.clickId: 'clk_01JA…'
if (link.deepLink != null) router.go(link.deepLink!);
Unolink.consumeDeferredDeepLink();
});
Il listener viene chiamato una volta per installazione. Un link arrivato prima che tu lo imposti viene consegnato appena lo imposti.
Aprilo dopo l’onboarding
Le prime aperture di solito iniziano dall’onboarding. Se la schermata del link si trova dopo l’onboarding o l’accesso, non aprirlo dal listener. Quando l’onboarding (o l’accesso) è finito, leggi il link in sospeso, aprilo e poi segnalo come consumato:
// when onboarding (or sign-in) is done, and on every launch after that until it's consumed
final link = await Unolink.getPendingDeferredDeepLink();
if (link?.deepLink != null) {
router.go(link!.deepLink!);
await Unolink.consumeDeferredDeepLink();
}
Il link aspetta finché non lo consumi, anche se nel frattempo l’app viene chiusa (fino a 30 giorni dopo l’installazione;
0.3.3+). Un nuovo utente che esce a metà onboarding lo riceve comunque all’avvio successivo, quindi non devi salvarlo tu.
Chiama consumeDeferredDeepLink() dopo averlo aperto: fino ad allora, getPendingDeferredDeepLink() lo restituisce a
ogni avvio. È null prima di configure e finché Google Play non ha risposto, e sempre null su iPhone.
Imposta Deep link e Parametri del link nella dashboard (Link → ⋯ → Modifica). Come funziona è spiegato in Deep link differiti su Android.
Altre chiamate
| Chiamata | Cosa fa |
|---|---|
await Unolink.getInstallId() | L’ID casuale di questa installazione, oppure null prima di configure. Non identifica nessuna persona né dispositivo. |
Unolink.flush() | Invia subito gli eventi in coda. Di solito non serve. |
Unolink.setEnabled(false) | Disattiva il tracciamento ed elimina gli eventi in coda, per la tua impostazione di opt-out. true lo riattiva. |
Dispositivi di test
Con debug: kDebugMode, le build di debug sono dispositivi di test. I loro dati sono reali ma nascosti finché non attivi Includi
dispositivi di test in Funnel e Percorsi. Altro in Test.
Privacy
- Nessun IDFA, nessun Google Advertising ID, nessuna richiesta di App Tracking Transparency, nessun fingerprinting.
- Un ID di installazione casuale, versione dell’app, versione del sistema operativo, versione dell’SDK, telefono o tablet, lingua. Il paese deriva dall’edge di rete. Gli indirizzi IP non vengono mai salvati.
- Su iOS il privacy manifest dell’SDK nativo è incluso nel pacchetto: analytics, non collegati all’identità.
- Non mettere mai nomi, email o altri dati personali nelle proprietà degli eventi.
Risoluzione dei problemi
- MissingPluginException? Chiudi l’app ed eseguila di nuovo. Hot reload e hot restart non caricano nuovo codice nativo.
- Niente nella dashboard? Attiva Includi dispositivi di test: le build
kDebugModesono nascoste per impostazione predefinita. - Ancora niente? Configura con
logLevel: UnolinkLogLevel.debuge cercaUnolinknella console di Xcode o in Logcat. Una chiave sbagliata o revocata viene registrata come errore.
Altro in Risoluzione dei problemi.