Respectlytics Respect lytics
Menu
Flutter Notification permission granted Privacy-first

How to track notification permission grants in Flutter without personal data

Notification permission outcomes — beyond the simple opt-in moment — include OS-level permission revocations, deferred prompts, and provisional grants. Respectlytics helps developers avoid collecting personal data in the first place: in Flutter, each permission outcome is its own named event, fired at the moment the system delivers the result. Below: how to wire the call to platform-specific permission callbacks, how to distinguish the states, and what to leave to your push-delivery backend.

Wire each callback path to its own event_name: granted, denied, provisional, deferred. The platform permission API delivers the result asynchronously — fire on the result, not on the request.

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> reportPermissionState() async {
  final settings = await FirebaseMessaging.instance.getNotificationSettings();
  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 fire — user hasn't been asked.
      break;
  }
}

Call this from a WidgetsBindingObserver.didChangeAppLifecycleState listener so you catch settings-screen revocations.

Privacy & implementation notes

Notification permission state is asymmetric: granting and revoking go through different OS pathways. Granting fires through your prompt callback; revoking happens silently in Settings, with no event delivered to your app. Detect revocation lazily on next foreground if you need it.

If you prompt at multiple points in the funnel (onboarding, post-first-session, after key feature), use distinct event names per timing — push_prompt_at_onboarding, push_prompt_post_session. Conversion-rate-by-timing falls out of 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

Notification permission eventFirebase AnalyticsMixpanelRespectlytics
Per-user permission stateYes (user property)Yes (profile)Out of scope
Push token / FCM ID storedYesYesNever
Permission outcome states distinguishableManual (params)Manual (params)Distinct event_name per outcome
Time-to-grant after first promptPer-userPer-userSession-scoped

Frequently asked questions

Should we track when the user revokes permission later?

Hard to detect reliably from the app. The OS doesn't deliver an explicit revocation event — you only learn at the next foreground when getNotificationSettings() returns denied. If you do detect it, fire push_revoked_detected (with no metadata) and use it for rate analysis only.

What's the right event for re-prompting after a deferred decision?

If you prompt twice, fire distinct events for each prompt: push_prompt_v1, push_prompt_v2. Apple and Google both have anti-spam policies — a second prompt is allowed only after meaningful product context, and you should instrument that decision point.

How does this differ from `push-opt-in`?

push-opt-in is the narrow event that fires on grant. notification-permission is the broader category that includes all permission outcomes — granted, denied, provisional, deferred, revoked. Use both, with non-overlapping event names per outcome.

What about silent / background-only notification capability?

On iOS, notification permission is independent from background-fetch capability. On Android 13+, POST_NOTIFICATIONS is required for visible notifications regardless of background fetch. If you care about background-only delivery, fire a separate push_background_only event when relevant.

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.