Respectlytics Respect lytics
Menu
Flutter Push notification opt-in Privacy-first

How to track push notification opt-in in Flutter without personal data

Push opt-in rate is one of the highest-leverage signals in mobile analytics: it gates every re-engagement channel you have. Respectlytics helps developers avoid collecting personal data in the first place: the opt-in event in Flutter is just push_optin — no device token, no APNs identifier, no Firebase Cloud Messaging registration ID. Below: how to wire the call into the system permission callback on Flutter, how to A/B-test prompt timing without per-user assignment, and the trade-off you make by not storing a per-user opt-in state.

Wire the call into the same callback that receives the system permission result. On success, emit push_optin. If you also want to measure declines (most teams do), emit push_decline on the negative result. Don't pass the device token or any registration ID as metadata — your push backend already has those.

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:firebase_messaging/firebase_messaging.dart';

Future<void> requestPushPermission() async {
  final settings = await FirebaseMessaging.instance.requestPermission(
    alert: true, badge: true, sound: true,
  );
  switch (settings.authorizationStatus) {
    case AuthorizationStatus.authorized:
      Respectlytics.track('push_optin');
    case AuthorizationStatus.provisional:
      Respectlytics.track('push_provisional_optin');
    case AuthorizationStatus.denied:
      Respectlytics.track('push_decline');
    case AuthorizationStatus.notDetermined:
      // Don't emit — user hasn't been asked.
      break;
  }
}

If you use a non-Firebase push provider (e.g. flutter_local_notifications + your own server), the same status flow applies — request permission, branch on the result, emit one event name per branch.

Privacy & implementation notes

Your push-delivery backend (APNs, FCM, OneSignal, Pusher Beams, etc.) already has the device push token — that's where it lives operationally. Sending it to Respectlytics would just be re-creating a per-user dataset you've already built elsewhere. The API rejects it.

Most push-related product decisions are about rate, not state: "does moving the prompt to post-onboarding move our DE iOS opt-in rate?". You don't need per-user opt-in state in your analytics pipeline to answer that — you need session-grouped event counts.

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

Push opt-in eventFirebase AnalyticsMixpanelRespectlytics
Device push token storedYes (FCM token in user property)Yes (in profile)Never
Per-user opt-in stateYesYesOut of scope (your push backend tracks this)
Prompt timing as event propertyRecommendedRecommendedUse distinct event_name
iOS provisional opt-in distinguishableManual (via param)Manual (via property)Use distinct event_name (push_provisional_optin)
Opt-in rate by country / platformYesYesYes (default aggregation)

Frequently asked questions

How do we know which users opted in if we don't store user state?

You don't, in your analytics. Your push-delivery backend (APNs, FCM, OneSignal, etc.) already has the authoritative opt-in state per device token — that's its job. Respectlytics tells you the opt-in rate over sessions, which is the metric you optimize for product decisions.

Can we A/B-test opt-in prompt timing?

Yes — emit distinct event names per prompt-timing variant: push_optin_at_onboarding, push_optin_post_first_session, etc. The aggregation gives you per-variant conversion rate without any per-user assignment stored.

Should we track when the prompt was *shown* in addition to the result?

Yes, with two event names: push_prompt_shown and push_optin (or push_decline). The session-grouped count gives you prompt → grant rate directly.

What about iOS 15+ provisional authorization?

If you use provisional authorization (which doesn't show a prompt and delivers quietly until the user upgrades to full), emit push_provisional_optin as a distinct event. It's a different state with different downstream implications, so don't conflate it with the explicit opt-in event.

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.