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
# 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: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 event | Firebase Analytics | Mixpanel | Respectlytics |
|---|---|---|---|
| Per-user permission state | Yes (user property) | Yes (profile) | Out of scope |
| Push token / FCM ID stored | Yes | Yes | Never |
| Permission outcome states distinguishable | Manual (params) | Manual (params) | Distinct event_name per outcome |
| Time-to-grant after first prompt | Per-user | Per-user | Session-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.