Noções básicas sobre o envio de mensagens

Com o FCM, você tem três conjuntos de ferramentas para acessar informações sobre a entrega de mensagens.

  • Relatórios de entrega de mensagens do Console do Firebase
  • Métricas agregadas de exibição do SDK do Android da API Data do Firebase Cloud Messaging
  • Exportação de dados abrangente para o Google BigQuery

Todas as ferramentas de relatórios descritas nesta página exigem o Google Analytics para funcionar. Se o Google Analytics não estiver ativado no seu projeto, você poderá configurá-lo na guia integrações das configurações do projeto do Firebase.

A geração de relatórios de muitas das estatísticas nesta página está sujeita a atrasos de até 24 horas devido ao agrupamento de dados de análise.

Relatórios de entrega de mensagens

Na guia Relatórios do Console do Firebase, é possível visualizar os seguintes dados sobre mensagens enviadas para SDKs do FCM da plataforma Android ou Apple, incluindo as enviadas pelo Editor do Notificações e pelas APIs do FCM:

  • Envios: a mensagem de dados ou de notificação foi enfileirada para a entrega ou foi corretamente transmitida a um serviço de terceiros, como APNs. Para mais informações, consulte ciclo de vida de uma mensagem.
  • Recebidas (disponível apenas em dispositivos Android): a mensagem de dados ou de notificação foi recebida pelo app. Os dados estarão disponíveis se o dispositivo Android receptor tiver a versão 18.0.1 ou mais recente do SDK do FCM instalada.
  • Impressões (disponível apenas para mensagens de notificação em dispositivos Android): a notificação de exibição foi mostrada no dispositivo enquanto o aplicativo estava em segundo plano.
  • Aberturas: o usuário abriu a mensagem de notificação. Informado apenas para notificações recebidas enquanto o aplicativo estava em segundo plano.

Esses dados estão disponíveis para todas as mensagens com um payload de notificação e todas as mensagens de dados com rótulo. Para saber mais sobre rótulos, consulte Como adicionar rótulos de análise às mensagens.

Ao visualizar relatórios de mensagens, é possível definir um período para os dados exibidos, com a opção de exportar para um arquivo CSV. Também é possível filtrar por estes critérios:

  • Plataforma (iOS ou Android)
  • App
  • Rótulos de análise personalizados

Como adicionar rótulos de análise às mensagens

A rotulação de mensagens é muito útil para a realização de análises personalizadas. Com ela, é possível filtrar estatísticas de entrega por rótulos ou conjuntos de rótulos. Para adicionar um rótulo a qualquer mensagem enviada usando a API HTTP v1, basta definir o campo fcmOptions.analyticsLabel no objeto mensagem ou nos campos AndroidFcmOptions ou ApnsFcmOptions específicos da plataforma.

Os rótulos de análise são strings de texto no formato ^[a-zA-Z0-9-_.~%]{1,50}$. Os rótulos podem incluir letras maiúsculas e minúsculas, números e os seguintes símbolos:

  • -
  • ~
  • %

O comprimento máximo é de 50 caracteres. Você pode especificar até 100 rótulos exclusivos por dia. As mensagens que receberem rótulos além desse limite não serão informadas.

Na guia Relatórios de mensagens do Console do Firebase, é possível pesquisar uma lista de todos os rótulos existentes e aplicá-los sozinhos ou em conjunto para filtrar as estatísticas exibidas.

Dados de entrega agregados com a API Data do FCM

A API Data do Firebase Cloud Messaging permite recuperar informações que possam ajudar você a entender os resultados das solicitações de mensagens direcionadas a apps Android. A API fornece dados agregados de todos os dispositivos Android com coleta de dados ativada em um projeto. Isso inclui detalhes sobre a porcentagem de mensagens entregues sem atraso e quantas mensagens atrasaram ou foram descartadas na Camada de transporte do Android. A avaliação desses dados pode revelar grandes tendências na entrega de mensagens e ajudar você a encontrar maneiras eficientes para melhorar o desempenho das solicitações de envio. Veja as linhas do tempo de dados agregados para saber mais sobre a disponibilidade de períodos nos relatórios.

A API fornece todos os dados disponíveis para um determinado aplicativo. Acesse a documentação de referência da API.

Como os dados são divididos?

Os dados de exibição são divididos por aplicativo, data e rótulo de análise. Uma chamada à API retornará dados para cada combinação dessas informações. Por exemplo, um único objeto JSON androidDeliveryData seria assim:

 {
  "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
    }
  }

Como interpretar as métricas

Os dados de entrega descrevem a porcentagem de mensagens que se enquadram em cada uma das métricas a seguir. É possível que uma única mensagem se ajuste a várias métricas. Devido às limitações na forma como coletamos os dados e no nível de detalhes em que as métricas foram agregadas, alguns resultados não são representados nas métricas, portanto, a soma das porcentagens abaixo não totaliza 100%.

Contar mensagens aceitas

A única contagem incluída no conjunto de dados é a de mensagens que foram aceitas pelo FCM para serem entregues a dispositivos Android. Todas as porcentagens usam esse valor como denominador. Lembre-se de que essa contagem não incluirá mensagens segmentadas a usuários que desativaram a coleta de informações de uso e diagnóstico nos dispositivos.

Porcentagens de resultados de mensagens

Os campos incluídos no objeto MessageOutcomePercents fornecem informações sobre os resultados das solicitações de mensagens. As categorias são mutuamente exclusivas. Esse objeto pode responder a perguntas como "Minhas mensagens estão sendo entregues?" e "Por qual motivo as mensagens estão sendo descartadas?"

Por exemplo, um valor alto no campo droppedTooManyPendingMessages pode indicar que as instâncias do app estão recebendo volumes de mensagens não recolhíveis que excedem o limite de 100 mensagens pendentes do FCM. Para atenuar isso, verifique se o app processa chamadas para onDeletedMessages e considere enviar mensagens recolhíveis. Da mesma forma, porcentagens altas no droppedDeviceInactive podem ser um sinal para atualizar tokens de registro no servidor, remover tokens desatualizados e cancelar a inscrição deles nos tópicos. Para ver as práticas recomendadas nessa área, consulte Gerenciar tokens de registro do FCM.

Porcentagens de desempenho de entregas

Os campos no objeto DeliveryPerformancePercents fornecem informações sobre mensagens que foram entregues. Ele pode responder a perguntas como "As mensagens foram enviadas com atraso?" e "Por que as mensagens estão atrasadas?". Por exemplo, um valor alto para delayedMessageThrottled indica que você excedeu os limites máximos por dispositivo e precisa ajustar a frequência de envio das mensagens.

Porcentagens de insights de mensagens

Esse objeto fornece mais informações sobre todas as mensagens enviadas. O campo priorityLowered mostra a porcentagem de mensagens aceitas que tinham prioridade reduzida de HIGH para NORMAL. Se esse valor for alto, tente enviar menos mensagens com prioridade alta ou garanta que uma notificação seja sempre exibida quando esse tipo de mensagem for enviada. Para mais informações, consulte nossa documentação sobre a prioridade de mensagens.

Qual é a diferença entre esses dados e os que são exportados para o BigQuery?

A exportação do BigQuery fornece registros de mensagens individuais sobre a aceitação de mensagens pelo back-end do FCM e a entrega de mensagens no SDK no dispositivo (etapas 2 e 4 da Arquitetura do FCM). Esses dados são úteis para garantir que mensagens individuais sejam aceitas e enviadas. Leia mais sobre exportação de dados do BigQuery na próxima seção.

Por outro lado, a API de dados do Firebase Cloud Messaging fornece detalhes agregados sobre o que acontece na camada de transporte Android (ou etapa 3 da Arquitetura do FCM). Esses dados fornecem insights sobre a entrega de mensagens dos back-ends do FCM para o SDK do Android. É muito útil para mostrar tendências sobre o motivo pelo qual as mensagens foram entregues com atraso ou descartadas durante esse transporte.

Em alguns casos, é possível que os dois conjuntos de dados não correspondam exatamente devido ao seguinte:

  • As métricas agregadas analisam apenas uma parcela das mensagens
  • As métricas agregadas são arredondadas
  • Não apresentamos métricas abaixo de um limite de privacidade
  • Alguns resultados de mensagens estão ausentes devido a otimizações na forma como gerenciamos o grande volume de tráfego

Limitações da API

Linhas do tempo de dados agregados

A API vai retornar sete dias de dados históricos. No entanto, os dados retornados por essa API serão atrasados em até cinco dias. Por exemplo, no dia 20 de janeiro, os dados entre 9 e 15 de janeiro vão estar disponíveis, mas não para 16 de janeiro em diante. Além disso, os dados são fornecidos com o melhor esforço. No caso de interrupção dos dados, o FCM trabalhará para corrigir o erro e não preencherá os dados após o problema ser resolvido. Em interrupções maiores, os dados podem ficar indisponíveis por uma semana ou mais.

Cobertura de dados

As métricas fornecidas pela API de dados do Firebase Cloud Messaging têm como objetivo oferecer insights sobre grandes tendências da entrega de mensagens. No entanto, elas não fornecem 100% de cobertura de todos os cenários de mensagem. Os casos a seguir são resultados conhecidos que não são refletidos nas métricas.

Mensagens expiradas

Se o time to live (TTL) expirar após o fim da data de registro especificada, a mensagem não será contada como droppedTtlExpired nessa data.

Mensagens para dispositivos inativos

As mensagens enviadas para dispositivos inativos podem ou não aparecer no conjunto de dados, dependendo do caminho de dados percorrido. Isso pode levar a uma contagem incorreta nos campos droppedDeviceInactive e pending.

Mensagens para dispositivos com preferências específicas do usuário

As mensagens dos usuários que desativaram a coleta de informações de uso e diagnósticos nos dispositivos não serão incluídas na contagem, de acordo com as preferências deles.

Arredondamento e mínimos

O FCM deliberadamente arredonda e exclui contagens em que os volumes não são grandes o suficiente.

Exportação de dados do BigQuery

É possível exportar os dados da sua mensagem ao BigQuery para uma análise mais detalhada. Com isso, é possível fazer análises usando o BigQuery SQL, exportar os dados para outro provedor de nuvem ou usá-los nos seus modelos personalizados de ML. Uma exportação para o BigQuery inclui todos os dados disponíveis para mensagens, independentemente do tipo de mensagem ou se ela é enviada usando a API ou o Editor do Notificações.

No caso de mensagens enviadas para dispositivos com as seguintes versões mínimas do SDK do FCM, você tem a opção de ativar a exportação de dados de entrega de mensagens para seu app:

  • Android 20.1.0 ou versão posterior
  • iOS 8.6.0 ou versão posterior
  • SDK do Firebase para Web 9.0.0 ou versão posterior

Veja abaixo detalhes sobre como ativar a exportação de dados para Android e iOS.

Para começar, vincule seu projeto ao BigQuery:

  1. Escolha uma das opções a seguir:

    • Abra o Editor do Notificações e clique em Acessar o BigQuery na parte inferior da página.

    • Na página Integrações no Console do Firebase, clique em Vincular no card do BigQuery.

      Esta página exibe opções de exportação do FCM para todos Apps compatíveis com o FCM no projeto.

  2. Siga as instruções na tela para ativar o BigQuery.

Consulte a página Vincular o Firebase ao BigQuery para mais informações.

Quando você ativa a exportação do BigQuery para o Cloud Messaging:

  • O Firebase exporta seus dados para o BigQuery. A propagação inicial dos dados para exportação pode levar até 48 horas para ser concluída.

  • Após a criação do banco de dados, o local não pode ser alterado, mas é possível mover (recriar) ou copiar o conjunto de dados para um local diferente. Para saber mais, consulte Mudar local do conjunto de dados.

  • O Firebase configura sincronizações regulares dos dados do projeto do Firebase para o BigQuery. Essas operações de exportação diárias começam às 9h, horário de Brasília, e geralmente terminam em 24 horas.

  • Todos os apps no projeto são vinculados ao BigQuery por padrão, e qualquer app adicionado posteriormente ao projeto também é vinculado automaticamente ao BigQuery. É possível gerenciar quais apps enviam dados.

Para desativar a exportação do BigQuery, desvincule seu projeto no Console do Firebase.

Ativar a exportação de dados de entrega de mensagens

dispositivos iOS com o SDK do FCM 8.6.0 ou versões posteriores podem ativar a exportação de dados de entrega de mensagens do app. O FCM aceita a exportação de dados para notificações de alerta e em segundo plano. Antes de ativar essas opções, primeiro crie o link do FCM-BiqQuery para seu projeto, conforme descrito em Exportação de dados do BigQuery.

Ativar a exportação de dados de entrega para notificações de alerta

Como apenas as notificações de alerta podem acionar extensões de app de serviço de notificação, é preciso adicionar uma extensão de serviço de notificação ao app e chamar essa API dentro de uma extensão de serviço para ativar o rastreamento de mensagens de exibição. Consulte a documentação da Apple sobre Como modificar o conteúdo em notificações recém-entregues (em inglês).

Esta notificação precisa ser feita para cada notificação recebida:

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.extensionHelper()
      .exportDeliveryMetricsToBigQuery(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

Se você estiver criando solicitações de envio usando a API HTTP v1, especifique mutable-content = 1 no objeto de payload.

Ativar exportação de dados de entrega para notificações em segundo plano

Para mensagens em segundo plano recebidas quando o app está em primeiro ou segundo plano, é possível chamar a API de exportação de dados dentro do gerenciador de mensagens de dados do app principal. Essa chamada precisa ser feita para cada notificação recebida:

Swift

// For background notifications, call the API inside the UIApplicationDelegate or NSApplicationDelegate method:
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any]) {
  Messaging.extensionHelper().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

Quais dados são exportados para o BigQuery?

A segmentação de tokens obsoletos ou registros inativos pode aumentar algumas dessas estatísticas.

Veja a seguir o esquema da tabela exportada:

_PARTITIONTIME TIMESTAMP Essa pseudocoluna contém um carimbo de data/hora para o início do dia, no fuso horário UTC. Essa data e hora representam o momento em que os dados foram carregados. Para a partição AAAAMMDD, essa pseudocoluna contém o valor TIMESTAMP('AAAA-MM-DD').
event_timestamp TIMESTAMP É o carimbo de data/hora do evento conforme registrado pelo servidor.
project_number INTEGER Esse número identifica o projeto que enviou a mensagem.
message_id STRING O ID da mensagem identifica uma mensagem. Gerado usando o ID do app e o carimbo de data/hora. O ID da mensagem pode, em alguns casos, não ser exclusivo globalmente.
instance_id STRING É o ID exclusivo do app para onde a mensagem é enviada (quando disponível). Pode ser um ID de instância ou de instalação do Firebase.
message_type STRING É o tipo de mensagem. Pode ser uma mensagem de notificação ou de dados. O tópico é usado para identificar a mensagem original em um envio de tópico ou campanha. As mensagens subsequentes são mensagens de notificação ou de dados.
sdk_platform STRING É a plataforma do aplicativo do destinatário.
app_name STRING É o nome do pacote de apps para Android ou o ID do pacote de apps para iOS.
collapse_key STRING A chave de recolhimento identifica um grupo de mensagens que podem ser recolhidas. Quando um dispositivo não está conectado, apenas a última mensagem com uma determinada chave de recolhimento é enfileirada para eventual entrega.
priority INTEGER É a prioridade da mensagem. Os valores válidos são "normal" e "high" (alta). No iOS, eles correspondem às prioridades 5 e 10 de APNs.
ttl INTEGER Esse parâmetro especifica por quanto tempo (em segundos) a mensagem deverá ser mantida no armazenamento do FCM se o dispositivo ficar off-line.
tópico STRING É o nome do tópico para o qual uma mensagem foi enviada (quando aplicável).
bulk_id INTEGER O ID em massa identifica um grupo de mensagens relacionadas, como um envio específico a um tópico.
evento STRING O tipo do evento. Estes são os valores possíveis:
  • MESSAGE_ACCEPTED: a mensagem foi recebida pelo servidor do FCM, e o pedido é válido.
  • MESSAGE_DELIVERED: a mensagem foi entregue ao SDK do FCM do app no dispositivo. Por padrão, esse campo não é propagado. Para ativar, siga as instruções fornecidas em setDeliveryMetricsExportToBigQuery(boolean).
  • MISSING_REGISTRATIONS: o pedido foi rejeitado devido a um registro faltando.
  • UNAUTHORIZED_REGISTRATION: a mensagem foi rejeitada porque o remetente não está autorizado a enviar para o registro.
  • MESSAGE_RECEIVED_INTERNAL_ERROR: ocorreu um erro não especificado ao processar a solicitação de mensagem.
  • MISMATCH_SENDER_ID: a solicitação de envio de uma mensagem foi rejeitada devido a uma incompatibilidade entre o ID do remetente que enviou a mensagem e a informação declarada ao destino.
  • QUOTA_EXCEEDED: a solicitação de envio de uma mensagem foi rejeitada devido a uma cota insuficiente.
  • INVALID_REGISTRATION: a solicitação de envio de uma mensagem foi rejeitada devido a um registro inválido.
  • INVALID_PACKAGE_NAME: a solicitação de envio de uma mensagem foi rejeitada devido a um nome de pacote inválido.
  • INVALID_APNS_CREDENTIAL: a solicitação de envio de uma mensagem foi rejeitada devido a um certificado inválido de APNs.
  • INVALID_PARAMETERS: a solicitação de envio de uma mensagem foi rejeitada devido a parâmetros inválidos.
  • PAYLOAD_TOO_LARGE: a solicitação de envio de uma mensagem foi rejeitada devido a um payload maior que o limite.
  • AUTHENTICATION_ERROR: a solicitação de envio de uma mensagem foi rejeitada devido a um erro de autenticação. Verifique a chave da API usada para enviar a mensagem.
  • INVALID_TTL: a solicitação de envio de uma mensagem foi rejeitada devido a um TTL inválido.
analytics_label STRING Com a API HTTP v1, o rótulo de análise pode ser definido ao enviar a mensagem para marcá-la para análise

O que você pode fazer com os dados exportados?

As seções a seguir oferecem exemplos de consultas que podem ser executadas no BigQuery em comparação com os dados exportados do FCM.

Contar mensagens enviadas por app

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;

Contar instâncias de apps exclusivas segmentadas por mensagens

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

Contar mensagens de notificação enviadas

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';

Contar mensagens de dados enviadas

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';

Contar mensagens enviadas para um tópico ou uma campanha

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 != '';

Para acompanhar eventos de uma mensagem enviada a um tópico específico, modifique esta consulta para substituir AND message_id != '' por AND message_id = <your message id>;.

Calcular a duração do fanout para um determinado tópico ou campanha

O horário de início do fanout representa o momento em que a solicitação original é recebida. A hora de término representa o momento da criação da última mensagem individual que segmenta uma instância única.

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;

Contar a porcentagem de mensagens entregues

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;

Rastrear todos os eventos para um determinado ID de mensagem e instância

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;

Calcular a latência de um determinado ID de mensagem e instância

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;