Flutter

x3growth is a federated Flutter plugin (Dart 3.10 and Flutter 3.38 or later, iOS 15+, Android API 24+) over the native iOS and Android SDKs, connected through type-safe Pigeon channels. Consent, queue, sessions, hashing and attribution run natively; the plugin adds a navigator observer, consent widgets and automatic deep link handling.

Install

flutter pub add x3growth

iOS pulls X3Kit/Core and X3Kit/Replay through CocoaPods (cd ios && pod install), Android io.x3growth:sdk and io.x3growth:sdk-replay through Gradle.

Configure

lib/main.dart
import 'package:flutter/material.dart';
import 'package:x3growth/x3growth.dart';

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await X3.configure('pk_3x_YOUR_APP_KEY', const X3Options(
    consent: X3ConsentOptions(mode: X3ConsentMode.optIn),
    host: 'https://nordlicht.app/n3',
  ));
  runApp(const NordlichtApp());
}

X3ConsentOptions(mode: …) is required (X3ConsentMode.always, optIn, optOut); purposes: X3Purposes(analytics: true, attribution: true, recordings: false, adPlatforms: false) by default. All options: app SDK reference › Options. The plugin always passes autoScreens: false to the native SDK; screens come from the observer.

Screens

MaterialApp(
  navigatorObservers: [X3NavigatorObserver()],
  routes: {'/': (_) => const HomePage(), '/paywall': (_) => const PaywallPage()},
)

The observer reports route.settings.name on push, replace and pop. Unnamed routes are skipped (with a debug log); give them a name (RouteSettings(name: 'Paywall')) or call X3.screen('Paywall'). With go_router, add the observer to GoRouter(observers: [X3NavigatorObserver()]) and name your routes.

Events, identify, leads, purchases

await X3.track('plan_selected', {'plan': 'year', 'trial': true});
await X3.identify(user.id, email: user.email);
await X3.reset();
try {
  await X3.lead(const X3Lead(form: 'consultation', email: 'jane@example.com'));
} on X3Exception catch (error) {
  // error.code: notConfigured, invalid, disabled, rateLimited, network, server
}
await X3.purchase(X3Purchase(orderId: transactionId, value: 59.99, currency: 'EUR', productId: 'pro_yearly'));
final token = await X3.purchaseAccountToken();   // applicationUserName / obfuscatedAccountId of your billing plugin
X3.consentChanges.listen((state) => debugPrint('consent: ${state.analytics}'));

With in_app_purchase, pass the token as applicationUserName of the PurchaseParam (it becomes appAccountToken on iOS and the obfuscated account id on Android).

final state = await X3ConsentSheet.show(context, privacyPolicyUrl: 'https://nordlicht.app/privacy', appName: 'Nordlicht');
// in your settings page:
const X3PrivacySettings(privacyPolicyUrl: 'https://nordlicht.app/privacy')

X3ConsentSheet.show completes with the new state after a button, or null when the sheet was dismissed without a decision. To embed the same content in your own onboarding page instead of a bottom sheet, use X3ConsentSheetView(onDone: (state) { … }).

Material widgets with the default German and English texts (locale from Localizations.maybeLocaleOf(context)), dark mode and semantics labels; texts: X3ConsentTexts(…) overrides any string (consent UI helpers).

Handled automatically: on iOS through the plugin's application-delegate callbacks for URLs and user activities, on Android through the initial intent and new intents of the activity. Call X3.handleOpenURL(uri) only for URLs that reach your app another way, and X3.applyLinkToken(token) for magic link tokens. Universal Links and App Links need the platform setup described for iOS and Android.

Recordings

Flutter draws all widgets into one native surface, so the native wireframe recorder of 1.0.0 does not see individual widgets. With recording: X3RecordingOptions(mode: X3RecordingMode.wireframe) and the purpose recordings granted, a Flutter screen is recorded as one masked area: screen changes, taps, friction markers and your events are in the recording, the widget content is not. Analytics, attribution, purchases, leads and consent work fully.

Widget-level wireframes for Flutter (a Dart recorder with X3Mask and X3Unmask widgets) are not part of x3growth 1.0.0; they follow in a later version.