Audience: Client developers integrating Zixflow SDK (iOS)
Purpose: Track push notification lifecycle events — delivery, open, and action clicks — so Zixflow can measure campaign performance accurately. See also: Push Notifications and the reference implementation in sdk-examples/ios.
Why Push Tracking Matters
When Zixflow sends a push notification to a user’s device, it records that the notification was sent. But it cannot know on its own:- Did the notification actually arrive on the device?
- Did the user open it (tap the banner)?
- Did the user tap an action button (“Shop Now”, “Remind Me”)?
The Delivery Lifecycle at a Glance
The Push Payload
Zixflow injects two special fields into every push notification’s data payload. Your app uses these to associate the tracking event with the correct campaign delivery.
These appear inside
userInfo (iOS native). The SDK’s trackMetric() method requires both to route the event correctly.
Example raw data payload received by the app:
Important:action_buttonsis a JSON string (not a nested object). Parse it withJSONSerializationbefore use.
The Three Tracking Events
1. Delivery Confirmed
Event name (sent to Zixflow):Push Notification DeliveredWhen to fire: The moment the push data payload arrives on the device — inside your
willPresent handler.SDK method:
Zixflow.instance.trackMetric(deliveryID:, deviceToken:, event: .delivered)What happens: Zixflow updates the campaign delivery record to
delivered. No profile event is stored.
Parameters:
2. Notification Opened
Event name (sent to Zixflow):Push Notification OpenedWhen to fire: When the user taps the notification banner. Fire for both body taps and action button taps.
SDK method:
Zixflow.instance.trackMetric(deliveryID:, deviceToken:, event: .opened)What happens: Zixflow updates the campaign delivery record to
opened. No profile event is stored.
With autoTrackPushEvents(true), body taps are tracked automatically. You do not need a wrapper for that path.
Parameters:
3. Action Button Clicked
Event name (sent to Zixflow):Push Notification Action ClickedWhen to fire: When the user taps a named action button (“Shop Now”, “Try It Free”, etc.). Always fire
trackMetric(opened) first, then fire this event.SDK method:
Zixflow.instance.track(name: "Push Notification Action Clicked", properties: {...})What happens: Zixflow records a
clicked delivery report and captures which button was tapped for campaign analytics.
This is a namedProperties:track()call — nottrackMetric(). There is noMetricEventenum for clicks.
Platform-Specific Integration
Token Registration
Track Delivery (Foreground — UNUserNotificationCenterDelegate)
Track Open (Background / Terminated Tap)
Action Buttons Format
Theaction_buttons field in the push payload is a JSON-encoded string containing an array of button objects. You must parse it before use.
Payload value (raw string):
- Maximum 2 buttons per notification (iOS system limit)
deeplinkmay be an empty string — handle gracefully, don’t navigate to a blank URL- Button index is 0-based
- On iOS, button labels are pre-registered at app init due to OS constraints. Use generic labels (“Action 1”, “Action 2”) and rely on the
action_namein the tracking event for analytics.
Parsing action_buttons
Building the Buttons on the Notification
Unlike Android/Flutter/RN, iOS does not let you attach dynamic buttons to an individual notification. Instead, the two generic actions (ACTION_0 / ACTION_1) are registered once at app launch, and every notification that should show buttons just needs its categoryIdentifier set to match:
title: passed to UNNotificationAction(identifier:title:options:) at registration time — generic (“Action 1”, “Action 2”) because iOS has no per-push dynamic label API. The real, campaign-specific label (action_name) and action_deeplink only exist in the payload’s action_buttons and are resolved at tap time in your didReceive response: handler.
Handling the Tap (End-to-End)
Sticky Notifications
Field:sticky (boolean, sent in the data.* payload as the string "true" / "false")
This is Android-only — there is no iOS/APNs equivalent. Notifications on iOS can always be swiped away by the user; there is no API to prevent this. The sticky field can be safely ignored on iOS.
Deep Link Handling
Every Zixflow push notification may carry adeeplink_url at the top level and per-button deeplinks in action_buttons. Your app is responsible for routing these to the right in-app screen.
Priority order for navigation on tap:
- If an action button was tapped → use
action_buttons[index].deeplink - If body was tapped → use
deeplink_url - If neither is set → open app to default screen
Decision Flowchart
Fallback Behaviour (No Zixflow-Delivery-ID)
If the push notification was sent by a non-Zixflow source,Zixflow-Delivery-ID and Zixflow-Delivery-Token will be absent from the payload.
In this case, skip trackMetric(). Push notification event names are reserved for Zixflow’s delivery pipeline — they are not stored as user profile events.
Testing
Enable.logLevel(.debug). Dashboard → Messaging → Push Notifications: Delivered, Opened, Clicked. Use a physical device.