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
# 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
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
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 event | Firebase Analytics | Mixpanel | Respectlytics |
|---|---|---|---|
| Per-user identity | app_instance_id | distinct_id | Never |
| Variant / experiment ID as parameter | Recommended | Recommended | Use distinct event_name |
| Placement (home, settings, …) as parameter | Recommended | Recommended | Use distinct event_name |
| Computed metric: paywall_view → paywall_purchase rate | Per-user | Per-user | Session-grouped |
| Bot / accidental view filtering | Heuristic per user | Heuristic per user | Country + 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.