Aby rozwiązać problemy z nieudanym dostarczaniem wiadomości, skorzystaj z narzędzia do rozwiązywania problemów z FCM i przeczytaj ten artykuł na blogu, aby poznać różne przyczyny, dla których możesz nie widzieć wiadomości. Możesz też otworzyć panel stanu FCM, aby sprawdzić, czy występują przerwy w działaniu usługi FCM.
FCM udostępnia też 3 zestawy narzędzi, które pomagają uzyskać ogólny wgląd w skuteczność i strategię przesyłania wiadomości:
- Firebase raportów dostarczania wiadomości w konsoli,
- Zagregowane dane o wyświetlaniu pakietu SDK na Androida z interfejsu API danychFirebase Cloud Messaging
- Kompleksowy eksport danych do Google BigQuery
Eksport danych do BigQuery i karta Raporty w FirebasekonsoliGoogle Analytics wymagają do działania. Jeśli Google Analytics nie jest włączona w Twoim projekcie, możesz ją skonfigurować na karcie Integracje w ustawieniach projektu Firebase. Dane zbiorcze o dostawie nie wymagają Google Analytics do działania.
Pamiętaj, że raportowanie wielu statystyk na tej stronie może być opóźnione nawet o 24 godziny ze względu na przetwarzanie danych analitycznych w pakietach.
Raporty dostarczania wiadomości
Na karcie Raporty w konsoli Firebase możesz wyświetlać te dane dotyczące wiadomości wysyłanych do pakietów SDK FCM na platformach Android i Apple, w tym wiadomości wysyłanych za pomocą narzędzia do tworzenia powiadomień i interfejsów FCM API:
- Wysłano – wiadomość z danymi lub powiadomienie zostało umieszczone w kolejce do dostarczenia lub zostało prawidłowo przekazane do usługi innej firmy, np. APNs, w celu dostarczenia. Pamiętaj, że statystyki wysyłania mogą być opóźnione o kilka godzin. Więcej informacji znajdziesz w sekcji Okres ważności wiadomości.
- Odebrano (dostępne tylko na urządzeniach z Androidem) – wiadomość z danymi lub powiadomienie zostało odebrane przez aplikację. Te dane są dostępne, gdy na urządzeniu z Androidem jest zainstalowany FCMpakiet SDK w wersji 18.0.1 lub nowszej.
- Wyświetlenia (dostępne tylko w przypadku powiadomień na urządzeniach z Androidem) – powiadomienie zostało wyświetlone na urządzeniu, gdy aplikacja działała w tle.
- Otwarcie – użytkownik otworzył wiadomość z powiadomieniem. Raportowane tylko w przypadku powiadomień otrzymywanych, gdy aplikacja działa w tle.
Te dane są dostępne w przypadku wszystkich wiadomości z ładunkiem powiadomienia i wszystkich oznaczonych wiadomości z danymi. Więcej informacji o etykietach znajdziesz w artykule Dodawanie etykiet analitycznych do wiadomości.
Podczas wyświetlania raportów o wiadomościach możesz ustawić zakres dat dla wyświetlanych danych, a także wyeksportować je do pliku CSV. Możesz też filtrować według tych kryteriów:
- Platforma (iOS lub Android)
- Aplikacja
- Etykiety własne w Analytics
Dodawanie etykiet Analytics do wiadomości
Oznaczanie wiadomości etykietami jest bardzo przydatne w przypadku analizy niestandardowej, ponieważ umożliwia filtrowanie statystyk dostarczania według etykiet lub zestawów etykiet. Do każdej wiadomości wysłanej za pomocą interfejsu HTTP v1 API możesz dodać etykietę, ustawiając pole fcmOptions.analyticsLabel
w obiekcie message lub w polach AndroidFcmOptions
lub ApnsFcmOptions
specyficznych dla platformy.
Etykiety Analytics to ciągi tekstowe w formacie ^[a-zA-Z0-9-_.~%]{1,50}$
.
Etykiety mogą zawierać małe i wielkie litery, cyfry oraz te symbole:
-
~
%
Maksymalna długość to 50 znaków. Możesz określić maksymalnie 100 unikalnych etykiet dziennie. Wiadomości z etykietami dodanymi po przekroczeniu tego limitu nie są uwzględniane w raportach.
Na karcie Firebasekomunikatów w konsoliRaporty możesz wyszukać listę wszystkich istniejących etykiet i zastosować je pojedynczo lub w kombinacji, aby filtrować wyświetlane statystyki.
zagregowane dane o dostarczaniu za pomocą interfejsu FCM Data API,
Interfejs Firebase Cloud Messaging Data API umożliwia pobieranie informacji, które mogą pomóc w zrozumieniu wyników żądań wysyłania wiadomości kierowanych do aplikacji na Androida. Interfejs API udostępnia dane zbiorcze ze wszystkich urządzeń z Androidem, na których w projekcie włączono zbieranie danych. Obejmuje to szczegółowe informacje o procentowym udziale wiadomości dostarczonych bez opóźnień, a także o liczbie wiadomości opóźnionych lub utraconych w warstwie transportowej Androida. Ocena tych danych może ujawnić ogólne trendy w dostarczaniu wiadomości i pomóc Ci znaleźć skuteczne sposoby na zwiększenie skuteczności wysyłanych próśb. Informacje o zakresach dat dostępnych w raportach znajdziesz w artykule Oś czasu danych zbiorczych.
Interfejs API udostępnia wszystkie dane dostępne w przypadku danej aplikacji. Zapoznaj się z dokumentacją interfejsu API.
Jak dane są podzielone?
Dane o dostarczaniu są podzielone według aplikacji, daty i etykiety Analytics.
Wywołanie interfejsu API zwróci dane dla każdej kombinacji daty, aplikacji i etykiety analitycznej. Na przykład pojedynczy obiekt JSON androidDeliveryData
wyglądałby tak:
{
"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
}
}
Interpretowanie danych
Dane o dostarczaniu zawierają odsetek wiadomości, które spełniają poszczególne z tych kryteriów: Może się zdarzyć, że jedna wiadomość pasuje do kilku rodzajów danych. Ze względu na ograniczenia w sposobie zbierania danych i poziom szczegółowości, na którym agregujemy dane, niektóre wyniki wiadomości nie są w ogóle uwzględniane w danych, więc podane poniżej wartości procentowe nie sumują się do 100%.
Zliczanie zaakceptowanych wiadomości
Jedyną liczbą uwzględnioną w zbiorze danych jest liczba wiadomości, które zostały zaakceptowane przez FCM do dostarczenia na urządzenia z Androidem. Wszystkie wartości procentowe używają tej wartości jako mianownika. Pamiętaj, że ta liczba nie obejmuje wiadomości kierowanych do użytkowników, którzy wyłączyli zbieranie informacji o użytkowaniu i danych diagnostycznych na swoich urządzeniach.
Odsetki wyników wiadomości
Pola zawarte w obiekcie MessageOutcomePercents
zawierają informacje o wynikach żądań wiadomości. Wszystkie kategorie wzajemnie się wykluczają. Może odpowiadać na pytania takie jak „Czy moje wiadomości są dostarczane?” i „Co powoduje utratę wiadomości?”.
Na przykład wysoka wartość w polu droppedTooManyPendingMessages
może sygnalizować, że instancje aplikacji otrzymują dużą liczbę wiadomości, których nie można zwinąć, przekraczającą limit 100 oczekujących wiadomości w przypadku parametru FCM.
Aby temu zapobiec, zadbaj o to, aby aplikacja obsługiwała wywołania funkcji onDeletedMessages
i rozważ wysyłanie zwijalnych wiadomości. Podobnie wysokie odsetki w przypadku droppedDeviceInactive
mogą sygnalizować konieczność zaktualizowania tokenów rejestracji na serwerze, usunięcia nieaktualnych tokenów i wyrejestrowania ich z tematów. Więcej informacji o sprawdzonych metodach w tym zakresie znajdziesz w artykule Zarządzanie FCM tokenami rejestracji.
Procenty skuteczności dostarczania
Pola w obiekcie DeliveryPerformancePercents
zawierają informacje o wiadomościach, które zostały dostarczone. Może odpowiadać na pytania takie jak „Czy moje wiadomości są opóźnione?” i „Dlaczego wiadomości są opóźnione?”. Na przykład wysoka wartość parametru
delayedMessageThrottled
wyraźnie wskazuje, że przekraczasz maksymalne limity na urządzenie
i powinieneś(-aś) dostosować częstotliwość wysyłania wiadomości.
Procentowe statystyki wiadomości
Ten obiekt zawiera dodatkowe informacje o wszystkich wysłanych wiadomościach. Pole
priorityLowered
wyraża odsetek zaakceptowanych wiadomości, których priorytet został obniżony z HIGH
na NORMAL
. Jeśli ta wartość jest wysoka, spróbuj wysyłać mniej wiadomości o wysokim priorytecie lub zawsze wyświetlaj powiadomienie, gdy wysyłana jest wiadomość o wysokim priorytecie. Więcej informacji znajdziesz w dokumentacji dotyczącej priorytetu wiadomości
Czym te dane różnią się od danych eksportowanych do BigQuery?
Eksport BigQuery udostępnia dzienniki poszczególnych wiadomości dotyczące akceptowania wiadomości przez backend FCM i dostarczania wiadomości w pakiecie SDK na urządzeniu (kroki 2 i 4 architektury FCM). Te dane są przydatne do sprawdzania, czy poszczególne wiadomości zostały zaakceptowane i dostarczone. Więcej informacji o eksportowaniu danych do BigQuery znajdziesz w następnej sekcji.
Natomiast interfejs Firebase Cloud Messaging Data API udostępnia zagregowane informacje o tym, co dzieje się konkretnie w warstwie transportowej Androida (czyli na etapie 3 architektury FCM). Te dane dostarczają informacji o dostarczaniu wiadomości z backendów FCM do pakietu SDK na Androida. Jest to szczególnie przydatne do wyświetlania trendów dotyczących przyczyn opóźnień lub odrzucenia wiadomości podczas przesyłania.
W niektórych przypadkach te 2 zbiory danych mogą się nie zgadzać dokładnie z tych powodów:
- Dane zbiorcze obejmują tylko próbkę wszystkich wiadomości.
- Zagregrowane dane są zaokrąglane.
- Nie wyświetlamy danych poniżej progu prywatności.
- Brak części wyników wiadomości z powodu optymalizacji sposobu zarządzania dużym ruchem.
Ograniczenia interfejsu API
Oś czasu danych zbiorczych
Interfejs API zwróci dane historyczne z 7 dni, ale dane zwrócone przez ten interfejs API będą opóźnione o maksymalnie 5 dni. Na przykład 20 stycznia dostępne będą dane z okresu 9–15 stycznia, ale nie z okresu od 16 stycznia. Dane są też dostarczane z możliwie największą dokładnością. W przypadku awarii danych FCM podejmie działania w celu naprawienia problemu, ale nie uzupełni danych wstecznie po jego rozwiązaniu. W przypadku większych awarii dane mogą być niedostępne przez tydzień lub dłużej.
Zakres danych
Dane udostępniane przez interfejs Firebase Cloud Messaging Data API mają na celu dostarczanie informacji o ogólnych trendach w zakresie dostarczania wiadomości. Nie zapewniają one jednak 100% pokrycia wszystkich scenariuszy wyświetlania wiadomości. Te scenariusze to znane wyniki, które nie są odzwierciedlone w danych.
Wygasłe wiadomości
Jeśli czas TTL wygaśnie po zakończeniu danego dnia w logu, wiadomość nie zostanie uwzględniona jako droppedTtlExpired
w tym dniu.
Wiadomości na nieaktywne urządzenia
Wiadomości wysyłane na nieaktywne urządzenia mogą, ale nie muszą pojawiać się w zbiorze danych w zależności od ścieżki danych, którą pokonują. Może to prowadzić do błędnego zliczania w polach droppedDeviceInactive
i pending
.
Wiadomości do urządzeń z określonymi ustawieniami użytkownika
W naszych statystykach nie uwzględniamy wiadomości użytkowników, którzy wyłączyli zbieranie informacji o użytkowaniu i diagnostyce na swoich urządzeniach. Jest to zgodne z ich preferencjami.
Zaokrąglanie i wartości minimalne
FCM celowo zaokrągla i wyklucza wartości, w przypadku których wolumeny nie są wystarczająco duże.
Eksportowanie danych z BigQuery
Dane wiadomości możesz eksportować do BigQuery w celu dalszej analizy. BigQuery umożliwia analizowanie danych za pomocą BigQuery SQL, eksportowanie ich do innego dostawcy usług w chmurze lub używanie ich w modelach ML dostosowanych do Twoich potrzeb. Eksport do BigQuery obejmuje wszystkie dostępne dane wiadomości, niezależnie od ich typu i sposobu wysyłania (przez interfejs API lub kompozytor powiadomień).
W przypadku wiadomości wysyłanych na urządzenia z tymi FCMminimalnymi wersjami pakietu SDKFCM możesz dodatkowo włączyć eksportowanie danych o dostarczaniu wiadomości w swojej aplikacji:
- Androida w wersji 20.1.0 lub nowszej.
- iOS 8.6.0 lub nowszy
- Firebase Web SDK w wersji 9.0.0 lub nowszej
Poniżej znajdziesz szczegółowe informacje o włączaniu eksportowania danych na Androidzie i iOS.
Aby rozpocząć, połącz projekt z BigQuery:
Wybierz jedną z tych opcji:
Otwórz edytor powiadomień, a następnie u dołu strony kliknij Dostęp do BigQuery.
Na stronie Integracje w konsoli Firebase kliknij Połącz na karcie BigQuery.
Na tej stronie wyświetlane są FCM opcje eksportu dla wszystkich aplikacji w projekcie, w których włączono FCM.
Aby włączyć BigQuery, postępuj zgodnie z instrukcjami wyświetlanymi na ekranie.
Więcej informacji znajdziesz w artykule Łączenie Firebase z BigQuery.
Gdy włączysz eksportowanie BigQuery w przypadku Cloud Messaging:
Firebase eksportuje Twoje dane do BigQuery. Pamiętaj, że początkowe rozpowszechnianie danych na potrzeby eksportu może potrwać do 48 godzin.
- Możesz ręcznie zaplanować uzupełnianie danych z ostatnich 30 dni.
Gdy zbiór danych zostanie utworzony, jego lokalizacji nie można już zmienić. Możesz natomiast skopiować zbiór danych do innej lokalizacji lub go ręcznie przenieść przez ponowne utworzenie tego zbioru w innej lokalizacji. Więcej informacji znajdziesz w artykule Zmiana lokalizacji zbioru danych.
Firebase konfiguruje regularne synchronizacje danych z projektu Firebase z BigQuery. Codzienne operacje eksportu rozpoczynają się o 4:00 czasu pacyficznego i zwykle kończą w ciągu 24 godzin.
Domyślnie wszystkie aplikacje w projekcie są połączone z BigQuery. Wszystkie aplikacje, które dodasz do projektu później, także zostaną automatycznie połączone z BigQuery. Możesz określić, które aplikacje mają wysyłać dane.
Aby dezaktywować eksportowanie BigQuery, odłącz projekt w konsoli Firebase.
Włączanie eksportowania danych o dostarczaniu wiadomości
Na urządzeniach z Androidem z pakietem SDK FCM w wersji 20.1.0 lub nowszej można włączyć eksportowanie danych o dostarczaniu wiadomości z aplikacji. Eksport danych jest domyślnie wyłączony na poziomie aplikacji. Programowe włączenie tej funkcji na poziomie instancji aplikacji umożliwia proszenie użytkowników o zezwolenie na analizowanie danych o dostarczaniu wiadomości (zalecane). Jeśli oba te ustawienia są skonfigurowane, wartość na poziomie instancji aplikacji zastępuje wartość na poziomie aplikacji.
Zanim włączysz te opcje, musisz najpierw utworzyć FCMpołączenie z BigQuery dla swojego projektu zgodnie z opisem w artykule Eksport danych do BigQuery.
Włączanie eksportu danych o dostarczaniu w przypadku instancji aplikacji
W większości przypadków zalecamy włączenie eksportowania danych o dostarczaniu wiadomości tylko na poziomie instancji aplikacji i pozostawienie go wyłączonego na poziomie aplikacji.
FirebaseMessaging.getInstance().setDeliveryMetricsExportToBigQuery(true)
Włączanie eksportu danych o dostarczaniu w przypadku aplikacji
Jeśli wolisz włączyć eksport na poziomie aplikacji, nie wywołuj metody
setDeliveryMetricsExportToBigQuery
i dodaj tę właściwość do obiektu aplikacji w pliku manifestu aplikacji:
<application>
<meta-data android:name="delivery_metrics_exported_to_big_query_enabled"
android:value="true" />
</application>
Jakie dane są eksportowane do BigQuery?
Pamiętaj, że kierowanie na nieaktualne tokeny lub nieaktywne rejestracje może zawyżać niektóre z tych statystyk.
Schemat wyeksportowanej tabeli jest następujący:
_PARTITIONTIME | SYGNATURA CZASOWA | Ta pseudokolumna zawiera sygnaturę czasową początku dnia (w czasie UTC), w którym wczytano dane. W przypadku partycji RRRRMMDD ta pseudokolumna zawiera wartość TIMESTAMP('RRRR-MM-DD'). |
event_timestamp | SYGNATURA CZASOWA | Sygnatura czasowa zdarzenia zarejestrowana przez serwer |
project_number | LICZBA CAŁKOWITA | Numer projektu identyfikuje projekt, z którego została wysłana wiadomość. |
message_id | CIĄG ZNAKÓW | Identyfikator wiadomości określa wiadomość. Identyfikator wiadomości jest generowany na podstawie identyfikatora aplikacji i sygnatury czasowej, więc w niektórych przypadkach może nie być globalnie unikalny. |
instance_id | CIĄG ZNAKÓW | Unikalny identyfikator aplikacji, do której wysyłana jest wiadomość (jeśli jest dostępny). Może to być identyfikator instancji lub identyfikator instalacji Firebase. |
message_type | CIĄG ZNAKÓW | Typ wiadomości. Może to być powiadomienie lub wiadomość z danymi. Temat służy do identyfikowania pierwotnej wiadomości wysłanej w ramach tematu lub kampanii. Kolejne wiadomości to powiadomienia lub wiadomości zawierające dane. |
sdk_platform | CIĄG ZNAKÓW | Platforma aplikacji odbiorcy |
app_name | CIĄG ZNAKÓW | Nazwa pakietu w przypadku aplikacji na Androida lub identyfikator pakietu w przypadku aplikacji na iOS. |
collapse_key | CIĄG ZNAKÓW | Klucz zwijania identyfikuje grupę wiadomości, które można zwinąć. Gdy urządzenie nie jest połączone, w kolejce do dostarczenia jest tylko ostatni komunikat z danym kluczem zwijania. |
rekrutacja priorytetowa | LICZBA CAŁKOWITA | Priorytet wiadomości. Prawidłowe wartości to „normal” i „high”. W systemie iOS odpowiadają one priorytetom APNs 5 i 10. |
ttl | LICZBA CAŁKOWITA | Ten parametr określa, jak długo (w sekundach) wiadomość powinna być przechowywana w pamięci FCM, jeśli urządzenie jest offline. |
temat | CIĄG ZNAKÓW | Nazwa tematu, do którego wysłano wiadomość (w stosownych przypadkach). |
bulk_id | LICZBA CAŁKOWITA | Identyfikator zbiorczy określa grupę powiązanych wiadomości, np. konkretną wysyłkę do tematu. |
event | CIĄG ZNAKÓW | Typ zdarzenia.
Możliwe wartości:
|
analytics_label | CIĄG ZNAKÓW | Za pomocą interfejsu HTTP API w wersji 1 możesz ustawić etykietę analityczną podczas wysyłania wiadomości, aby oznaczyć ją na potrzeby analizy. |
Co można zrobić z wyeksportowanymi danymi?
W sekcjach poniżej znajdziesz przykłady zapytań, które możesz uruchamiać w BigQuery na wyeksportowanych danych FCM.
Liczba wysłanych wiadomości według aplikacji
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;
Zliczanie unikalnych instancji aplikacji, do których kierowane są wiadomości
SELECT COUNT(DISTINCT instance_id)
FROM `project ID.firebase_messaging.data`
WHERE
_PARTITIONTIME = TIMESTAMP('date as YYYY-MM-DD')
AND event = 'MESSAGE_ACCEPTED';
Liczba wysłanych powiadomień
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';
Zliczanie wysłanych wiadomości zawierających dane
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';
Zliczanie wiadomości wysłanych do tematu lub kampanii
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 != '';
Aby śledzić zdarzenia dotyczące wiadomości wysłanej do konkretnego tematu, zmień to zapytanie, zastępując AND message_id != ''
ciągiem AND message_id = <your message id>;
.
Obliczanie czasu trwania rozsyłania dla danego tematu lub kampanii
Czas rozpoczęcia rozsyłania to moment otrzymania pierwotnego żądania, a czas zakończenia to moment utworzenia ostatniej pojedynczej wiadomości kierowanej na jedno wystąpienie.
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;
Obliczanie odsetka dostarczonych wiadomości
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;
Śledzenie wszystkich zdarzeń dotyczących danego identyfikatora wiadomości i identyfikatora instancji
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;
Obliczanie opóźnienia dla danego identyfikatora wiadomości i identyfikatora instancji
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;