Respectlytics Respect lytics
Menu
Flutter Trial start Privacy-first

How to track trial-start events in Flutter without personal data

Trial start is the activation moment for SaaS subscription apps — and the moment most analytics SDKs start tagging the new user with payment-method metadata, plan ID, and trial duration. Respectlytics helps developers avoid collecting personal data in the first place: in Flutter, trial start is one named event, fired right after the StoreKit / Billing trial purchase succeeds. Below: where to wire the call, how to compute trial-to-paid rate without per-user joins, and the metadata you should leave in your billing system.

Fire the call right after the platform billing API confirms the trial transaction. Avoid passing the trial duration, the plan ID, or the payment-method type — your billing vendor (App Store Connect, Google Play, Stripe, RevenueCat) already has all of those with authoritative timestamps.

Install the Flutter SDK

yaml Respectlytics
# pubspec.yaml
dependencies:
  flutter:
    sdk: flutter
  respectlytics_flutter: ^3.0.0

Pure Dart — no platform channels for analytics. Same code on every platform Flutter compiles to (iOS, Android, web, macOS, Windows, Linux). On web, events are sent via the REST API; mobile platforms use the same path.

Initialize Respectlytics in Flutter

dart Respectlytics
import 'package:flutter/material.dart';
import 'package:respectlytics_flutter/respectlytics_flutter.dart';

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Respectlytics.configure(appKey: '<YOUR_APP_KEY>');
  runApp(const MyApp());
}

Initialize in main() after WidgetsFlutterBinding.ensureInitialized() and before runApp(). The future completes immediately on configuration; events queued before completion are flushed once the network is available.

Track the event in Flutter

dart Respectlytics
import 'package:respectlytics_flutter/respectlytics_flutter.dart';
import 'package:in_app_purchase/in_app_purchase.dart';

void onPurchaseUpdate(List<PurchaseDetails> purchases) {
  for (final purchase in purchases) {
    if (purchase.status != PurchaseStatus.purchased) continue;
    // Trial detection: typically by checking the SKU's offer details locally.
    if (_isTrialOffer(purchase.productID)) {
      Respectlytics.track('trial_start');
    }
    InAppPurchase.instance.completePurchase(purchase);
  }
}

The in_app_purchase package doesn't directly expose the offer type — most apps maintain a SKU → offer mapping in their config. RevenueCat's Flutter SDK exposes isTrialPeriod on the receipt if you use it.

Privacy & implementation notes

Your billing system (App Store Connect, Google Play Billing, RevenueCat, Stripe) is the system of record for plan IDs, durations, payment methods, and renewal states. Duplicating that data into your analytics pipeline produces two truths that drift over time. The Respectlytics 5-field schema simply refuses the duplication — by design.

Cohort retention curves ("of the trials started in March, what % were paying in May?") are most accurately computed against your billing data, not your product analytics. Respectlytics tells you product engagement; your billing system tells you revenue truth. Keep them separate.

The Flutter SDK is pure Dart. No MethodChannel, no platform-specific iOS or Android plugin code. The same code runs on every platform Flutter supports — including web and desktop targets. This eliminates one common audit surface ("what's the Android implementation doing?").

Always initialize after WidgetsFlutterBinding.ensureInitialized() and before runApp(). If you skip the binding step, the configure call will throw on platforms that need a binding for asynchronous I/O. The SDK documentation example uses this pattern by default.

How this compares to other analytics SDKs

Trial start eventFirebase AnalyticsMixpanelRespectlytics
Per-user identityapp_instance_id + user_iddistinct_idNever
Plan ID / trial durationRecommendedRecommendedRejected by API
Payment method typeRecommendedRecommendedRejected by API
Trial-to-paid attributionPer-userPer-user (Identity Merging)Session-scoped or via billing system
Cohort retention curvePer-userPer-userOut of scope (use billing data)

Frequently asked questions

How do we compute trial-to-paid conversion rate?

Either by session (a session that emits trial_start and later trial_conversion is converting), or — for the authoritative number — by querying your billing system. Most boards want the billing-system number for revenue, and the session-rate number for product diagnosis.

What about distinguishing 7-day vs 14-day trial cohorts?

If you offer multiple trial lengths, emit distinct event names: trial_start_7d, trial_start_14d. The aggregation gives you per-cohort conversion rate. Don't pass the duration as a parameter — the API rejects it.

Should we tag the source (organic / paid / referral)?

Distinct event names per source — trial_start_organic, trial_start_paid. Keep to your top 3–5 sources; bucket the rest as trial_start_other.

When do we fire — at button tap, or at billing confirmation?

At billing confirmation. Tap-fire produces inflated numbers when users abandon the platform billing prompt; confirmation-fire produces the truthful trial-start rate. The few extra seconds of wait are worth a non-noisy metric.

Related guides

Track what matters. Collect nothing you don't.

Five-field event schema, RAM-only event queue, no IDFA, no AAID, no persistent user IDs. Helps developers avoid collecting personal data in the first place.