Respectlytics Respect lytics
Menu
Flutter Paywall view Privacy-first

How to track paywall views in Flutter without personal data

Paywall view is the top of the monetization funnel — and the place teams over-instrument with placement metadata, experiment assignment IDs, and per-user variant tracking. Respectlytics helps developers avoid collecting personal data in the first place: in Flutter, paywall view is one named event, with no payload. If you A/B-test placements or copy variants, encode the variant into the event name. Below: the Flutter pattern, the conversion-rate math you can still do, and the metadata trade-offs.

Fire the call when the paywall surface is actually visible to the user — not on push, not on configure. SwiftUI/Compose/RN/Flutter visibility callbacks are the right hook. Don't pass the variant ID, the placement, or the offer config as metadata.

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:flutter/widgets.dart';
import 'package:respectlytics_flutter/respectlytics_flutter.dart';

class PaywallScreen extends StatefulWidget {
  const PaywallScreen({super.key});
  @override
  State<PaywallScreen> createState() => _PaywallScreenState();
}

class _PaywallScreenState extends State<PaywallScreen> {
  @override
  void initState() {
    super.initState();
    // initState fires when the widget is inserted into the tree.
    Respectlytics.track('paywall_view');
  }
  @override
  Widget build(BuildContext context) => /* paywall content */ Container();
}

If you use RouteObserver, prefer didPush for views shown via navigation — it accounts for back-navigation re-entries that initState does not.

Privacy & implementation notes

Fire the event on actual visibility, not on data fetch. SwiftUI's .onAppear, Compose's LaunchedEffect(Unit), RN's useFocusEffect, and Flutter's AfterFirstLayout mixin are the canonical hooks. Tracking on configure inflates the rate with paywalls the user never saw.

Experiment IDs are tempting because they look harmless — they're really not. A stable experiment ID across thousands of sessions becomes a per-user fingerprint via the variant assignment pattern. Encode the variant in the event name; discard the assignment ID.

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

Paywall view eventFirebase AnalyticsMixpanelRespectlytics
Per-user identityapp_instance_iddistinct_idNever
Variant / experiment ID as parameterRecommendedRecommendedUse distinct event_name
Placement (home, settings, …) as parameterRecommendedRecommendedUse distinct event_name
Computed metric: paywall_view → paywall_purchase ratePer-userPer-userSession-grouped
Bot / accidental view filteringHeuristic per userHeuristic per userCountry + session aggregate

Frequently asked questions

How do we measure paywall conversion rate without joining view → purchase per user?

Per-session. A session that emits both paywall_view and paywall_purchase is a converting session. The ratio across all sessions is your conversion rate. The noise from sessions where the user views the paywall on day 1 and converts on day 3 is small at scale — and your billing system already has the longitudinal truth.

Can we A/B-test paywall variants?

Yes. Emit paywall_view_a, paywall_view_b, etc., and pair with paywall_purchase_a, paywall_purchase_b. Per-variant conversion rate falls out of session-grouped event counts.

What about tracking which placement the paywall was shown from?

Distinct event names per placement: paywall_view_home, paywall_view_settings, paywall_view_post_onboarding. Keep the taxonomy short — under 8 placements is comfortable; past that, bucket the long tail.

Should we track the offered price or product set?

No. Pricing changes belong in your release notes and your billing system, not in your analytics pipeline. Mixing them in produces stale data the moment you change a price.

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.