कंसोल पर जाएं

Understanding message delivery

FCM provides tools to help you get insight into message delivery. In addition to the delivery reports and notification funnel analysis built into the Firebase console, FCM provides comprehensive data export to Google BigQuery.

Keep in mind that the reporting of many of the statistics on this page, are subject to delays up to 24 hours due to batching of analytics data.

Message delivery reports

You can evaluate whether the messages you send reach your users. In the Reports tab in the Firebase console, you can view the following data for messages sent to Android or iOS FCM SDKs, including those sent via the Notifications composer and the FCM APIs:

  • Sends — The data message or notification message has been enqueued for delivery or has been successfully passed to a third-party service like APNs for delivery. See lifetime of a message for more information.
  • Received (available only on Android devices) — The data message or notification message has been received by the app. This data is available when the receiving Android device has FCM SDK 18.0.1 or higher installed.
  • Impressions (available only for notification messages on Android devices) — The display notification has been displayed on the device while the app is in the background.
  • Opens — The user opened the notification message. Reported only for notifications received when the app is in the background.

This data is available for all messages with a notification payload and all labeled data messages. To learn more about labels, see Adding analytics labels to messages.

When viewing message reports, you can set a date range for the data displayed, with the option to export to CSV. You can also filter by these criteria:

  • Platform (iOS or Android)
  • App
  • Custom analytics labels

Adding analytics labels to messages

Labeling messages is very useful for custom analysis, allowing you to filter delivery statistics by labels or sets of labels. You can add a label to any message sent via the HTTP v1 API by setting the fcmOptions.analyticsLabel field in the message object, or in the platform-specific AndroidFcmOptions or ApnsFcmOptions fields.

Analytics labels are text strings in the format ^[a-zA-Z0-9-_.~%]{1,50}$. Labels can include lower and upper case letters, numbers, and the following symbols:

  • -
  • ~
  • %

Max length is 50 characters. You can specify up to 100 unique labels per day; messages with labels added beyond that limit are not reported.

In the Firebase console messaging Reports tab, you can search a list of all existing labels and apply them singly or in combination to filter the statistics displayed.

Notification funnel analysis

A built-in Notifications funnel analysis shows you how your users respond to particular notifications sent from the Firebase console. This view includes data for targeted iOS and Android devices in these categories:

  • Notifications sent — The message has been enqueued for delivery or has been successfully passed to a third-party service like APNs for delivery. Note that targeting stale tokens or inactive registrations may inflate these statistics.
  • Notifications opened — The number of notifications opened. Reported only for notifications received when the app is in the background.
  • The number of unique users who have triggered a conversion event, if one is defined.

To see the Notifications funnel analysis:

  1. In the Notifications composer, select the Notifications tab.
  2. Click on a completed or in progress message in the message list. An expanded view including a Funnel analysis is displayed.

Analytics reports update periodically, but there can be some delay between when a user opens the notification and when the event data is available in the console. In addition to these reports under the Notifications tab, you can also build custom funnels in Analytics to visualize the completion rate of a sequence of steps in your app.

BigQuery data export

You can export your message data into BigQuery for further analysis. BigQuery allows you to analyze the data using BigQuery SQL, export it to another cloud provider, or use the data for your custom ML models. An export to BigQuery includes all messages, regardless of platform, message type, or whether the message is sent via the API or the Notifications composer.

Refer to Link Firebase to BigQuery for more information.

  1. To get started, use one of the following options:

    • Open the Notifications composer, then click Link BigQuery at the bottom of the page.

    • From the Integrations page in the Firebase console, click Link in the BigQuery card.

      This page displays FCM export options for all FCM-enabled apps in the project.

  2. Follow the on-screen instructions to enable BigQuery.

When you link your project to BiqQuery:

  • Firebase exports a copy of your existing data to BigQuery.

  • Firebase sets up regular syncs of your data from your Firebase project to BigQuery.

  • By default, all apps in your project are linked to BigQuery and any apps that you later add to the project are automatically linked to BigQuery. You can manage which apps send data.

To deactivate BigQuery export, unlink your project in the Firebase console.

What data is exported to BigQuery?

Note that targeting stale tokens or inactive registrations may inflate some of these statistics.

The schema of the exported table is:

_PARTITIONTIME TIMESTAMP This pseudo column contains a timestamp for the start of the day (in UTC) in which the data was loaded. For the YYYYMMDD partition, this pseudo column contains the value TIMESTAMP('YYYY-MM-DD').
event_timestamp TIMESTAMP Event timestamp as recorded by the server
project_number INTEGER The project number identifies the project that sent the message
message_id STRING The message id identifies a single unique message
instance_id STRING The instance id of the app the message is sent to (when available)
message_type STRING The type of the message. Can be Notification message or Data message. Topic is used to identify the original message for a topic or campaign send; the subsequent messages is either a notification or data message.
sdk_platform STRING The platform of the recipient app
app_name STRING The package name for Android apps or the bundle id for iOS apps
collapse_key STRING The collapse key identifies a group of messages that can be collapsed. When a device is not connected, only the last message with a given collapse key is queued for eventual delivery
priority INTEGER The priority of the message. Valid values are "normal" and "high." On iOS, these correspond to APNs priorities 5 and 10
ttl INTEGER This parameter specifies how long (in seconds) the message should be kept in FCM storage if the device is offline
topic STRING The name of the topic to which a message was sent (when applicable)
bulk_id INTEGER The bulk ID identifies a group of related messages, such as a particular send to a topic
device_recently_active BOOLEAN This parameter is true if the device has connected recently
event STRING The type of the event. Possible values are:
  • MESSAGE_ACCEPTED: the message was received by the FCM server and the request is valid;
  • MESSAGE_DELIVERED: the message has been sent to the device;
  • MESSAGE_DELIVERED_ON_RECONNECT: the message was sent to the device when the device re-connected;
  • MISSING_REGISTRATIONS: the request was rejected due to a missing registration;
  • MESSAGE_EXPIRED: the message expired before the device connected and it could be delivered;
  • MESSAGE_DELAYED_DOZE: the message delivery to the device was being delayed because the device is in doze mode;
  • UNAUTHORIZED_REGISTRATION: the message was rejected because the sender is not authorized to send to the registration;
  • MESSAGE_COLLAPSED: the message was replaced by a newer message with the same collapse key before it could be delivered;
  • MESSAGE_RECEIVED_INTERNAL_ERROR: there was an unspecified error when processing the message request;
  • MESSAGE_DELAYED_THROTTLED: the message delivery to the device was delayed due to throttling for its' collapse key;
  • MISMATCH_SENDER_ID: the request to send a message was rejected due to a mismatch between the sender id sending the message, and the one declared for the end-point;
  • QUOTA_EXCEEDED: the request to send a message was rejected due to insufficient quota;
  • INVALID_REGISTRATION: the request to send a message was rejected due to an invalid registration;
  • INVALID_PACKAGE_NAME: the request to send a message was rejected due to an invalid package name;
  • INVALID_APNS_CREDENTIAL: the request to send a message was rejected due to an invalid APNS certificate;
  • INVALID_PARAMETERS: the request to send a message was rejected due to invalid parameters;
  • PAYLOAD_TOO_LARGE: the request to send a message was rejected due to a payload larger than the limit;
  • DEVICE_NOT_FOUND: the request to send a message was rejected due to the device not being found in our database;
  • AUTHENTICATION_ERROR: the request to send a message was rejected due to an authentication error (check the API Key used to send the message);
  • INVALID_TTL: the request to send a message was rejected due to an invalid TTL.

What can you do with the exported data?

Count sent messages by app

SELECT app_name, COUNT(1)
FROM [<project name>:firebase_messaging.data]
WHERE
  _PARTITIONTIME = TIMESTAMP('<date as YYYY-MM-DD>')
  AND event = 'MESSAGE_ACCEPTED'
  AND message_id != ''
GROUP BY 1;

Count unique app instances targeted by messages

SELECT COUNT(DISTINCT instance_id)
FROM [<project name>:firebase_messaging.data]
WHERE
  _PARTITIONTIME = TIMESTAMP('<date as YYYY-MM-DD>')
  AND event = 'MESSAGE_ACCEPTED';

Count notification messages sent

SELECT COUNT(1)
FROM [<project name>:firebase_messaging.data]
WHERE
  _PARTITIONTIME = TIMESTAMP('<date as YYYY-MM-DD>')
  AND event = 'MESSAGE_ACCEPTED'
  AND message_type = 'DISPLAY_NOTIFICATION';

Count data messages sent

SELECT COUNT(1)
FROM [<project name>:firebase_messaging.data]
WHERE
  _PARTITIONTIME = TIMESTAMP('<date as YYYY-MM-DD>')
  AND event = 'MESSAGE_ACCEPTED'
  AND message_type = 'DATA_MESSAGE';

Count messages send to a topic or campaign from the notifications console

SELECT COUNT(1)
FROM [<project name>:firebase_messaging.data]
WHERE
  _PARTITIONTIME = TIMESTAMP('<date as YYYY-MM-DD>')
  AND event = 'MESSAGE_ACCEPTED'
  AND bulk_id = <your bulk id> AND message_id != '';

Compute fanout duration for a given topic or campaign

The fanout start time is when the original request is received, and the end time is the time the last individual message targeting a single instance is created.

SELECT
  TIMESTAMP_DIFF(
    end_timestamp, start_timestamp, MILLISECOND
  ) AS fanout_duration_ms,
  end_timestamp,
  start_timestamp
FROM (
    SELECT MAX(event_timestamp) AS end_timestamp
    FROM [<project name>:firebase_messaging.data]
    WHERE
      _PARTITIONTIME = TIMESTAMP('<date as YYYY-MM-DD>')
      AND event = 'MESSAGE_ACCEPTED'
      AND bulk_id = <your bulk id>
  ) sent
  CROSS JOIN (
    SELECT event_timestamp AS start_timestamp
    FROM [<project name>:firebase_messaging.data]
    WHERE
      _PARTITIONTIME = TIMESTAMP('<date as YYYY-MM-DD>')
      AND event = 'MESSAGE_ACCEPTED'
      AND bulk_id = <your bulk id>
      AND message_type = 'TOPIC'
  ) initial_message;

Count percentage of delivered messages

SELECT
  messages_sent,
  messages_delivered,
  messages_delivered / messages_sent * 100 AS percent_delivered
FROM (
    SELECT COUNT(DISTINCT CONCAT(message_id, instance_id)) AS messages_sent
    FROM [<project name>:firebase_messaging.data]
    WHERE
      _PARTITIONTIME = TIMESTAMP('<date as YYYY-MM-DD>')
      AND event = 'MESSAGE_ACCEPTED'
  ) sent
  CROSS JOIN (
    SELECT COUNT(DISTINCT CONCAT(message_id, instance_id)) AS messages_delivered
    FROM [<project name>:firebase_messaging.data]
    WHERE
      _PARTITIONTIME = TIMESTAMP('<date as YYYY-MM-DD>')
      AND (event = 'MESSAGE_DELIVERED' OR event = 'MESSAGE_DELIVERED_ON_RECONNECT')
      AND message_id
      IN (
        SELECT message_id FROM [<project name>:firebase_messaging.data]
        WHERE
          _PARTITIONTIME = TIMESTAMP('<date as YYYY-MM-DD>')
          AND event = 'MESSAGE_ACCEPTED'
        GROUP BY 1
      )
  ) delivered;

Track all events for a given message id and instance id

SELECT *
FROM [<project name>:firebase_messaging.data]
WHERE
    _PARTITIONTIME = TIMESTAMP('<date as YYYY-MM-DD>')
    AND message_id = '<your message id>'
    AND instance_id = '<your instance id>'
ORDER BY event_timestamp;

Compute latency for a given message id and instance id

SELECT
  TIMESTAMP_DIFF(
    MAX(delivered_time), MIN(accepted_time), MILLISECOND
  ) AS latency_ms
FROM (
    SELECT event_timestamp AS accepted_time
    FROM [<project name>:firebase_messaging.data]
    WHERE
      _PARTITIONTIME = TIMESTAMP('<date as YYYY-MM-DD>')
      AND message_id = '<your message id>'
      AND instance_id = '<your instance id>'
      AND event = 'MESSAGE_ACCEPTED'
  ) sent
  CROSS JOIN (
    SELECT event_timestamp AS delivered_time
    FROM [<project name>:firebase_messaging.data]
    WHERE
      _PARTITIONTIME = TIMESTAMP('<date as YYYY-MM-DD>') AND
      message_id = '<your message id>' AND instance_id = '<your instance id>'
      AND (event = 'MESSAGE_DELIVERED' OR event = 'MESSAGE_DELIVERED_ON_RECONNECT')
  ) delivered;