Flutter
Das Paket unolink ist eine dünne Schicht über den nativen iOS- und Android-SDKs, die darin enthalten sind. Es braucht keine
Berechtigungen außer Internet und keine Einträge in Info.plist. Auf pub.dev veröffentlicht von unolink.dev. Ab dem Pro-Tarif.
Voraussetzungen
- Flutter 3.22+ (Dart 3.4+).
- Android 6.0+ (
minSdk 23) und iOS 13+. - Ein SDK-Schlüssel: Öffne im Dashboard deine App → Einstellungen → SDK-Schlüssel → Neuer Schlüssel. Er wird nur einmal angezeigt, kopiere ihn also gleich.
Installieren
flutter pub add unolink
Das fügt unolink: ^0.3.3 zu pubspec.yaml hinzu und lädt es. Baue die App danach neu; ein Hot Reload reicht nach dem
Hinzufügen von nativem Code nicht.
Wenn CocoaPods beim iOS-Build mit einem Encoding-Fehler abbricht (Ruby 4 oder eine Locale ohne UTF-8), führe es selbst in UTF-8 aus und baue dann erneut:
cd ios && LANG=en_US.UTF-8 pod install
Konfigurieren
Ruf configure einmal in main() auf, nach WidgetsFlutterBinding.ensureInitialized() und vor 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());
}
Optionen
| Option | Standard | Was sie macht |
|---|---|---|
debug | false | Markiert diese Installation als Testgerät. Übergib kDebugMode. Dashboards blenden Testgeräte aus, solange Testgeräte einbeziehen nicht aktiv ist. |
logLevel | UnolinkLogLevel.warn | Wie viel in der Xcode-Konsole oder in Logcat landet (Tag Unolink): none, error, warn, info, debug. |
baseUrl | https://api.unolink.dev | Die SDK-API. Lass sie, wie sie ist. |
Der Schlüssel ist öffentlich: Er wird mit deiner App ausgeliefert und kann nur Daten für genau diese eine App melden. Siehe SDK-Schlüssel.
Funnel-Events
Füge an jedem wichtigen Moment eine Zeile hinzu. Daraus werden die Schritte in Funnel und Journeys.
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+)
Ohne RevenueCat meldest du Testphasen und Käufe selbst. Der Betrag ist ein String, damit er nie gerundet wird:
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');
Eigene Events nehmen einen Namen und bis zu 20 Eigenschaften:
Unolink.track('level_up', {'level': 3});
Die vollständige Liste mit den Namen, die im Dashboard ankommen, findest du unter Events.
Nutzer-ID und RevenueCat
Wenn du RevenueCat nutzt, verbinde es unter deiner App → Einstellungen → RevenueCat. Ruf dann nicht
purchase oder trialStarted auf: RevenueCat sendet Testphasen, Käufe, Verlängerungen, Kündigungen und Erstattungen selbst, und
Unolink ignoriert Kaufaufrufe aus der App, damit nichts doppelt zählt.
Um diese Käufe mit der Installation zu verknüpfen, melde RevenueCats eigene App-User-ID. Ab SDK 0.3.2 hält eine Zeile sie
aktuell. Ruf sie einmal beim Start auf, vor oder nach configure:
Unolink.connectRevenueCat(
() => Purchases.appUserID,
addListener: Purchases.addCustomerInfoUpdateListener,
removeListener: Purchases.removeCustomerInfoUpdateListener,
);
Unolink liest die ID, sobald RevenueCat konfiguriert ist, bei jedem Update der Kundeninfos (Käufe, logIn, logOut) und
jedes Mal, wenn die App fortgesetzt wird, und sendet sie nur, wenn sie sich geändert hat. Wenn RevenueCat noch nicht konfiguriert ist, schlägt das Lesen still fehl und wird später erneut versucht.
Der Aufruf gibt eine Funktion zurück, die die Verbindung trennt. Unolink.revenueCatUserChanged() ist auf Flutter daher normalerweise nicht nötig.
Ohne sie (oder vor 0.3.2) ruf setUserId mit RevenueCats ID auf, nach Purchases.configure, nach jedem
Purchases.logIn und Purchases.logOut, und bei jedem Start. Nutze das eine oder das andere, nicht beides:
// after Purchases.configure, logIn and logOut, and on every launch
Unolink.setUserId(await Purchases.appUserID);
Für einen Gast ist das RevenueCats anonyme ID, sodass ein Kauf, der vor der Registrierung gemacht wird, sofort mit der
Installation verknüpft wird. Nach logIn ist es die ID des Kontos. Jede ID, die eine Installation gemeldet hat, zählt,
sodass der Kauf des Gasts verknüpft bleibt. Siehe Gäste und Konten.
Unolink speichert die ID selbst nie, nur einen Einweg-Hash, der für jede deiner Apps anders ist.
Deferred Deep Links
Wenn jemand unter Android über einen Unolink-Link mit Deeplink installiert, läuft der Listener einmal, beim ersten Öffnen. Auf dem iPhone wird er nicht aufgerufen: Apple hat keinen Install-Referrer, und Unolink nutzt nie 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();
});
Der Listener wird einmal pro Installation aufgerufen. Ein Link, der angekommen ist, bevor du den Listener setzt, wird zugestellt, sobald du ihn setzt.
Nach dem Onboarding öffnen
Der erste Start beginnt meistens im Onboarding. Wenn der Screen des Links hinter Onboarding oder Anmeldung liegt, öffne ihn nicht aus dem Listener. Sobald Onboarding (oder Anmeldung) erledigt ist, lies den ausstehenden Link, öffne ihn und markiere ihn dann als verbraucht:
// 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();
}
Der Link wartet, bis du ihn als verbraucht markierst, auch wenn die App zwischendurch geschlossen wird (bis zu 30 Tage nach der
Installation; 0.3.3+). Ein neuer Nutzer, der mitten im Onboarding aufhört, bekommt ihn beim nächsten Start trotzdem, du musst
ihn also nicht selbst speichern. Ruf consumeDeferredDeepLink() auf, sobald du ihn geöffnet hast: Bis dahin gibt
getPendingDeferredDeepLink() ihn bei jedem Start zurück. Vor configure und bis Google Play geantwortet hat, ist er null, auf dem iPhone
immer.
Leg Deeplink und Parameter des Links im Dashboard fest (Links → ⋯ → Bearbeiten). Wie es funktioniert, steht unter Deferred Deep Links unter Android.
Weitere Aufrufe
| Aufruf | Was er macht |
|---|---|
await Unolink.getInstallId() | Die zufällige ID dieser Installation, oder null vor configure. Sie identifiziert keine Person und kein Gerät. |
Unolink.flush() | Sendet Events aus der Warteschlange sofort. Normalerweise nicht nötig. |
Unolink.setEnabled(false) | Schaltet das Tracking aus und löscht Events aus der Warteschlange, für deine Opt-out-Einstellung. true schaltet es wieder ein. |
Testgeräte
Mit debug: kDebugMode sind Debug-Builds Testgeräte. Ihre Daten sind echt, aber ausgeblendet, bis du Testgeräte
einbeziehen in Funnel und Journeys aktivierst. Mehr unter Testen.
Datenschutz
- Keine IDFA, keine Google Advertising ID, keine Abfrage für App Tracking Transparency, kein Fingerprinting.
- Eine zufällige Installations-ID, App-Version, OS-Version, SDK-Version, Smartphone oder Tablet, Sprache. Das Land kommt vom Netzwerk-Edge. IP-Adressen werden nie gespeichert.
- Unter iOS kommt das Privacy Manifest des nativen SDK mit dem Paket: Analysen, nicht mit der Identität verknüpft.
- Pack nie Namen, E-Mail-Adressen oder andere personenbezogene Daten in Event-Eigenschaften.
Fehlerbehebung
- MissingPluginException? Stoppe die App und starte sie erneut. Hot Reload und Hot Restart laden keinen neuen nativen Code.
- Nichts im Dashboard? Aktiviere Testgeräte einbeziehen:
kDebugMode-Builds sind standardmäßig ausgeblendet. - Immer noch nichts? Konfiguriere mit
logLevel: UnolinkLogLevel.debugund such in der Xcode-Konsole oder in Logcat nachUnolink. Ein falscher oder widerrufener Schlüssel wird als Fehler geloggt.
Mehr unter Fehlerbehebung.