Skip to main content
Complete guide to implementing push notifications in Flutter with Zixflow using Firebase Cloud Messaging (FCM) and flutter_local_notifications for display and action buttons.
Track your campaigns: With this Dart integration you call trackMetric(opened) and track action clicks yourself. For delivery, opens, and action-button details, see Push Notification Tracking. The reference implementation is lib/push_handlers.dart in sdk-examples/flutter.

Prerequisites

  1. Configure FCM in the Zixflow dashboard — add your Firebase / FCM credentials
  2. Firebase project — create a project and add both iOS and Android apps
  3. Identify users — call identify() before sending notifications so tokens attach to a profile
  4. Test on physical devices — iOS Simulator cannot receive remote pushes
A device cannot receive Zixflow pushes until you: (1) register a device token, (2) identify a person, (3) obtain notification permission.

Platform-Specific Requirements

iOS

  • iOS 13.0+, Xcode 14.0+
  • Push Notifications capability enabled
  • Optional Notification Service Extension for rich push and reliable delivered metrics
  • Physical device for testing

Android

  • API 21+ (Android 5.0)
  • google-services.json in android/app/
  • POST_NOTIFICATIONS for Android 13+ (API 33+)
  • coreLibraryDesugaring (required by flutter_local_notifications)

Step 1: Firebase Project Setup

  1. Create or open a project at Firebase Console
  2. Add an iOS app (bundle ID), download GoogleService-Info.plistios/Runner/
  3. Add an Android app whose package name matches applicationId in android/app/build.gradle, download google-services.jsonandroid/app/
applicationId must match the package name registered in Firebase, or FCM token registration fails.

Step 2: Add Dependencies


Step 3: Initialize Firebase and Zixflow

Native google-services.json / GoogleService-Info.plist is enough. FlutterFire (firebase_options.dart) is optional.

Step 4: Handle Push Notifications (Dart path)

Use FCM for receive/token and flutter_local_notifications to display notifications (including action buttons). Track opens with trackMetric and action presses with track('Push Notification Action Clicked', ...).

Token registration

Permission

Message listeners and tracking

Do not track opens with a custom event like push_notification_clicked. Use trackMetric(..., MetricEvent.opened) and the reserved action event name below.

Step 5: Identify Users

Tokens are linked to the profile when you call identify().

Local Notifications (Display + Action Buttons)

Channel ID zixflow_default, Android icon app_icon, iOS category ZX_2BTN, actions ACTION_0 / ACTION_1. Pass the full message.data map as JSON payload so taps can track and deep-link.
When showing the notification, set payload: jsonEncode(data) with the full FCM data map (include title/body for action tracking). Support up to two AndroidNotificationActions (ACTION_0 / ACTION_1), download image_url / large_icon_url for rich media, map sticky == 'true' to Android ongoing: true (with autoCancel: true), and set iOS categoryIdentifier: 'ZX_2BTN'.

Background FCM handler

The background handler must also display the local notification (so action buttons work when the app is backgrounded or terminated):

Push Payload Fields

Zixflow data payload fields used by the Dart handlers: Example:

iOS-Specific Setup

Push capabilities

  1. Open ios/Runner.xcworkspace
  2. Runner target → Signing & Capabilities
  3. Add Push Notifications
  4. Add Background Modes → enable Remote notifications

AppDelegate — register ZX_2BTN

Notification Service Extension (rich push + delivered)

  1. File → New → Target → Notification Service Extension (e.g. NotificationServiceExtension)
  2. Enable App Groups on Runner and the extension (same group ID, e.g. group.com.yourcompany.app)
  3. Podfile — NSE only (Runner does not need zixflow/fcm for this Dart path):
  1. NotificationService.swift:
Use cdpApiKey (not apiKey) and set .appGroupId(...) to the same App Group as the host app.

Android-Specific Setup

Gradle (plugins DSL)

android/settings.gradle:
android/app/build.gradle:
Place a white notification icon drawable named app_icon (referenced by AndroidInitializationSettings('app_icon')).
After tracking Opened / Action Clicked, open URLs the same way as push_handlers.dart + navigation.dart:
Attach navigatorKey to MaterialApp. Full open / action / delivered contract: Push Notification Tracking.

Testing

  1. Register token + identify() a test user
  2. Enable LogLevel.debug
  3. Send a test push from the Zixflow dashboard (include action_buttons if testing buttons)
  4. Use a physical iOS device; Android emulator needs Google Play Services

Troubleshooting


Best Practices

  1. Initialize Firebase before Zixflow, then your push handlers
  2. Identify users after login; clearIdentify() on logout
  3. Store the full FCM data map in the local-notification payload for tracking
  4. Prefer button deeplink over deeplink_url on action taps
  5. Cancel the notification ID on action press (Android)
  6. Re-initialize Zixflow in the background notification-response isolate
  7. See Push Notification Tracking for metrics details