React Native et Expo

@unolink/react-native est une fine passerelle vers les SDK natifs iOS et Android, qui sont fournis dans le package. Il ne demande aucun plugin de configuration, aucune permission en dehors d’internet et aucune entrée Info.plist. Forfait Pro et plus.

Prérequis

  • React Native 0.79+ (nouvelle architecture).
  • Expo : un development build, npx expo prebuild ou EAS Build. Il ne fonctionne pas dans Expo Go, car il contient du code natif.
  • Une clé SDK : dans le tableau de bord, ouvrez votre app → Paramètres → Clés SDK → Nouvelle clé. Elle n’est affichée qu’une fois, copiez-la à ce moment-là.

Installation

Expo :

npx expo install @unolink/react-native
npx expo prebuild        # or: eas build

React Native sans Expo :

npm install @unolink/react-native
cd ios && pod install

Puis recompilez l’app. Un rechargement JavaScript ne suffit pas après l’ajout de code natif.

Si pod install échoue sur une erreur d’encodage (Ruby 4, ou une locale qui n’est pas en UTF-8), lancez-le en UTF-8 :

cd ios && LANG=en_US.UTF-8 pod install

N’installez pas avec npm install --legacy-peer-deps : cette commande réécrit package-lock.json et supprime les dépendances peer optionnelles.

Configuration

Appelez configure une seule fois, au niveau le plus haut, avant le rendu de votre premier écran : dans app/_layout.tsx avec Expo Router, ou dans index.js.

import { Unolink } from "@unolink/react-native"

Unolink.configure("ulk_…", { debug: __DEV__ })

Avec la version 0.3.1 ou plus récente :

  • Les appels faits avant configure attendent, et sont envoyés juste après, vous pouvez donc restaurer une session d’abord.
  • Une clé manquante (par exemple une entrée .env absente) est signalée dans la console au lieu d’échouer en silence. Unolink.isConfigured() indique s’il est actif.
  • debug vaut __DEV__ par défaut.

Options

OptionPar défautCe qu’elle fait
debug__DEV__ (0.3.1+ ; false avant)Marque cette installation comme appareil de test. Les tableaux de bord masquent les appareils de test sauf si Inclure les appareils de test est activé.
logLevel"warn"La quantité de logs envoyée vers la console Xcode ou Logcat (tag Unolink) : "none", "error", "warn", "info", "debug".
baseUrlhttps://api.unolink.devL’API du SDK. Laissez-la telle quelle.

La clé est publique : elle est livrée dans votre app et ne peut envoyer des données que pour cette app. Voir Clés SDK.

Événements d’entonnoir

Ajoutez une ligne à chaque moment qui compte. Elles deviennent les étapes de Entonnoir et Parcours.

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+)

Écrans d’onboarding, un appel par écran quand il apparaît :

import { useOnboardingStep } from "@unolink/react-native"

useOnboardingStep("goal", { index: 0 })   // in each onboarding screen component
Unolink.onboardingSkipped("goal")         // on Skip

Les identifiants d’écran utilisent des lettres, des chiffres, _ et . (how_heard, pas how-heard). En développement, le StrictMode de React monte les écrans deux fois, vous pouvez donc y voir un écran envoyé deux fois ; les builds de release l’envoient une fois. Les builds de développement avertissent dans la console des identifiants ou propriétés que le serveur rejetterait (0.3.1+).

Sans RevenueCat, remontez vous-même les essais et les achats. Passez le montant sous forme de chaîne pour qu’il ne soit jamais arrondi :

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")

Vos propres événements prennent un nom et jusqu’à 20 propriétés (chaînes, nombres ou booléens) :

Unolink.track("level_up", { level: 3 })

La liste complète, avec les noms qui arrivent dans le tableau de bord, se trouve dans Événements.

Identifiant utilisateur et RevenueCat

Si vous utilisez RevenueCat, connectez-le dans votre app → Paramètres → RevenueCat. N’appelez alors pas purchase ni trialStarted : RevenueCat envoie lui-même les essais, achats, renouvellements, annulations et remboursements, et Unolink ignore les appels d’achat de l’app pour que rien ne compte deux fois.

Pour relier ces achats à l’installation, signalez le propre identifiant utilisateur d’app de RevenueCat. Avec le SDK 0.3.2 ou plus récent, une seule ligne le tient à jour. Appelez-la une fois au lancement, avant ou après configure :

import Purchases from "react-native-purchases"

Unolink.connectRevenueCat(Purchases)

Unolink lit l’identifiant tout de suite, à chaque mise à jour des infos client (achats, logIn, logOut) et chaque fois que l’app revient au premier plan, et ne l’envoie que s’il a changé. Si RevenueCat n’est pas encore configuré, la lecture échoue sans bruit et est retentée plus tard. L’appel renvoie une fonction qui déconnecte. Unolink.revenueCatUserChanged() n’est donc normalement pas nécessaire sur React Native.

Sans elle (ou avant la 0.3.2), appelez setUserId avec l’identifiant de RevenueCat après Purchases.configure, après chaque Purchases.logIn et Purchases.logOut, et à chaque lancement. Utilisez l’un ou l’autre, pas les deux :

// after Purchases.configure, logIn and logOut, and on every launch
Unolink.setUserId(await Purchases.getAppUserID())

Pour un invité, c’est l’identifiant anonyme de RevenueCat, donc un achat fait avant l’inscription est relié à l’installation tout de suite. Après logIn, c’est l’identifiant du compte. Chaque identifiant signalé par une installation compte, donc l’achat de l’invité reste relié. Voir Invités et comptes.

Unolink ne stocke jamais l’identifiant lui-même, seulement un hachage à sens unique, différent pour chacune de vos apps.

Sur Android, quand quelqu’un installe depuis un lien Unolink qui a un deep link, le lien arrive une fois, à la première ouverture. Sur iPhone, il n’y en a pas : Apple n’a pas de referrer d’installation, et Unolink ne fait jamais de fingerprinting.

link.deepLink est ce que vous avez défini sur le lien : un chemin comme /promo/3for2, ou une URL complète.

Les premières ouvertures commencent généralement par l’onboarding. Si l’écran du lien se trouve derrière l’onboarding ou la connexion, ouvrez-le une fois ces étapes terminées, puis consommez-le (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()
}

À partir de 0.3.3, le lien attend que vous le consommiez, même si l’app est fermée entre-temps (jusqu’à 30 jours après l’installation). Un nouvel utilisateur qui quitte l’app au milieu de l’onboarding le retrouve au lancement suivant : inutile de le stocker vous-même (pas besoin d’AsyncStorage). Appelez consumeDeferredDeepLink() une fois que vous l’avez ouvert : d’ici là, getPendingDeferredDeepLink() le renvoie à chaque lancement. Il vaut null avant configure et tant que Google Play n’a pas répondu. Avec 0.3.1 et 0.3.2, il n’est conservé que pendant le lancement en cours.

Si l’écran est accessible tout de suite, un listener suffit. Les listeners sont appelés une fois par installation. Avec 0.3.1, un lien arrivé avant votre abonnement est transmis au premier listener que vous ajoutez ; avec 0.3.0, abonnez-vous juste après 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()

Définissez le Deep link et les Paramètres du lien dans le tableau de bord (Liens → ⋯ → Modifier). Le fonctionnement est expliqué dans Liens profonds différés Android.

Autres appels

AppelCe qu’il fait
Unolink.getInstallId()L’identifiant d’installation aléatoire, ou null avant configure. Il n’identifie aucune personne ni aucun appareil.
Unolink.flush()Envoie tout de suite les événements en file d’attente. Normalement inutile.
Unolink.setEnabled(false)Désactive le suivi et supprime les événements en file d’attente, pour votre réglage de désinscription. Mémorisé d’un lancement à l’autre.

Les appels ne lèvent jamais d’exception et ne bloquent jamais : les événements sont mis en file d’attente sur l’appareil et envoyés en arrière-plan par le SDK natif.

Jest

Depuis la version 0.3.1, le package a son propre mock, qui enregistre chaque appel :

jest.mock("@unolink/react-native", () => require("@unolink/react-native/jest"))
// expect(Unolink.signUp).toHaveBeenCalledWith("apple")

Appareils de test

Les builds de développement sont des appareils de test (passez debug: __DEV__ avant 0.3.1). Les pistes de test de Google Play ne peuvent pas être reconnues sur le téléphone : passez debug: true dans ces builds, par exemple via une variable EXPO_PUBLIC_. Leurs données sont réelles mais masquées tant que vous n’activez pas Inclure les appareils de test dans Entonnoir et Parcours. Plus d’informations dans Tests.

Confidentialité

  • Pas d’IDFA, pas de Google Advertising ID, pas de demande App Tracking Transparency, pas de fingerprinting.
  • Un identifiant d’installation aléatoire, la version de l’app, la version de l’OS, la version du SDK, téléphone ou tablette, la langue. Le pays vient de la périphérie du réseau. Les adresses IP ne sont jamais stockées.
  • Sur iOS, le manifeste de confidentialité du SDK natif est fourni avec le package : analyse, non liées à l’identité.
  • Ne mettez jamais de noms, d’e-mails ou d’autres données personnelles dans les propriétés des événements.

Dépannage

  • « Native module not found » ou similaire ? Vous êtes dans Expo Go, ou vous n’avez pas recompilé depuis l’installation. Faites un development build. Depuis la version 0.3.1, l’app ne plante pas sans le module natif : les appels ne font rien et un avertissement explique pourquoi.
  • Rien dans le tableau de bord ? Activez Inclure les appareils de test : les builds __DEV__ sont masqués par défaut.
  • Toujours rien ? Configurez avec { debug: __DEV__, logLevel: "debug" } et cherchez Unolink dans la console Xcode ou Logcat. Une clé erronée ou révoquée est consignée comme erreur.

Plus d’informations dans Dépannage.