React Native ed Expo
@unolink/react-native è un sottile ponte sugli SDK nativi per iOS e Android, inclusi nel pacchetto. Non richiede
alcun config plugin, nessun permesso oltre a internet e nessuna voce in Info.plist. Dal piano Pro in su.
Requisiti
- React Native 0.79+ (nuova architettura).
- Expo: una development build,
npx expo prebuildo EAS Build. Non funziona in Expo Go, perché contiene codice nativo. - Una chiave SDK: nella dashboard, apri la tua app → Impostazioni → Chiavi SDK → Nuova chiave. Viene mostrata una sola volta, quindi copiala subito.
Installazione
Expo:
npx expo install @unolink/react-native
npx expo prebuild # or: eas build
React Native senza Expo:
npm install @unolink/react-native
cd ios && pod install
Poi ricompila l’app. Ricaricare il JavaScript non basta dopo aver aggiunto codice nativo.
Se pod install fallisce con un errore di codifica (Ruby 4, o un locale che non è UTF-8), eseguilo in UTF-8:
cd ios && LANG=en_US.UTF-8 pod install
Non installare con npm install --legacy-peer-deps: riscrive package-lock.json e toglie le dipendenze peer opzionali.
Configurazione
Chiama configure una sola volta, al livello più alto, prima che venga mostrata la prima schermata: in app/_layout.tsx con Expo Router, oppure
in index.js.
import { Unolink } from "@unolink/react-native"
Unolink.configure("ulk_…", { debug: __DEV__ })
Con la 0.3.1 o successiva:
- Le chiamate fatte prima di
configureaspettano, e vengono inviate subito dopo, quindi va bene ripristinare prima una sessione. - Una chiave mancante (per esempio una voce
.envmancante) viene segnalata nella console invece di fallire in silenzio.Unolink.isConfigured()indica se è in funzione. debugvale__DEV__per impostazione predefinita.
Opzioni
| Opzione | Predefinito | Cosa fa |
|---|---|---|
debug | __DEV__ (0.3.1+; false prima) | Segna questa installazione come dispositivo di test. Le dashboard nascondono i dispositivi di test a meno che Includi dispositivi di test non sia attivo. |
logLevel | "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("onboarding") // a paywall appeared; placement says which one
Unolink.paywallSkipped("onboarding") // closed without buying
Unolink.signUp("apple") // a new account was created
Unolink.signIn("apple") // signed in to an account they already had
Unolink.signUpSkipped() // went on as a guest (0.3.1+)
Schermate di onboarding, una chiamata per schermata quando appare:
import { useOnboardingStep } from "@unolink/react-native"
useOnboardingStep("goal", { index: 0 }) // in each onboarding screen component
Unolink.onboardingSkipped("goal") // on Skip
Gli ID delle schermate usano lettere, cifre, _ e . (how_heard, non how-heard). In sviluppo, lo StrictMode di React monta
le schermate due volte, quindi lì potresti vedere una schermata inviata due volte; le build di release la inviano una volta. Le development build avvisano nella
console di ID o proprietà che il server rifiuterebbe (0.3.1+).
Senza RevenueCat, riporta tu prove e acquisti. Passa l’importo come stringa, così non viene mai arrotondato:
Unolink.trialStarted("pro_yearly")
Unolink.purchase("49.99", "USD", "pro_yearly")
Unolink.purchaseCancelled("pro_yearly") // closed the purchase sheet
Unolink.purchaseFailed("pro_yearly", "payment_failed")
I tuoi eventi accettano un nome e fino a 20 proprietà (stringhe, numeri o booleani):
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:
import Purchases from "react-native-purchases"
Unolink.connectRevenueCat(Purchases)
Unolink legge l’ID subito, a ogni aggiornamento delle informazioni del cliente (acquisti, logIn, logOut) e ogni
volta che l’app torna in primo piano, 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 React Native.
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.getAppUserID())
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 link arriva una volta, alla prima apertura. Su iPhone non arriva: Apple non ha un install referrer, e Unolink non usa mai il fingerprinting.
link.deepLink è quello che hai impostato sul link: un path come /promo/3for2, o un URL completo.
Le prime aperture di solito iniziano dall’onboarding. Se la schermata del link si trova dopo l’onboarding o l’accesso, aprilo quando sono finiti e poi segnalo come consumato (0.3.1+):
// when onboarding (or sign-in) is done, and on every launch after that until it's consumed:
const link = Unolink.getPendingDeferredDeepLink()
if (link?.deepLink) {
router.push(link.deepLink) // a path; open a full URL with Linking.openURL
Unolink.consumeDeferredDeepLink()
}
Dalla 0.3.3 il link aspetta finché non lo consumi, anche se nel frattempo l’app viene chiusa (fino a 30 giorni dopo
l’installazione). Un nuovo utente che esce a metà onboarding lo riceve comunque all’avvio successivo, quindi non devi
salvarlo tu (niente AsyncStorage). 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. Con la 0.3.1 e la 0.3.2 viene conservato solo per l’avvio corrente.
Se la schermata è raggiungibile subito, basta un listener. I listener vengono chiamati una volta per installazione. Con la
0.3.1, un link arrivato prima della tua iscrizione va al primo listener che aggiungi; con la 0.3.0, iscriviti subito dopo
configure.
import { router } from "expo-router"
const subscription = Unolink.addDeferredDeepLinkListener((link) => {
// link.deepLink: "/promo/3for2", link.params: { offer: "3for2" }
// link.linkSlug: "tiktok" or null, link.clickId: "clk_01JA…"
if (link.deepLink) router.push(link.deepLink)
Unolink.consumeDeferredDeepLink()
})
// when the component unmounts
subscription.remove()
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 |
|---|---|
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. Viene ricordato tra un avvio e l’altro. |
Le chiamate non lanciano mai eccezioni e non bloccano mai: gli eventi vengono messi in coda sul dispositivo e inviati in background dall’SDK nativo.
Jest
Dalla 0.3.1 il pacchetto ha il suo mock, che registra ogni chiamata:
jest.mock("@unolink/react-native", () => require("@unolink/react-native/jest"))
// expect(Unolink.signUp).toHaveBeenCalledWith("apple")
Dispositivi di test
Le development build sono dispositivi di test (passa debug: __DEV__ prima della 0.3.1). I canali di test di Google Play non possono essere
riconosciuti sul telefono: passa debug: true in quelle build, per esempio da una variabile EXPO_PUBLIC_. 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
- "Native module not found" o simile? Sei in Expo Go, oppure non hai ricompilato dopo l’installazione. Crea una development build. Dalla 0.3.1 l’app non va in crash senza il modulo nativo: le chiamate non fanno nulla e un avviso spiega perché.
- Niente nella dashboard? Attiva Includi dispositivi di test: le build
__DEV__sono nascoste per impostazione predefinita. - Ancora niente? Configura con
{ debug: __DEV__, logLevel: "debug" }e cercaUnolinknella console di Xcode o in Logcat. Una chiave sbagliata o revocata viene registrata come errore.
Altro in Risoluzione dei problemi.