@react-native-firebase/messaging for FCM and @notifee/react-native for display and action buttons.
Track your campaigns: Track opens withZixflow.trackMetric({ event: MetricEvent.Opened })and action presses withZixflow.track('Push Notification Action Clicked', ...). See Push Notification Tracking. Reference implementation:src/pushHandlers.tsin sdk-examples/react-native.
Prerequisites
- Configure FCM (and APNs for iOS) in the Zixflow dashboard
- Add Firebase config files (
google-services.json,GoogleService-Info.plist) - Call
identify()so device tokens attach to a user - Test on a physical device for iOS
Dependencies
Architecture
The Zixflow native FCM service may still run in parallel for token/delivery on Android. This stack owns display and open/action tracking in JavaScript — no custom Kotlin action installer required.
Initialize handlers
AfterZixflow.initialize():
index.js (before AppRegistry.registerComponent):
showNotification path so action buttons work when the app is backgrounded or terminated.
Display with notifee (including action buttons)
Parseaction_buttons (max 2). Use channel zixflow_default, iOS categoryId: 'ZX_2BTN', and store the full data map on the notification for tap tracking.
Zixflow-Delivery-ID, Zixflow-Delivery-Token, title, body, deeplink_url, image_url, large_icon_url, action_buttons, sticky, sound, badge.
Open and action tracking
WiretrackOpened / handleNotifeeEvent / handleDeeplink as in the example pushHandlers.ts:
- Body tap →
trackMetric(Opened)+ opendeeplink_url - Action tap →
trackMetric(Opened)+track('Push Notification Action Clicked')+ cancel notification + open buttondeeplink(elsedeeplink_url)
Custom Action Buttons — iOS category
RegisterZX_2BTN at launch so system / notifee notifications can show ACTION_0 / ACTION_1:
application(_:didFinishLaunchingWithOptions:) (see the example AppDelegate). Also configure Firebase (FirebaseApp.configure()).
When notifee displays the notification, action presses are handled in JS via notifee.onForegroundEvent / onBackgroundEvent — you do not need a separate AppDelegate didReceive tracker for that path.
iOS Capabilities
- Open the
.xcworkspacein Xcode - App target → Signing & Capabilities
- Add Push Notifications
- Add Background Modes → Remote notifications
App Groups
App Groups improve delivery metric reliability on iOS. If the system terminates the Notification Service Extension before a tracking request finishes, the SDK can recover pending metrics on the next app launch when both targets share an App Group. Add the same App Group to the host app and the Notification Service Extension:- Host app target → Signing & Capabilities → + Capability → App Groups
- Create an ID such as
group.com.yourcompany.yourapp.zixflow - NSE target → App Groups → select the same identifier
.appGroupId(...) in both the host app push init and the NSE init. Values must match the Xcode entitlements.
Host app (AppDelegate, APNs example):
MessagingPushFCM.initialize with the same .appGroupId(...).
Notification Service Extension:
group.com.zixflow.demo.rn as a concrete sample.
If you omit .appGroupId(...), the SDK may try a default patterned identifier. Prefer an explicit App Group ID to avoid mismatches.
Android Setup
- Place
google-services.jsoninandroid/app/ - Apply the Google Services Gradle plugin
- Declare
POST_NOTIFICATIONSand request it at runtime on API 33+ - Create the notifee channel
zixflow_defaultin JS (as above)
Notification Channels
On Android 8.0+, notifications belong to a channel that controls sound, importance, and user settings.When you display with notifee (example path)
The React Native example creates the channel in JavaScript:notifee.displayNotification({ android: { channelId: 'zixflow_default', ... } }). Manifest io.customer.notification_channel_* meta-data does not configure this notifee channel.
When the native Zixflow SDK displays the notification
Zixflow creates one channel per app when the first Zixflow push is delivered (unless you customize it via manifest meta-data).
Importance levels:
0 min, 1 low, 2 medium, 3 default/high, 4 urgent.
Customize native SDK channel in AndroidManifest
Set meta-data under<application> before you ship a build that creates the channel. After users have the channel, Android only lets you reliably change the name; ID and importance are sticky for that channel ID.
Use these exactIf you previously shipped with an undesired channel ID, Android allows deleting a channel and creating another with new settings. Do this carefully in native code (users lose prior preference for the old ID):android:namestrings — the native SDK reads those keys. Changing the displayedandroid:valuefor name is supported after release; changing ID/importance for an existing channel generally has no effect for users who already have that channel.
Deep Links
Deep links send users to a specific screen when they tap a push (or an action button). The React Native example opens them in JS after tracking:Android
Add intent filters on your main activity inAndroidManifest.xml:
Push click behavior (Android)
Control activity recreation when a notification is tapped:
Opened metrics are tracked for all options when using the default Zixflow push path.
iOS
App scheme
- In Xcode → target Info → URL Types, add your scheme (for example
yourapp). - Forward opens to React Native:
Universal Links
Follow React Native’s Linking / associated domains setup forhttps:// links that should open the app when installed.
React Navigation
Payload link fields
Usedeeplink_url for body taps and action_buttons[].deeplink for action taps (fallback to deeplink_url). Open them with handleDeeplink after tracking — see Push Notification Tracking.
If deep links fail when the app was killed on iOS, see Troubleshooting.
Multiple Push Providers
The example app uses@react-native-firebase/messaging + @notifee/react-native for receive and display, and tracks opens/actions in JS. If another library also receives FCM, avoid double display and double metrics.
Option 1: Display yourself (Firebase + notifee)
Own display with notifee (or similar), then:- Track opened / action clicked with
trackMetric/track(see Push Notification Tracking) - Optionally track delivered with
trackMetric(Delivered), or forward for tracking only:
onMessageReceived(..., true) if notifee already displayed the same message.
Option 2: Forward payloads for Zixflow to display
Background helper (avoids duplicate display when FCM already showed a
notification payload):
Example with @react-native-firebase/messaging
Option 3: Register Zixflow’s FCM service
Hand Android FCM delivery to Zixflow by declaring the service inAndroidManifest.xml under <application>:
Identify Users
Testing
- Register token + identify a test user
- Send a push from the Zixflow dashboard (include
action_buttonsto test buttons) - Use a physical iOS device
- Enable
ZixflowLogLevel.Debugduring development