Как доставляются сообщения

Чтобы устранить неполадки с доставкой сообщений, воспользуйтесь инструментом устранения неполадок FCM и ознакомьтесь с этой записью в блоге, чтобы узнать, почему вы можете не получать сообщения. Вы также можете перейти на панель мониторинга статуса FCM, чтобы узнать, нет ли сбоев в работе сервиса.

FCM также предоставляет три набора инструментов, которые помогут вам оценить эффективность отправки сообщений и стратегии:

  • Firebase Отчеты о доставке сообщений из консоли
  • Агрегированные показатели доставки Android SDK из Data API Firebase Cloud Messaging
  • Полный экспорт данных в Google BigQuery

Экспорт данных в BigQuery и вкладка Отчеты в консоли Firebase требуют Google Analytics. Вы можете включить Google Analytics в консоли Firebase, выбрав Настройки > вкладка Интеграции. Агрегированные данные о доставке не требуют для работы Google Analytics.

Обратите внимание, что многие показатели на этой странице могут обновляться с задержкой до 24 часов из-за пакетной обработки данных.

Отчеты о доставке сообщений

В консоли Firebase перейдите на вкладку DevOps & Engagement (DevOps и взаимодействие) > Messaging (Обмен сообщениями) > Reports (Отчеты), чтобы посмотреть следующие данные о сообщениях, отправленных в SDK FCM для платформ Android или Apple, в том числе с помощью конструктора уведомлений и API FCM:

  • Отправлено – сообщение с данными или уведомление поставлено в очередь на доставку или успешно передано стороннему сервису, например APNs, для доставки. Обратите внимание, что статистика по отправленным сообщениям может обновляться с задержкой в несколько часов. Подробнее о сроке хранения писем…
  • Получено (доступно только на устройствах Android). Приложение получило сообщение с данными или уведомление. Эти данные доступны, если на принимающем устройстве Android установлена версия FCMSDK 18.0.1 или более поздняя.
  • Показы (доступно только для уведомлений на устройствах Android) – уведомление было показано на устройстве, когда приложение работало в фоновом режиме.
  • Открытия – пользователь открыл уведомление. Приводится только для уведомлений, полученных, когда приложение работает в фоновом режиме.

Эти данные доступны для всех сообщений с полезной нагрузкой уведомлений и всех помеченных сообщений с данными. Подробнее о ярлыках можно узнать в статье Как добавить ярлыки Аналитики в письма.

При просмотре отчетов о письмах можно задать диапазон дат для отображаемых данных и экспортировать их в CSV-файл. Вы также можете отфильтровать данные по следующим критериям:

  • Платформа (iOS или Android)
  • Приложение
  • Специальные ярлыки аналитики

Добавление ярлыков аналитики в письма

Ярлыки позволяют фильтровать статистику доставки по ярлыкам или их наборам, что очень удобно для анализа. Вы можете добавить ярлык к любому письму, отправленному с помощью API HTTP версии 1, задав поле fcmOptions.analyticsLabel в объекте message или в полях AndroidFcmOptions или ApnsFcmOptions, относящихся к определенной платформе.

Ярлыки Analytics – это текстовые строки в формате ^[a-zA-Z0-9-_.~%]{1,50}$. Ярлыки могут содержать буквы верхнего и нижнего регистра, цифры и следующие символы:

  • -
  • ~
  • %

Максимальная длина – 50 символов. Вы можете указать до 100 уникальных ярлыков в день. Сообщения с ярлыками, добавленными сверх этого лимита, не будут регистрироваться.

На вкладке Firebase Сообщения консоли Отчеты можно найти список всех существующих ярлыков и применить их по отдельности или в сочетании, чтобы отфильтровать отображаемую статистику.

Агрегированные данные о доставке с помощью FCM Data API

Firebase Cloud Messaging Data API позволяет получать информацию, которая помогает понять результаты запросов сообщений, предназначенных для приложений Android. API предоставляет агрегированные данные со всех устройств Android, на которых включен сбор данных в проекте. В том числе можно посмотреть процент сообщений, доставленных без задержки, а также количество сообщений, которые были задержаны или потеряны в транспортном уровне Android. Анализ этих данных позволяет выявлять общие тенденции в доставке сообщений и находить эффективные способы повысить эффективность запросов на отправку. Информацию о том, какие диапазоны дат доступны в отчетах, можно найти в разделе Сроки хранения агрегированных данных.

API предоставляет все данные, доступные для определенного приложения. Подробная информация приведена в справочной документации по API.

Как разбиты данные?

Данные о доставке разбиты по приложениям, датам и ярлыкам аналитики. Вызов API возвращает данные для каждой комбинации даты, приложения и ярлыка аналитики. Например, один объект JSON androidDeliveryData будет выглядеть так:

 {
  "appId": "1:23456789:android:a93a5mb1234efe56",
  "date": {
    "year": 2021,
    "month": 1,
    "day": 1
  },
  "analyticsLabel": "foo",
  "data": {
    "countMessagesAccepted": "314159",
    "messageOutcomePercents": {
      "delivered": 71,
      "pending": 15
    },
   "deliveryPerformancePercents": {
      "deliveredNoDelay": 45,
      "delayedDeviceOffline": 11
    }
  }

Как интерпретировать показатели

Данные о доставке показывают процент сообщений, соответствующих каждому из следующих показателей: Одно сообщение может соответствовать нескольким показателям. Из-за ограничений в способе сбора данных и уровне детализации, на котором мы агрегировали показатели, некоторые результаты сообщений не представлены в показателях, поэтому приведенные ниже проценты не будут в сумме равны 100 %.

Количество принятых сообщений

Единственное количество, включенное в набор данных, – это количество сообщений, которые были приняты FCM для доставки на устройства Android. Все проценты рассчитываются на основе этого значения. Обратите внимание, что в статистику не входят сообщения, отправленные пользователям, которые отключили сбор данных об использовании и диагностике на своих устройствах.

Процентное соотношение результатов сообщений

Поля, включенные в объект MessageOutcomePercents, содержат информацию о результатах запросов сообщений. Категории являются взаимоисключающими. Он может ответить на такие вопросы, как "Доставляются ли мои письма?" и "Почему письма не доставляются?".

Например, высокое значение поля droppedTooManyPendingMessages может указывать на то, что экземпляры приложения получают большое количество нескладываемых сообщений, превышающее ограничение FCM в 100 ожидающих сообщений. Чтобы избежать этого, убедитесь, что ваше приложение обрабатывает вызовы onDeletedMessages, и рассмотрите возможность отправки сворачиваемых сообщений. Аналогично, если процент для droppedDeviceInactive высок, это может означать, что на вашем сервере нужно обновить токены регистрации, удалив устаревшие и отменив подписку на темы. Рекомендации по этому вопросу можно найти в статье Как управлять токенами регистрации FCM.

Процент выполнения

Поля в объекте DeliveryPerformancePercents содержат информацию о доставленных письмах. Он может ответить на такие вопросы, как "Были ли мои письма задержаны?" и "Почему письма были задержаны?" Например, если значение delayedMessageThrottled будет высоким, это будет означать, что вы превышаете максимальное количество сообщений на устройство и вам следует снизить частоту отправки сообщений.

Процентные показатели в статистике сообщений

Этот объект содержит дополнительную информацию обо всех отправленных сообщениях. Поле priorityLowered содержит процент принятых писем, приоритет которых был снижен с HIGH до NORMAL. Если это значение высокое, попробуйте отправлять меньше сообщений с высоким приоритетом или всегда показывать уведомление при отправке такого сообщения. Подробнее о приоритете сообщений…

Чем эти данные отличаются от данных, экспортированных в BigQuery?

Экспорт в BigQuery позволяет получать отдельные журналы сообщений о принятии сообщений серверной частью FCM и доставке сообщений в SDK на устройстве (шаги 2 и 4 архитектуры FCM). Эти данные помогают убедиться, что отдельные письма были приняты и доставлены. Подробнее об экспорте данных в BigQuery…

В отличие от него, Firebase Cloud Messaging Data API предоставляет агрегированные данные о том, что происходит на транспортном уровне Android (или на шаге 3 архитектуры FCM). Эти данные позволяют отслеживать доставку сообщений из серверной части FCM в Android SDK. Особенно полезно отслеживать тенденции, связанные с причинами задержек или удаления писем при передаче.

В некоторых случаях два набора данных могут не совпадать из-за следующих факторов:

  • Агрегированные показатели основаны на выборке сообщений
  • Агрегированные показатели округляются
  • Мы не показываем показатели, которые не соответствуют пороговому значению конфиденциальности
  • Часть результатов сообщений отсутствует из-за оптимизации обработки большого объема трафика.

Ограничения API

Хронология агрегированных данных

API возвращает данные за последние семь дней, но с задержкой до пяти дней. Например, 20 января будут доступны данные за период с 9 по 15 января, но не за 16 января и более поздние даты. Кроме того, данные предоставляются по мере возможности. В случае сбоя в работе FCM будет восстановлена только дальнейшая передача данных. При более масштабных сбоях данные могут быть недоступны в течение недели или более.

Охват данных

Показатели, предоставляемые Firebase Cloud Messaging Data API, предназначены для того, чтобы вы могли отслеживать общие тенденции доставки сообщений. Однако они не охватывают все возможные сценарии показа сообщений. Ниже перечислены известные результаты, которые не отражаются в показателях.

Сообщения с истекшим сроком действия

Если время жизни (TTL) истекает после окончания указанной даты журнала, сообщение не будет считаться droppedTtlExpired на эту дату.

Сообщения на неактивных устройствах

Сообщения, отправленные на неактивные устройства, могут быть или не быть в наборе данных в зависимости от того, каким образом они были переданы. Это может привести к неточностям в полях droppedDeviceInactive и pending.

Сообщения для устройств с определенными настройками пользователя

Сообщения пользователей, которые отключили сбор данных об использовании и диагностической информации на своих устройствах, не будут учитываться в соответствии с их предпочтениями.

Округление и минимальные значения

FCM намеренно округляет и исключает данные, если их недостаточно.

Экспорт данных в BigQuery

Вы можете экспортировать данные о сообщениях в BigQuery для дальнейшего анализа. BigQuery позволяет анализировать данные с помощью SQL BigQuery, экспортировать их в другое облачное хранилище или использовать для собственных моделей машинного обучения. При экспорте в BigQuery включаются все доступные данные о сообщениях, независимо от типа сообщения и способа его отправки (через API или с помощью инструмента создания уведомлений).

Для сообщений, отправленных на устройства с указанными ниже минимальными версиями SDK, можно включить экспорт данных о доставке сообщений для вашего приложения:FCM

  • Android 20.1.0 или более поздней версии.
  • iOS 8.6.0 или более поздней версии.
  • Firebase Web SDK 12.14.0 или более поздней версии.

Чтобы начать работу, свяжите свой проект с BigQuery, используя консоль Firebase:

  1. Выберите действие. Вы можете:

    • Выберите DevOps & Engagement (DevOps и вовлечение) > Messaging (Обмен сообщениями) > the Notifications composer (конструктор уведомлений), а затем нажмите Access BigQuery (Открыть BigQuery) внизу страницы.

    • Нажмите на значок Настройки и перейдите на вкладку Интеграции. Затем в разделе BigQuery нажмите Связать.

      На этой странице представлены варианты экспорта FCM для всех приложений с поддержкой FCM в проекте.

  2. Следуйте инструкциям на экране, чтобы включить BigQuery.

Подробнее о том, как связать Firebase с BigQuery…

Если вы включите экспорт данных из BigQuery в Cloud Messaging:

  • Firebase экспортирует данные в BigQuery. Примечание. Первоначальное распространение данных для экспорта может занять до 48 часов.

  • После создания набора данных местоположение изменить нельзя, но можно скопировать набор данных в другое место или вручную переместить (воссоздать) набор данных в другое местоположение. Подробнее о том, как изменить местоположение набора данных…

  • Firebase регулярно синхронизирует данные из вашего проекта Firebase с BigQuery. Ежедневные операции экспорта начинаются в 4:00 по тихоокеанскому времени и обычно завершаются в течение 24 часов.

  • По умолчанию все приложения в вашем проекте связаны с BigQuery, и все приложения, которые вы добавите в проект позже, будут автоматически связаны с BigQuery. Но вы можете указать, из каких приложений следует экспортировать данные.

Чтобы отключить экспорт BigQuery, отмените связь с проектом в консоли Firebase.

Как включить экспорт данных о доставке писем

iOS+

На устройствах iOS с FCM SDK 8.6.0 или более поздней версии можно включить экспорт данных о доставке сообщений приложения. FCM поддерживает экспорт данных для уведомлений об оповещениях и фоновых уведомлений. По умолчанию экспорт данных отключен на уровне приложения. Если включить его на уровне экземпляра приложения, вы сможете запрашивать у конечных пользователей разрешение на анализ данных о доставке сообщений (рекомендуется). Если заданы оба значения, значение на уровне экземпляра приложения переопределяет значение на уровне приложения.

Прежде чем включить эти параметры, необходимо создать связь FCM с BigQuery для своего проекта, как описано в разделе Экспорт данных в BigQuery.

Как включить экспорт данных о доставке для уведомлений об оповещениях

Поскольку расширения приложений для сервиса уведомлений могут запускаться только уведомлениями об оповещениях, вам необходимо добавить в приложение расширение сервиса уведомлений и вызвать этот API внутри расширения сервиса, чтобы включить отслеживание сообщений. Подробнее о том, как изменить контент в новых уведомлениях…

Для каждого полученного уведомления необходимо выполнить следующий вызов:

Swift

// For alert notifications, call the API inside the service extension:
class NotificationService: UNNotificationServiceExtension {
  override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
    Messaging.serviceExtension().exportDeliveryMetrics(withMessageInfo:request.content.userInfo)
  }
}

Objective-C

// For alert notifications, call the API inside the service extension:
@implementation NotificationService
- (void)didReceiveNotificationRequest:(UNNotificationRequest *)request
                   withContentHandler:(void (^)(UNNotificationContent *_Nonnull))contentHandler {
  [[FIRMessaging extensionHelper] exportDeliveryMetricsToBigQueryWithMessageInfo:request.content.userInfo];
}
@end

Если вы создаете запросы на отправку с помощью HTTP v1 API, убедитесь, что в объекте полезной нагрузки указано значение `mutable-content = 1`.

Как включить экспорт данных о доставке для фоновых уведомлений

Для фоновых сообщений, полученных, когда приложение находится на переднем или заднем плане, можно вызвать API экспорта данных внутри обработчика сообщений данных основного приложения. Этот вызов необходимо выполнять для каждого полученного уведомления:

Swift

// For background notifications, call the API inside the
// UIApplicationDelegate or NSApplicationDelegate method:
func application(_ application: UIApplication,
didReceiveRemoteNotification userInfo: [AnyHashable : Any]) {
  Messaging.serviceExtension().exportDeliveryMetricsToBigQuery(withMessageInfo:userInfo)
}

Objective-C

// For background notifications, call the API inside the
// UIApplicationDelegate or NSApplicationDelegate method:
@implementation AppDelegate
- (void)application:(UIApplication *)application
    didReceiveRemoteNotification:(NSDictionary *)userInfo
          fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
  [[FIRMessaging extensionHelper] exportDeliveryMetricsToBigQueryWithMessageInfo:userInfo];
}
@end

Android

На устройствах Android с SDK FCM версии 20.1.0 или более поздней можно включить экспорт данных о доставке сообщений из приложения. По умолчанию экспорт данных отключен на уровне приложения. Если включить его на уровне экземпляра приложения, вы сможете запрашивать у конечных пользователей разрешение на анализ данных о доставке сообщений (рекомендуется). Если заданы оба значения, значение на уровне экземпляра приложения переопределяет значение на уровне приложения.

Прежде чем включить эти параметры, необходимо создать связь FCM-BiqQuery для проекта, как описано в разделе Экспорт данных в BigQuery.

Как включить экспорт данных о доставке для экземпляров приложений

В большинстве случаев мы рекомендуем включить экспорт данных о доставке сообщений только на уровне экземпляра приложения и оставить его отключенным на уровне приложения.

FirebaseMessaging.getInstance().setDeliveryMetricsExportToBigQuery(true);

Как включить экспорт данных о доставке для приложения

Если вы хотите включить экспорт на уровне приложения, не вызывайте метод setDeliveryMetricsExportToBigQuery и добавьте следующее свойство в объект приложения в манифесте приложения:

<application>
  <meta-data android:name="delivery_metrics_exported_to_big_query_enabled"
      android:value="true" />
</application>

Веб-приложение

Экспорт данных о доставке возможен с помощью FCM SDK для сайтов версии 12.14.0 или более поздней. По умолчанию экспорт данных отключен на уровне приложения. Если включить его на уровне экземпляра приложения, вы сможете запрашивать у конечных пользователей разрешение на анализ данных о доставке сообщений (рекомендуется). Если заданы оба значения, значение на уровне экземпляра приложения переопределяет значение на уровне приложения. Когда конечный пользователь дает согласие или отказывается от сбора данных, приложение должно установить экспериментальный флаг включения или отключения для каждого экземпляра приложения, как показано ниже.

// userConsent holds the decision of the user to give big query export consent.
const userConsent = ...;

const messaging = getMessagingInSw(app);

experimentalSetDeliveryMetricsExportedToBigQueryEnabled(messaging, userConsent);

Какие данные экспортируются в BigQuery?

Обратите внимание, что таргетинг на устаревшие токены или неактивные регистрации может привести к завышению некоторых из этих показателей.

Схема экспортируемой таблицы:

_PARTITIONTIME ВРЕМЕННЫЕ МЕТКИ Этот псевдостолбец содержит временную метку начала дня (в UTC), в который были загружены данные. Для раздела YYYYMMDD этот псевдостолбец содержит значение TIMESTAMP('YYYY-MM-DD').
event_timestamp ВРЕМЕННЫЕ МЕТКИ Временная метка события, записанная сервером.
project_number INTEGER Номер проекта, из которого было отправлено письмо.
message_id STRING Идентификатор сообщения позволяет определить письмо. Идентификатор сообщения генерируется на основе идентификатора приложения и временной метки, поэтому в некоторых случаях он может быть не уникальным в глобальном масштабе.
instance_id STRING Уникальный идентификатор приложения, в которое отправлено сообщение (если доступно). Это может быть идентификатор экземпляра или идентификатор установки Firebase.
message_type STRING Тип сообщения. Может быть уведомлением или сообщением с данными. Тема используется для идентификации исходного сообщения для отправки темы или кампании. Последующие сообщения являются уведомлениями или сообщениями с данными.
sdk_platform STRING Платформа приложения получателя
app_name STRING Название пакета для приложений Android или идентификатор пакета для приложений iOS.
collapse_key STRING Ключ свертывания определяет группу сообщений, которые можно свернуть. Если устройство не подключено, в очередь на доставку помещается только последнее сообщение с определенным ключом collapse_key.
прием в приоритетном порядке INTEGER Приоритет сообщения. 5 – нормальный приоритет, 10 – высокий.
ttl INTEGER Этот параметр определяет, как долго (в секундах) сообщение должно храниться в хранилище FCM, если устройство находится в офлайн-режиме.
тема STRING Название темы, в которую было отправлено сообщение (если применимо).
bulk_id INTEGER Идентификатор массовой рассылки позволяет определить группу связанных сообщений, например отправленных в рамках одной рассылки на определенную тему.
event STRING Тип события. Возможные значения:
  • MESSAGE_ACCEPTED – сообщение получено сервером FCM и запрос действителен;
  • MESSAGE_DELIVERED – сообщение доставлено в SDK FCM приложения на устройстве. По умолчанию это поле не распространяется. Чтобы включить ее, следуйте инструкциям в setDeliveryMetricsExportToBigQuery(boolean).
  • MISSING_REGISTRATIONS – запрос был отклонен из-за отсутствия регистрации.
  • UNAUTHORIZED_REGISTRATION: письмо было отклонено, поскольку отправитель не имеет права отправлять письма на адрес регистрации;
  • MESSAGE_RECEIVED_INTERNAL_ERROR – при обработке запроса на переписку произошла неизвестная ошибка;
  • MISMATCH_SENDER_ID – запрос на отправку сообщения был отклонен из-за несоответствия между идентификатором отправителя, отправляющего сообщение, и идентификатором, заявленным для конечной точки.
  • QUOTA_EXCEEDED – запрос на отправку сообщения был отклонен из-за недостаточной квоты.
  • INVALID_REGISTRATION – запрос на отправку сообщения был отклонен из-за недопустимой регистрации.
  • INVALID_PACKAGE_NAME – запрос на отправку сообщения был отклонен из-за недопустимого названия пакета.
  • INVALID_APNS_CREDENTIAL – запрос на отправку сообщения был отклонен из-за недействительного сертификата APNS;
  • INVALID_PARAMETERS – запрос на отправку сообщения был отклонен из-за недопустимых параметров.
  • PAYLOAD_TOO_LARGE: запрос на отправку письма был отклонен, поскольку полезная нагрузка превышает допустимый размер;
  • AUTHENTICATION_ERROR – запрос на отправку сообщения был отклонен из-за ошибки аутентификации (проверьте ключ API, использованный для отправки сообщения);
  • INVALID_TTL: запрос на отправку сообщения был отклонен из-за недопустимого значения TTL.
analytics_label STRING С помощью HTTP v1 API можно задать ярлык аналитики при отправке сообщения, чтобы пометить его для целей анализа.

Что можно делать с экспортированными данными

В следующих разделах приведены примеры запросов, которые можно выполнять в BigQuery к экспортированным данным FCM.

Как подсчитать отправленные сообщения по приложениям

SELECT app_name, COUNT(1)
FROM `project ID.firebase_messaging.data`
WHERE
  _PARTITIONTIME = TIMESTAMP('date as YYYY-MM-DD')
  AND event = 'MESSAGE_ACCEPTED'
  AND message_id != ''
GROUP BY 1;

Количество уникальных экземпляров приложений, на которые нацелены сообщения

SELECT COUNT(DISTINCT instance_id)
FROM `project ID.firebase_messaging.data`
WHERE
  _PARTITIONTIME = TIMESTAMP('date as YYYY-MM-DD')
  AND event = 'MESSAGE_ACCEPTED';

Количество отправленных уведомлений

SELECT COUNT(1)
FROM `project ID.firebase_messaging.data`
WHERE
  _PARTITIONTIME = TIMESTAMP('date as YYYY-MM-DD')
  AND event = 'MESSAGE_ACCEPTED'
  AND message_type = 'DISPLAY_NOTIFICATION';

Количество отправленных сообщений с данными

SELECT COUNT(1)
FROM `project ID.firebase_messaging.data`
WHERE
  _PARTITIONTIME = TIMESTAMP('date as YYYY-MM-DD')
  AND event = 'MESSAGE_ACCEPTED'
  AND message_type = 'DATA_MESSAGE';

Как подсчитать количество сообщений, отправленных в тему или кампанию

SELECT COUNT(1)
FROM `project ID.firebase_messaging.data`
WHERE
  _PARTITIONTIME = TIMESTAMP('date as YYYY-MM-DD')
  AND event = 'MESSAGE_ACCEPTED'
  AND bulk_id = your bulk id AND message_id != '';

Чтобы отслеживать события для сообщения, отправленного в определенную тему, измените запрос, заменив AND message_id != '' на AND message_id = <your message id>;.

Как рассчитать продолжительность распространения для определенной темы или кампании

Время начала разветвления – это время получения исходного запроса, а время окончания – это время создания последнего отдельного сообщения, предназначенного для одного экземпляра.

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 ID.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 ID.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;

Процент доставленных писем

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 ID.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 ID.firebase_messaging.data`
    WHERE
      _PARTITIONTIME = TIMESTAMP('date as YYYY-MM-DD')
      AND (event = 'MESSAGE_DELIVERED'
      AND message_id
      IN (
        SELECT message_id FROM `project ID.firebase_messaging.data`
        WHERE
          _PARTITIONTIME = TIMESTAMP('date as YYYY-MM-DD')
          AND event = 'MESSAGE_ACCEPTED'
        GROUP BY 1
      )
  ) delivered;

Отслеживание всех событий для определенного идентификатора сообщения и идентификатора экземпляра

SELECT *
FROM `project ID.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;

Как рассчитать задержку для определенного идентификатора сообщения и идентификатора экземпляра

SELECT
  TIMESTAMP_DIFF(
    MAX(delivered_time), MIN(accepted_time), MILLISECOND
  ) AS latency_ms
FROM (
    SELECT event_timestamp AS accepted_time
    FROM `project ID.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 ID.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'
  ) delivered;