Push metrics and message statuses

How it works

While we track the status of each individual message as it goes through Customer.io, push notifications can be trickier to track than other message channels for two main reasons:

  1. A person can have multiple devices, and you can send a message to all of a person’s devices. How your workspace tracks deliveries depends on whether you have multi-app support enabled in your account:
    • If multi-app support is enabled: Your workspace logs a delivery for each device. If a push message is sent to two devices associated with one customer person, that counts as two sent push notifications.
    • If multi-app support is not enabled: When you send to All Devices, your workspace aggregates metrics across all of a person’s devices. If a push message is sent to two devices associated with one customer person, that counts as one, not two, sent push notifications.
  2. Push notifications go through an intermediary—the push provider (APNS or FCM). We report statuses between us and your push provider; devices using our SDK report back delivered and opened metrics back to Customer.io—but there can be a slight delay in reporting these metrics. And Customers who have an earlier version of your app that doesn’t have our SDK installed may not report these statuses back at all.
flowchart LR a(trigger push<br>notification) a-->b{Is push finished<br>sending to all devices} b-.->|No|c(Push Attempted) b-->|Yes|i{Is at least one<br>send successful?} i-->|Yes|d(Push Sent) i-.->|No, liquid<br>failure|j(Push Failed) i-.->|No, bounced<br>tokens|k(Push Bounced) d-->e{Is device online?} e-->|Yes|z(Push Delivered) z-->g{Does person<br>tap push?}-->|yes|h(Push Opened) e-.->|No|x(Wait for device<br>to come online)-.->z

Delivery metrics when multi-app support is enabled

If multi-app support is enabled on your account, your push metrics reflect one delivery per device. This means if you send a push notification to two devices associated with one customer person, your workspace logs two sent push notifications, not one. Each delivery shows the exact payload sent to that device and the device it went to, so you can troubleshoot per device instead of digging through a single combined record.

Deliveries created from the same send are related: when you look at one of them, you’ll see links to the others. You see related deliveries in the delivery details and on the person’s journey timeline.

Because each device gets its own delivery, your push metrics count messages to devices. If you send a push to a person with two devices, you’ll see two deliveries—and your automation metrics count two Sent. Other metrics work the same way: an Opened belongs to the delivery for the device where the tap happened.

If you sent pushes to All devices before multi-app support was enabled, your sent counts may start to look higher than before because your workspace now counts a delivery for each device, not each customer person. There’s no change to how your audience receives push notifications, just a change to how your workspace reports deliveries.

Mobile metrics

In general, you’re concerned with a few metrics for push notifications:

  • Sent: We’ve sent a message to the push provider.
  • Delivered: The device reported that it received the message.
  • Opened: The user tapped the notification; if the notification includes a deep link, this takes the user into the app.
  • Converted: The user achieved a goal and you want to report that back to Customer.io.

You can measure success of push notifications against the number of Sent or Delivered messages, but there’s an important distinction between the two: Sent is reported by the push provider (APNS or FCM) and Delivered is reported by the device.

When you send a push notification, it’s much more likely that it’ll report Sent right away, but it may not report Delivered (or other metrics on the device) until the user opens the app. When you measure the success of messages, just remember that your Sent is immediately trustworthy, and the Delivered count may change over time as people open your app.

What push metrics do we capture from devices and when?

Devices report message deliveries, opens, and conversions. But unlike other channels, push notification reporting depends on the status of your app on the recipient’s device.

  • If your app is in the foreground, we’ll typically report metrics (if you show push notifications when your app is in the foreground).
  • If your app is in the background, we might be able to report metrics based on the device’s operating system and your SDK implementation. See Reporting metrics while apps are in the background for more information.
  • If the app is closed (sometimes called the killed or cold state), we can’t report metrics until the user opens your app. The exception is Delivered on iOS: your app’s Notification Service Extension reports it even when your app is closed.

Android and iOS have strict rules about what we can do when apps are in the background. This can cause a delay between when you send a message and when we can report metrics relating to deliveries, opens, and so on.

In general, this is an issue for deliveries, which happen independently of your app’s state on a recipient’s device—as opposed to an Opened or Converted events. For example, if your push notifications include deep links, your link will open the app and report metrics. Your notification is only likely to be opened in the background if it doesn’t include a deep link into your app.

EventReported in ForegroundReported in BackgroundReported in Closed
SentN/AN/AN/A
Delivered✅✅*iOS only***
Opened✅✅**❌
Converted✅N/A❌
* Background reporting is dependent on the device operating system and user settings.
** Opening a message while the app is in the background typically applies to messages that don’t contain deep links. If a message has a deep link into your app, it’ll bring the app to the foreground and we’ll report metrics.
*** When a notification with mutable-content set to 1 arrives, iOS starts your app’s Notification Service Extension, even when your app is closed, and the extension reports the delivery. Customer.io sets mutable-content for you unless you send a custom payload.

Reporting metrics when apps are in the background

Android and iOS both have strict, but slightly different rules for what our SDKs are allowed to do when apps are in the background.

For iOS, the SDK reports delivery from your app’s Notification Service Extension, which has 30 seconds after receiving a notification to report metrics back to Customer.io.

For Android, apps in the background will report metrics back to Customer.io if:

  • The device isn’t in Doze mode.
  • The device and/or your app isn’t in Deep Sleep mode.
  • The user hasn’t otherwise optimized battery usage in a way that blocks background activity.

Why are messages sent but not delivered?

We mark a message sent when we send it to the push provider (APNS or FCM). But we can’t verify delivery until a device reports a delivered event back to Customer.io.

Because the SDK reports delivery, a message might show sent but not yet show delivered when:

  • The app is closed.
  • The recipient’s device is offline.
  • The recipient doesn’t have a version of your app containing the Customer.io SDK.

In many cases, the push notification probably made it to your recipient’s device, but we won’t know about it because the app can’t report back delivered metrics until it’s opened or put in a state that allows it to report back metrics (like foregrounding the app).

flowchart LR a{Is <code>unsubscribed</code> true?} a-.....->|yes|c(push not sent) a-->|no|b(push sent) b(push sent) b-->d{Is person opted-into<br>notifications?} d-...->|no|h(push not delivered) d-->|yes|f{Does the app include<br>the Customer.io SDK?} f-..->|no|i(push delivered but delivery <br>not reported to Customer.io) f-->|yes|k{Is device online and<br>able to report?} k-.->|no|l(Wait for app<br>to come online) l-.->k k-->|yes|j(push delivered and marked<br> <code>delivered</code> in Customer.io)

Differences in delivered metrics for Android and iOS

Android and iOS handle deliveries differently, which means that you’ll see a significant difference in delivered metrics between the two platforms.

iOS devices only report delivery when a user has opted into notifications and a push notification appears to the user (whether in the notification tray, lock screen, etc). But Android reports the delivery of notifications regardless of opt-in status. This means that a message can be delivered to a device, suppressed because a user hasn’t opted into notifications, and the device will still report back that the message was delivered.

Because Android reports delivery regardless of opt-in status, you’ll likely see higher delivered metrics for Android devices than iOS devices. We’re working on ways to reconcile the difference between the two platforms in the future, so that we can give you a better understanding of your audience’s engagement.

iOS delivery reporting requires the Notification Service Extension

On iOS, our SDK reports Delivered automatically only from your app’s Notification Service Extension (NSE). iOS starts the NSE for notifications that set mutable-content to 1. Customer.io sets it for you unless you send a custom payload. In a custom payload, you need to set it yourself.

If your app doesn’t include the NSE, the SDK doesn’t report Delivered, even when people receive the notification, unless you report delivery yourself. If someone taps the notification, the SDK still reports Opened.

To add the NSE, follow the push setup for your SDK:

Fix low delivered rates

When your Delivered count is much lower than Sent, check whether the devices can report back:

  • Add the Notification Service Extension to your iOS app. Without the NSE, our SDK doesn’t report Delivered on iOS.
  • Set mutable-content to 1 in custom payloads. iOS only starts the NSE for notifications that set it. Customer.io sets it for you in every other push message. See custom payloads.
  • Set up App Groups on iOS. iOS can stop the NSE before it finishes reporting a delivery. With App Groups, the SDK sends those deliveries the next time someone opens your app. Set up App Groups for iOS, React Native, Flutter, or Expo.
  • Release app versions that include our SDK, and encourage people to update. Devices on app versions without the SDK (and, on iOS, the NSE) can receive notifications but can’t report Delivered.
  • Register devices every time your app launches. Device tokens change, for example when someone deletes and installs your app again or updates their OS, so send us the device on every launch to keep tokens current.

Push reporting when migrating from another provider

If you migrated a push audience from another provider, your audience may have versions of your app that don’t include our SDK. These devices can still receive notifications (assuming you use the same certificates in Customer.io and your previous service provider), but they won’t report back delivered metrics to Customer.io unless you gather this data using a third party like Segment or Rudderstack and send these events to Customer.io.

Web push metrics

Web push uses the same metrics as mobile push. Instead of our SDK in your app, the Customer.io service worker on your website reports them from the browser:

  • Sent: Customer.io handed the notification to the browser’s push service.
  • Delivered: The service worker showed the notification. The browser has to be running to show it, so a browser that was closed reports delivery when the person opens it again, as long as the push service still holds the notification.
  • Opened: The person clicked the notification or one of its action buttons. When they click a button, the delivery records which button it was.

If delivered and opened metrics are missing, see troubleshoot web push.

Metrics by platform

When an automation sends to browsers, its metrics can show iOS, Android, and Web separately:

  • On the automation’s Overview, when you filter to the Push channel, the Sent and Opened cards show a line for each platform next to the push total.
  • On Metrics > Delivery metrics, the Platform menu shows the numbers for one platform. All platforms shows the total across iOS, Android, and Web.

The split by platform only covers deliveries since March 23, 2026, so older deliveries count toward the total but not toward a platform.

Push notification statuses

You can look up the status of each push notification by clicking on the message in the Deliveries page. This can help you understand whether a message was sent, delivered, opened, or converted.

How statuses map to deliveries depends on whether multi-app support is enabled in your account:

  • Multi-app support enabled: Your workspace records one delivery per device, so each device has its own status. A push to a person’s two devices creates two deliveries, and each one reports Sent, Delivered, Opened, and other statuses independently.
  • Multi-app support not enabled: When you send to All Devices, one delivery aggregates statuses across all of a person’s devices. See Push notification status when targeting all devices for how each status aggregates.
Attempted: We're in the process of sending a message to the push notification service.

This status means that your push notification has been created and we’ve tried to send it via the appropriate service—Apple’s Push Notification Service (APNS) or Firebase Cloud Messaging (FCM)—which then would send to your customer’s device. If there are errors with our attempt, we’ll try to send it again up to ten times.

Sent: We've successfully sent your message to the push notification service.

This status does not indicate that a message has been successfully delivered. It only means that the push payload and credential were valid and the push notification service accepted the payload.

Note that the total number of “Sends” in your automation metrics includes people whose messages bounced and were suppressed. We do this to help calculate your total audience size when you send a message: sends minus suppressed and bounced messages equals total recipients.

Delivered: The device reported back that it received the message.

There are a number of things that can affect or delay us reporting message delivery. See What push metrics do we capture from devices and when? for more information.

Opened: The user tapped the notification.

We report a message as Opened when someone taps on a push notification sent to any of their devices. This metric is reported back to Customer.io when someone opens your app (or already has the app open).

Failed: Our attempts to send a push notification were unsuccessful.

This status occurs when none of the attempts to send a push notification to the recipient’s devices are successful. You’ll be able to see the failure reasons on the Delivery page. If we’re able to send a push notification to at least one of a person’s devices, we’ll report the message as Sent.

Converted: The user achieved a goal and your app reported that back to Customer.io.

This is treated the same as emails; when a user matches your automation’s conversion criteria, the message nearest the conversion is marked as Converted.

Opens and clicks are the same things in push notifications

Unlike other channels, where people have to open a message before they can click a link, people can read a notification right when it’s delivered—they don’t have to open it. So, in push notifications, we track Opened in the same way that most other messages track Clicked.

Push notification status when targeting all devices

For other message channels, you send your message to an individual email address, phone number, etc—a message is one-to-one with a recipient. But for push notifications, you can target all of a person’s devices, which affects how we track the status of messages and associated metrics. How your workspace tracks these statuses depends on whether multi-app support is enabled.

In general, we recommend that you use Last used device when you send a message so you don’t overwhelm your audience with messages across all their possible devices.

When multi-app support is enabled

Your workspace records one delivery per device, so each device has its own status. When you send to All Devices and a person has two devices, you’ll see two deliveries—each with its own Sent, Delivered, Opened, and other statuses—and your metrics count one delivery per device. A message counts as Sent as soon as we send it to the push provider for that device, and a delivery is Delivered or Opened based on what that specific device reports. See Delivery metrics when multi-app support is enabled for more information.

When multi-app support is not enabled

Your workspace aggregates statuses across a person’s devices into a single delivery, and your metrics count one delivery per person rather than per device. For some statuses, like Sent, we count a status when it has occurred for all of a person’s devices. For others, like Opened, we count it when it has occurred for any of a person’s devices. For metrics, we’ll display an aggregate metric for the person rather than each device they own, because we (and you!) monitor engagement at a personal level, not a device level.

For example, when you use Last Device, a sent message is a single push notification sent to the push provider. When you use All Devices, we don’t count a message as being sent until we’ve sent a message to the push provider for each of a person’s devices.

Do we record a status when it’s true for all of a person’s devices or any of their devices?
StatusAll DevicesAny DeviceDescription
Attempted✅We’re in the process of sending messages.
Sent✅We’ve sent messages to the push provider.
Delivered✅Your app reported back that it received the message.
Opened✅Your app reported back that the message was opened.
Converted✅The person matched your automation’s conversion criteria.
Failed✅We were unable to send messages to the push provider. This is typically due to a liquid error. See Failed for more information.
Undeliverable✅We couldn’t attempt delivery. This happens when a user has no devices associated with them.
Bounced✅There’s a temporary delivery issue, like a soft bounce in an email. This usually happens when a user has uninstalled your app, their device token has expired or their device token is invalid.

Message failures

If you see a message Failed, you can see the failure reasons on the Delivery page. Here’s a list of failure reasons you might see, what they mean, and how to fix them.

Failure ReasonDescription
Liquid error: variable is missingThe recipient didn’t have a value for a variable you used in your message. For example, if your message used {{customer.email}} and the customer didn’t have an email attribute, the message will fail. Check that you’re using the correct variable name and either set a fallback or that the recipient has a value for that variable.
Customer doesn’t existA rare error indicating that the value you’ve used for the recipient doesn’t exist. Make sure you’re using the correct customer ID or email for a message.
Customer is unsubscribedThis error indicates that the customer has opted out of receiving messages. Verify the customer’s subscription status to make sure they can receive messages.
Credentials not foundYour push credentials failed or were otherwise empty. Check that you’ve provided your push certificate and that it hasn’t expired.

Provider response in exported delivery data

When you export deliveries, the failure_message column for an iOS or Android push notification holds the response from APNs or FCM for each device. Customer.io fills it for every send, including successful ones, so a value in this column isn’t an error indicator and isn’t proof that a device received the message.

The value is a JSON array with one entry for each device the delivery went to. Each entry includes the device’s token (id), its platform, the HTTP status that FCM or APNs returned, a detail code when the provider returned an error, and bounced and suppressed flags:

  • status of 200 with an empty detail: FCM or APNs accepted the request. This is the same as the Sent status. It doesn’t mean the device has shown the notification.
  • bounced set to true: The provider rejected the device token, and Customer.io won’t retry the send to that device. The detail code tells you why:
    • APNS_Unregistered, APNS_BadDeviceToken, FCM_UNREGISTERED, FCM_INVALID_TOKEN, or FCM_DEVICE_TOKEN_DISABLED usually mean someone uninstalled your app or the token expired.
    • APNS_DeviceTokenNotForTopic, APNS_TopicDisallowed, or FCM_SENDER_ID_MISMATCH mean the token belongs to a different app than the push credentials you sent with. Check that your app’s bundle ID or Firebase project matches the credentials in your workspace.
  • suppressed set to true: An earlier send to this device already returned one of the preceding token errors, so Customer.io didn’t send to it again. Customer.io sends to the device again after your app registers it again.

How a rejected token affects a delivery’s status depends on whether multi-app support is enabled in your account:

  • Multi-app support enabled: Your workspace records one delivery per device, so each delivery’s array has one entry. When a device’s token is rejected, that device’s delivery shows Bounced, even if the person’s other devices received the message.
  • Multi-app support not enabled: When you send to All Devices, one delivery covers all of a person’s devices, and its array has an entry for each device. The delivery shows Bounced only when no device accepted the message. If at least one device accepted it, the delivery shows Sent, and only the rejected devices’ entries have bounced set to true.

Web push deliveries use the same format, with platform set to web. Most of their detail codes start with WEBPUSH_. See web push failure reasons for what each code means.

Set automation goals to measure engagement

Unlike email, recipients can read and react to your push notification without “opening” it.

While you can measure engagement with Opened metrics—where a person taps on a push notification to go to a link—you may find more success setting an automation goal to measure whether or not a message helps you achieve a specific business goal.

Ideally, your messages have a call to action, a result you want your audience to achieve. You want your audience to finish setting up their profile in your app, complete a purchase, sign up for a class, and so on.

If you capture these actions as goals, you’ll be able to understand how many people engage with your message and achieve your goal—which is a much better metric of success than raw sent and delivered metrics.

We track metrics at the message and journey level. Setting an automation goal as an event that you want your audience to achieve—a completed purchase, visiting a specific page, etc—can help you understand how your push notifications contribute to your business goals, even when it’s difficult to track the status of individual push notifications.

Automation Overview data

On the Overview page, you can see how your push notifications perform in your automation.

Delivered

You can track delivery using our SDKs, or by adding custom code to your app to report delivery metrics back to Customer.io when a customer receives a push.

Opened

To track opened metrics, you need to either integrate with our SDKs or add some code to your app to detect when opens occur and then send “open” events to Customer.io as documented in our Technical Integration Guide. Note, you need to include the CIO-Delivery-ID and CIO-Delivery-Token parameters from the push when sending open events to Customer.io.

Delivery Logs data

image.png

When filtering deliveries, you can choose to only see push notifications. In this view, you’ll be able to see:

  • The name of the push notification and a link to the message
  • Which customer triggered that message, and how many of their devices we attempted to send to
  • When the push notification was attempted
  • The push notification status (sent, failed, attempted, etc.)
  • Conversion information where applicable

You’ll also have the option to retry sending the push notification if its status is ‘failed’:

image.png
Updated November 5, 2026