メッセージ配信について

FCM には、メッセージ配信の分析に役立つ 3 つのツールセットが用意されています。

  • Firebase コンソールのメッセージ配信レポート
  • Firebase Cloud Messaging Data API が提供する集計済みの Android SDK 配信指標
  • Google BigQuery への包括的なデータ エクスポート

このページで説明するレポートツールを機能させるには、すべて Google Analytics が必要です。プロジェクトで Google Analytics が有効になっていない場合は、Firebase プロジェクト設定の [統合] タブで設定できます。

アナリティクス データをバッチ処理するため、このページの多くの統計情報はレポートに反映されるまで最大 24 時間かかる場合があります。

メッセージ配信レポート

Firebase コンソールの [レポート] タブでは、Android や Apple プラットフォームの FCM SDK に送信されたメッセージ(Notifications Composer および FCM API を介して送信されたメッセージを含む)に関して、以下のデータを表示できます。

  • 送信 - データ メッセージまたは通知メッセージが配信のためにキューに入れられているか、APN などのサードパーティのサービスに正常に渡されているかどうかを確認できます。詳細については、メッセージの有効期間をご覧ください。
  • 受信(Android デバイスでのみ利用可能) - データ メッセージまたは通知メッセージがアプリで受信されたかどうかを確認できます。このデータは、受信側の Android デバイスに FCM SDK 18.0.1 以降がインストールされている場合に提供されます。
  • 表示回数(Android デバイスの通知メッセージでのみ利用可能) - アプリがバックグラウンドで動作中に、デバイスに表示通知が表示されたかどうかを確認できます。
  • 開かれた回数 - ユーザーが通知メッセージを開いたかどうかを確認できます。ここに含まれるのは、アプリがバックグラウンドで動作中に受信した通知のみです。

このデータは、通知ペイロードが設定されているすべてのメッセージと、ラベルが付いているすべてのデータ メッセージに関して提供されます。 ラベルの詳細については、メッセージにアナリティクス ラベルを追加するをご覧ください。

メッセージ レポートを表示しているときに、表示されるデータの日付範囲を設定できます。また、CSV にエクスポートするためのオプションも用意されています。次に示す基準でフィルタすることもできます。

  • プラットフォーム(iOS または Android)
  • アプリ
  • カスタム アナリティクス ラベル

メッセージにアナリティクス ラベルを追加する

メッセージにラベルを付けると、配信統計情報をラベルやラベルセットでフィルタリングできるので、カスタム分析に非常に役立ちます。HTTP v1 API を使用して送信される任意のメッセージにラベルを追加するには、メッセージ オブジェクト内の fcmOptions.analyticsLabel フィールド、またはプラットフォーム固有の AndroidFcmOptions フィールドまたは ApnsFcmOptions フィールドを設定します。

アナリティクス ラベルは、^[a-zA-Z0-9-_.~%]{1,50}$ の形式のテキスト文字列です。ラベルには、大文字と小文字、数字のほかに、次の記号を含めることができます。

  • -
  • ~
  • %

最大長は 50 文字です。1 日あたり最大 100 個のユニークラベルを指定できます。この制限を超えるラベルが追加されたメッセージはレポートされません。

Firebase コンソールのメッセージの [レポート] タブで、既存のすべてのラベルの一覧を検索し、それらを単独でまたは組み合わせて適用して、表示される統計をフィルタすることができます。

FCM Data API が提供する集計済みの配信データ

Firebase Cloud Messaging Data API を使用すると、Android アプリを対象としたメッセージ リクエストの結果を把握するための情報を取得できます。この API は、プロジェクト内のデータ収集が可能なすべての Android デバイスから集計したデータを提供します。これには、遅延なしで配信されたメッセージの割合や、Android トランスポート レイヤ内で遅延したメッセージの数と破棄されたメッセージの数などが含まれます。このデータを評価することで、メッセージ配信の全般的な傾向を確認でき、送信リクエストのパフォーマンスを向上させる効果的な方法を見つけることができます。レポートに表示される期間については、集計データのタイムラインをご覧ください。

この API は、対象のアプリケーションで利用可能なすべてのデータを提供します。API リファレンス ドキュメントをご覧ください。

データの分類

配信データは、アプリケーション、日付、アナリティクス ラベルごとに分類されます。API を呼び出すと、日付、アプリケーション、アナリティクス ラベルのあらゆる組み合わせのデータが返されます。たとえば、単一の androidDeliveryData JSON オブジェクトは次のようになります。

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

指標を解釈する方法

配信データは、次の各指標に合致するメッセージの割合を示します。1 つのメッセージが複数の指標に合致する可能性があります。データの収集方法と指標を集計する粒度に制限があることにより、メッセージの結果の中には指標に含まれないものがあるため、以下の割合の合計は 100% になりません。

受け入れられたメッセージの数

このデータセットに含まれるメッセージの数は、Android デバイスに配信するために FCM によって受け入れられたメッセージの数のみです。すべての割合でこの値が分母として使用されます。この数には、デバイスで使用状況と診断情報の収集を無効にしているユーザーをターゲットにしたメッセージは含まれません。

メッセージの結果に関する割合

MessageOutcomePercents オブジェクトに含まれるフィールドには、メッセージ リクエストの結果に関する情報が示されます。カテゴリはすべて相互に排他的です。「メッセージは配信されているか」や「メッセージが破棄される原因は何か」といった疑問に対する答えが見つかります。

たとえば、droppedTooManyPendingMessages フィールドの値が大きいと、アプリ インスタンスが受信している折りたたみ不可のメッセージの量が、FCM の保留メッセージ数の上限である 100 を超えている可能性があります。これを軽減するには、アプリで onDeletedMessages の呼び出しが処理されていることを確認したうえで、折りたたみ可能なメッセージを送信することを検討してください。同様に、droppedDeviceInactive の割合が高い場合は、サーバーで登録トークンを更新し、古いトークンを削除してトピックの登録解除を行う必要があることを示している可能性があります。登録トークンに関するベスト プラクティスについては、FCM 登録トークンを管理するをご覧ください。

配信パフォーマンスに関する割合

DeliveryPerformancePercents オブジェクトの各フィールドには、正常に配信されたメッセージに関する情報が示されます。「メッセージは遅延したか」や「なぜメッセージが遅延したか」といった疑問に対する答えが見つかります。たとえば、delayedMessageThrottled の値が大きくなると、デバイスごとの上限を超過していることが明確なため、メッセージの送信レートを調整する必要があります。

メッセージの分析情報に関する割合

このオブジェクトは、すべてのメッセージ送信に関する追加情報を提供します。priorityLowered フィールドは、受け入れられたメッセージのうち、優先度が HIGH から NORMAL に下がったものの割合を表します。この値が大きい場合は、送信する優先度の高いメッセージの数を減らすか、優先度の高いメッセージを送信する際には必ず通知が表示されるようにしてください。詳しくは、メッセージの優先度に関するドキュメントをご覧ください。

このデータと BigQuery にエクスポートされるデータの違い

BigQuery Export では、FCM バックエンドによるメッセージの受け入れとデバイス上の SDK でのメッセージ配信(FCM アーキテクチャのステップ 2 と 4 )に関する個々のメッセージのログが提供されます。このデータは、個々のメッセージが受け入れられて配信されたことの確認に利用できます。詳細については、次のセクションの BigQuery へのデータのエクスポートをご覧ください。

一方、Firebase Cloud Messaging Data API では、Android トランスポート レイヤでの動作(FCM アーキテクチャのステップ 3)の詳細情報を集約したデータが提供されます。このデータは、FCM バックエンドから Android SDK へのメッセージ配信に関する具体的な分析情報を提供します。これは、このトランスポートでメッセージの遅延または破棄が発生した理由に関する傾向を把握するのに特に便利です。

場合によっては、次の理由により、これら 2 つのデータセットが正確に一致しないことがあります。

  • 集計された指標がすべてのメッセージの一部のみをサンプリングしている
  • 集計された指標に丸め処理が行われている
  • プライバシーのしきい値を下回る指標は提供されない
  • 大量のトラフィックを管理する際に最適化が行われるため、一部のメッセージの結果が失われる

API に関する制限事項

集計データのタイムライン

この API は 7 日間のデータを返します。ただし、この API から返されるデータは最大 5 日遅れます。たとえば、1 月 20 日に 1 月 9 日~1 月 15 日のデータは確認できても、1 月 16 日以降のデータは確認できない場合があります。また、データはベスト エフォートで提供されます。データの処理が停止した場合、FCM は問題の修復に向けて作業を行いますが、問題が修復された後にデータがバックフィルされることはありません。大規模な停止の場合、データを 1 週間以上利用できないことがあります。

データのカバー範囲

Firebase Cloud Messaging Data API によって提供される指標は、メッセージ配信の全般的な傾向に関する分析情報を提供することを意図しています。ただし、すべてのメッセージ シナリオが 100% カバーされるわけではありません。次のシナリオでは、結果が指標に反映されないことが確認されています。

期限切れのメッセージの数

指定したログ日付の終了後に有効期間(TTL)が切れた場合、この日付のメッセージは droppedTtlExpired としてカウントされません。

非アクティブなデバイスへのメッセージ

非アクティブなデバイスに送信されたメッセージは、データパスに応じてデータセットに含まれる場合と含まれない場合があります。これにより、droppedDeviceInactive フィールドと pending フィールドで数え違えが起こる可能性があります。

特定のユーザー設定が指定されたデバイスへのメッセージ

ユーザーがデバイスで使用状況と診断情報の収集を無効にしている場合、そのユーザー設定に沿って、それらのデバイスに送信されるメッセージはカウントされません。

丸めと最小値

FCM はデータ量が十分ではない場合に、意図的にそれらのカウントの丸め処理と除外を行います。

BigQuery へのデータのエクスポート

メッセージ データを BigQuery にエクスポートしてさらに分析できます。BigQuery では、BigQuery SQL を使用してデータを分析したり、別のクラウド プロバイダにデータをエクスポートしたり、データをカスタム ML モデルで使用したりできます。BigQuery へのエクスポートには、メッセージの種類、メッセージの送信手段(API、Notifications Composer)に関係なく、メッセージで利用可能なすべてのデータが含まれます。

次のバージョン以降の FCM SDK を使用しているデバイスに送信されるメッセージについては、アプリのメッセージ配信データのエクスポートを有効にする追加のオプションがあります。

  • Android 20.1.0 以降
  • iOS 8.6.0 以降
  • Firebase Web SDK 9.0.0 以降

データ エクスポートの有効化について詳しくは、AndroidiOSをご覧ください。

まず、プロジェクトを BigQuery にリンクします。

  1. 次のいずれかのオプションを選択します。

    • Notifications Composer を開き、ページの下部にある [BigQuery にアクセス] をクリックします。

    • Firebase コンソールの [統合] ページで、[BigQuery] カードの [リンク] をクリックします。

      このページには、プロジェクト内のすべての FCM 対応アプリの FCM エクスポート オプションが表示されます。

  2. 画面上の指示に従って BigQuery を有効にします。

詳しくは、BigQuery を Firebase にリンクするをご覧ください。

Cloud MessagingBigQuery へのエクスポートを有効にすると、次のようになります。

  • Firebase は BigQueryデータをエクスポートします。なお、エクスポートするデータの初回の読み込みには、最長で 48 時間かかる場合があります。

  • データセットの作成後はロケーションを変更できませんが、データセットを別のロケーションにコピーするか、データセットを別のロケーションに手動で移動(再作成)することはできます。詳細については、データセットのロケーションの変更をご覧ください。

  • Firebase は、Firebase プロジェクトから BigQuery へのデータの定期的な同期を設定します。これらの毎日のエクスポート オペレーションは、太平洋時間の午前 4 時に始まり、通常は 24 時間以内に完了します。

  • デフォルトでは、プロジェクト内のすべてのアプリが BigQuery にリンクされ、後からプロジェクトに追加するアプリもすべて BigQuery に自動的にリンクされます。データを送信するアプリを管理することもできます。

BigQuery のエクスポートを無効にするには、Firebase コンソールでプロジェクトのリンクを解除します。

メッセージ配信データのエクスポートを有効にする

FCM SDK 8.6.0 以降を使用している iOS デバイスでは、アプリのメッセージ配信データのエクスポートを有効にできます。FCM は、アラート通知とバックグラウンド通知の両方のデータ エクスポートをサポートしています。これらのオプションを有効にする前に、BigQuery データのエクスポートで説明されているように、まずプロジェクトの FCM-BiqQuery リンクを作成する必要があります。

アラート通知の配信データのエクスポートを有効にする

通知サービスのアプリ拡張機能をトリガーできるのはアラート通知のみです。そのため、表示メッセージ トラッキングを有効にするには、通知サービス拡張機能をアプリに追加し、サービス拡張機能内でこの API を呼び出す必要があります。詳しくは、Apple のドキュメントの新しく配信される通知のコンテンツの変更をご覧ください。

次の呼び出しは、受信したすべての通知に対して行う必要があります。

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

HTTP v1 API を使用して送信リクエストを作成する場合は、ペイロード オブジェクトmutable-content = 1 を指定してください。

バックグラウンド通知の配信データのエクスポートを有効にする

アプリがフォアグラウンドまたはバックグラウンドで動作しているときに受信するバックグラウンド メッセージについては、メインアプリのデータ メッセージ ハンドラの中で、Data Export API を呼び出すことができます。この呼び出しは、受信したすべての通知に対して行う必要があります。

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

BigQuery にエクスポートされるデータの概要

古いトークンや無効な登録をターゲットにすると、統計値が膨れ上がることがあります。

エクスポートされるテーブルのスキーマは次のとおりです。

_PARTITIONTIME TIMESTAMP この疑似列には、データが読み込まれた日の開始時点のタイムスタンプ(UTC)が含まれます。YYYYMMDD パーティションの場合、この疑似列には TIMESTAMP 値('YYYY-MM-DD')が入ります。
event_timestamp TIMESTAMP サーバーにより記録されたイベントのタイムスタンプ。
project_number INTEGER プロジェクト番号は、メッセージを送信したプロジェクトを示します。
message_id STRING メッセージ ID はメッセージを識別します。メッセージ ID はアプリ ID とタイムスタンプから生成されるため、グローバルに一意ではない場合があります。
instance_id STRING メッセージの送信先のアプリの一意の ID(利用可能な場合)。インスタンス ID または Firebase インストール ID のいずれかです。
message_type STRING メッセージのタイプ。通知メッセージまたはデータ メッセージのいずれかです。トピックまたはキャンペーンの送信における元のメッセージを識別するには、トピックが使用されます。後続のメッセージは、通知メッセージまたはデータ メッセージのいずれかです。
sdk_platform STRING 受信側のアプリのプラットフォーム。
app_name STRING Android アプリのパッケージ名または iOS アプリのバンドル ID。
collapse_key STRING 折りたたみキーは、折りたたむことができるメッセージのグループを示します。 デバイスが接続されていない場合、指定された折りたたみキーを持つ最後のメッセージのみが後の配信のためにキューに入れられます。
priority INTEGER メッセージの優先度。有効な値は「normal」と「high」です。iOS では、これらは APNs 優先度の 5 と 10 に相当します。
ttl INTEGER このパラメータでは、デバイスがオフラインの場合にメッセージを FCM のストレージに保持する期間(秒単位)を指定します。
topic STRING メッセージが送信されたトピックの名前(該当する場合)。
bulk_id INTEGER バルク ID は、トピックへの特定の送信など、関連するメッセージのグループを識別します。
イベント STRING イベントのタイプ。 値は次のとおりです。
  • MESSAGE_ACCEPTED: メッセージは FCM サーバーによって受信され、リクエストは有効です。
  • MESSAGE_DELIVERED: メッセージはデバイス上のアプリの FCM SDK に配信されました。デフォルトでは、このフィールドは伝播されません。有効にするには、setDeliveryMetricsExportToBigQuery(boolean) の手順に従ってください。
  • MISSING_REGISTRATIONS: 登録がないため、リクエストが拒否されました。
  • UNAUTHORIZED_REGISTRATION: 送信者に登録に送信する権限がないため、メッセージは拒否されました。
  • MESSAGE_RECEIVED_INTERNAL_ERROR: メッセージ リクエストの処理中に特定できないエラーが発生しました。
  • MISMATCH_SENDER_ID: メッセージを送信する送信者 ID と、エンドポイントに対して宣言された 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 を使用すると、メッセージの送信時にアナリティクス ラベルを設定して、そのメッセージをアナリティクス用としてマークできます。

エクスポートされたデータで可能な操作

以下のセクションでは、エクスポートされた FCM データに対して BigQuery で実行できるクエリの例を示します。

送信されたメッセージ数をアプリごとにカウントする

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;

指定されたメッセージ ID とインスタンス ID のすべてのイベントを追跡する

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;

指定されたメッセージ ID とインスタンス ID のレイテンシを計算する

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;