BigQuery への Firebase イベントログのインポート

このチュートリアルでは、データを詳細に分析するために、Firebase 向け Google アナリティクスおよび Firebase Crashlytics から Google BigQuery にイベントログをエクスポートする方法を説明します。

Firebase は、データとファイルのストレージ、リアルタイム同期、認証などの機能を利用して、モバイルアプリを構築するためのプラットフォームです。 Firebase 向け Google アナリティクスは、Firebase 機能の使用状況を追跡し、アプリの使用状況およびユーザー エンゲージメントに関する分析情報を提供します。Firebase Crashlytics は、アプリの障害を記録し、ユーザーが経験する問題の種類や発生頻度に関する分析情報を提供します。

BigQuery は、ペタバイト級のデータ ウェアハウスであり、膨大な量のデータに対して SQL に似たクエリをリアルタイムに近い速度で行うことができます。

Firebase データを BigQuery にインポートすると、次の利点があります。

  • 複数のソースからデータを集約 — Firebase 向け Google アナリティクス、Firebase Crashlytics、Google アナリティクス 360、モバイル バックエンド サービスによって収集されたカスタム アナリティクスなど、複数の場所でユーザー イベントを追跡する場合、これらのすべてのソースから BigQuery にデータをインポートして、イベントデータの全体像を提供する分析を行うことができます。

  • 元データへのアクセス — BigQuery にデータをインポートすると、元データ値にアクセスして、イベントの分析を柔軟に行うことができるようになります。

  • アクセス制御 — BigQuery にデータをエクスポートすると、BigQuery ACL を使用してプロジェクトとデータセットに対する権限を管理し、Firebase アプリに対するアクセス権を提供することなくデータを共有できるようになります。

  • コールドデータのアーカイブ — 元データを保持する必要がある場合は、データを BigQuery に pull し、Google Cloud Storage や安価な長期保存用の別のストレージ場所にアーカイブできます。

  • カスタム イベント パラメータ — Google アナリティクスでは、追跡するカスタム イベントとパラメータを定義できます。データを BigQuery にインポートすることにより、標準とカスタムのイベント パラメータの両方に対して豊富な分析を実行できるようになります。

目標

このチュートリアルでは、次の方法について説明します。

  • Firebase プロジェクトを BigQuery にリンクする。これにより、Firebase 向け Google アナリティクス、および Firebase Crashlytics は BigQuery にイベントログを毎日エクスポートできます。
  • BigQuery に格納されたデータに対するクエリを実行する。

料金

Firebase データを BigQuery に送信するには、プロジェクトを Blaze レベルのサービスにアップグレードする必要があります。詳細については、Firebase の料金をご覧ください。

Firebase プロジェクトが BigQuery にリンクされている間は、次の費用が発生します。

毎日のイベントデータを BigQuery テーブルにストリーミングするための費用
毎日、リンクされたアプリから BigQuery テーブルに生のイベントデータがストリーミングされます。詳しくは、BigQuery を Firebase にリンクするをご覧ください。
BigQuery にデータを保存し、BigQuery に対してデータのクエリを実行するための費用
BigQuery には、データの保存量とクエリでのデータ処理量に基づく、さまざまな料金設定が用意されています。詳しくは、BigQuery の料金をご覧ください。

始める前に

  1. Firebase プロジェクトを作成します。

  2. Firebase イベントを送信するアプリをビルドします。方法については、Firebase Crashlytics を使ってみる、または iOS 用 Firebase 向け Google アナリティクスを使ってみるAndroid 用 Firebase 向け Google アナリティクスを使ってみるをご覧ください。

BigQuery へのプロジェクト データのリンク

Firebase プロジェクトを BigQuery にリンクすると、サンプリングされていない元のイベントデータにアクセスできるようになります。

  1. Firebase コンソールで [統合] ページにアクセスします。

  2. BigQuery カードで、[リンク] をクリックします。

  3. スイッチを使用して、アナリティクス データ、Crashlytics データ、またはその両方をエクスポートするかどうかを決定します。アナリティクス データをエクスポートする場合は、広告 ID を追加することもでき、これによって豊富なデータが提供されますが、BigQuery で追加のストレージとクエリの料金が発生します。

  4. [BigQuery にリンク] をクリックしてタスクを完了します。

プロジェクトをリンクすると、BigQuery は対応するデータセットを作成し、データセットをプロジェクトに関連付けます。プロジェクトによって、リンクされた各アプリのデータセットに新しいテーブルが毎日追加されます。データセットは、プロジェクトのイベントの最初の日次エクスポート後に利用できるようになります。

BigQuery にデータを送信するアプリを管理する

BigQuery にプロジェクトをリンクすると、Firebase はプロジェクト内のすべてのアプリのイベントをエクスポートします。日次のエクスポートからアプリを除外することで、この動作を変更できます。

  1. Firebase コンソールで [統合] ページにアクセスします。

  2. BigQuery カードで、[管理] をクリックします。

  3. アプリが BigQuery にデータを送信しないようにするには、そのアプリ名の横にあるスイッチをクリックし、[エクスポートを停止] を選択します。

  1. Firebase コンソールで [統合] ページにアクセスします。

  2. BigQuery カードで、[管理] をクリックします。

  3. ページの下部にある [プロジェクトのリンクを解除] を選択し、[BigQuery のリンクを解除] をクリックして確定します。

BigQuery での Firebase データのクエリ

データが BigQuery ロードされると、BigQuery を使用して、SQL に似たクエリを実行できます。詳細については、BigQuery のドキュメントでデータのクエリをご覧ください。

BigQuery は、フォームに入力して [クエリを実行] をクリックするだけで、データに対するクエリを簡単に実行できるウェブ UI を提供します。詳細については、BigQuery のドキュメントでウェブ UI を使用したクイックスタートをご覧ください。

BigQuery での Firebase アナリティクス データの操作

次に、アナリティクスのデータに対して実行できるクエリの例を示します。これらのクエリは、Google アナリティクス ダッシュボードでは提供されないレポートを生成します。

カスタム イベント パラメータのクエリ

Google アナリティクスでは、イベントにカスタム パラメータキーと値を設定できます。キーは String として型付けされており、値は String 型、Long 型、または Double 型にすることができます。

以下のクエリは、カスタム イベント値を集約して、ビジネス インサイトを提供するレポートを生成する方法を具体的に示しています。

例 1:

モバイルゲーム デベロッパーは、ゲームのどのレベルで、ゲーム内の購入フローが最大になるか知りたいと思っています。そのために、プレーヤーがゲーム内購入フローを開始すると実行される、次のカスタム イベント呼び出しをゲームに追加します。

この例では、カスタム イベントの名前は trigger_purchase であり、プレーヤーが購入を開始したときのレベルを示す整数値を指定するキー level を持っています。

iOS - Objective C

[FIRAnalytics logEventWithName:@"trigger_purchase"
                parameters:@{
                              @"level": 3,
}];

iOS - Swift

FIRAnalytics.logEventWithName("trigger_purchase", parameters: [
  "level": 3
])

Android - Java

Bundle params = new Bundle();
params.putInt("level", 3);
mFirebaseAnalytics.logEvent("trigger_purchase", params);

このカスタム イベントでは、BigQuery 内の結果としてのエントリは次のようになります。

フィールド
event_dim.name trigger_purchase
event_dim.params.key level
event_dim.params.value.int_value 3

レベルごとの購入数を決定するために、ユーザーの現在のレベル別にグループ化された trigger_purchase イベント数の分布を報告するクエリを作成します。このクエリは、データ範囲 2015/01/01 から 2016/12/31 にわたって実行されます。

SELECT COUNT(event_dim.name) as NumberOfPurchases,
event_dim.params.value.int_value as level
FROM
TABLE_DATE_RANGE(com_game_example_ANDROID.app_events_, TIMESTAMP('2015-01-01'), TIMESTAMP('2016-12-31'))
WHERE event_dim.name = 'trigger_purchase'
GROUP BY level

例 2:

同じゲームに対して作業している 2 番目のデベロッパーは、どのキャラクター クラスが最も多くの敵を倒すか知りたいと思っています。そのために、プレーヤーが敵を倒すとログを記録する次のカスタム イベントを追加します。

この例では、カスタム イベントの名前は defeat_opponent であり、敵の名前を示す文字列値を指定するキー character を持ちます。

iOS - Objective C

[FIRAnalytics logEventWithName:@"defeat_opponent"
                parameters:@{
                              @"character": "Hercules"
}];

iOS - Swift

FIRAnalytics.logEventWithName("defeat_opponent", parameters: [
  "character": "Hercules"
])

Android - Java

Bundle params = new Bundle();
params.putString("character", "Hercules");
mFirebaseAnalytics.logEvent("defeat_opponent", params);

このカスタム イベントでは、BigQuery 内の結果としてのエントリは次のようになります。

フィールド
event_dim.name defeat_opponent
event_dim.params.key character
event_dim.params.value.string_value Hercules

最も成功したキャラクター クラスを見つけるために、キャラクター クラスが defeat-opponent カスタム イベントに関係した回数をカウントするクエリを記述します。

SELECT COUNT(event_dim.name) as DefeatEvents,
event_dim.params.value.string_value as CharacterClass
FROM
TABLE_DATE_RANGE( com_game_example_ANDROID.app_events_, TIMESTAMP('2015-01-01'), TIMESTAMP('2016-12-31'))
WHERE event_dim.name = 'defeat_opponent'
AND event_dim.params.key = 'character'
GROUP BY CharacterClass
ORDER BY DefeatEvents desc

ユーザー イベントのクエリ

カスタム イベントのクエリに加えて、ユーザー イベント値を集計してビジネス インサイトを提供するレポートを生成することもできます。

例 3:

アプリのデベロッパーが、Firebase Cloud Messaging を使用して最近アプリを利用していないユーザーに再エンゲージメントのプッシュ通知を送信します。通知の連絡先リストを作成するために、以下のクエリを使用して、この 1 年間に登録したユーザーのうち、過去 2 週間アプリを利用していないユーザーを特定します。このクエリでは、iOS と Android の両方のユーザーが、初めてアプリを開いた日の日付とともに返されます。

下記のクエリの user_dim.user_id フィールドには、デベロッパーが setUserId API を呼び出してアプリで設定したユーザー ID が含まれています。この値が設定されると、Google アナリティクスはそれを永続化し、そのユーザーに関連する以降のすべての行にこの値を取り込みます。この値は、過去の行にさかのぼって追加されることはありません。

user_dim.user_id で ID を設定しない場合は、app_info.app_instance_id フィールドを代わりに使用できます。このフィールドには、user_dim.user_id の代わりに、Firebase によって生成されるデフォルトの ID が取り込まれます。同じデバイスで Firebase アプリをアンインストールして再インストールするたびに新しい app_info.app_instance_id が生成されることに注意してください。

iOS アプリの場合、BigQuery にエクスポートされるデータテーブルは com_retail_example_IOS.app_events_[DATE] です。Android でこれに対応するデータテーブルは com_retail_example_ANDROID.app_events_[DATE] です。[DATE] には現在の日付が取り込まれます。

SELECT
  userId,
  DATE(MIN( firstOpenTime )) firstOpenTime
FROM (
  SELECT
    user_dim.user_id AS userId,
    user_dim.first_open_timestamp_micros AS firstOpenTime
  FROM (TABLE_DATE_RANGE([com_retail_example_IOS.app_events_],
    DATE_ADD(CURRENT_TIMESTAMP(), -1, 'YEAR'), CURRENT_TIMESTAMP())),
    (TABLE_DATE_RANGE([com_retail_example_ANDROID.app_events_],
    DATE_ADD(CURRENT_TIMESTAMP(), -1, 'YEAR'), CURRENT_TIMESTAMP())) )
WHERE
  userId NOT IN (
  SELECT
    user_dim.user_id AS userId
  FROM (TABLE_DATE_RANGE([com_retail_example_IOS.app_events_],
    DATE_ADD(CURRENT_TIMESTAMP(), -14, 'DAY'), CURRENT_TIMESTAMP())),
    (TABLE_DATE_RANGE([com_retail_example_ANDROID.app_events_],
    DATE_ADD(CURRENT_TIMESTAMP(), -14, 'DAY'), CURRENT_TIMESTAMP())) )
GROUP BY
  userId

例 4:

iOS と Android の両方のプラットフォームでアプリのアクティブ ユーザー数が多い国を特定します。そのためには、以下のクエリを使用して、特定の日のユーザーとイベントの数を国別に表示します。

内側のクエリは、特定の行の user_idcountry を返し、その行のすべてのイベントをカウントします。このクエリでは、RECORD 内の event_dim として WITHIN RECORD 句が使用されています。これは、ネストされたレコードの集約を扱う最適な方法です。

外側のクエリでは、ユーザーの合計数の正確な値を提供するために userIdEXACT_COUNT_DISTINCT を使用しています。代わりに COUNT(DISTINCT user_id) を使用することもできますが、正確な値ではなく概算値になります。概算値の方が高速に処理できるため、非常に大きなデータセットで期間中の傾向を特定する場合など、正確さよりスピードが重視される場合には、概算値を使用できます。

SELECT
  country,
  EXACT_COUNT_DISTINCT(user_id) AS users,
  SUM(noOfEvents) AS totalEvents
FROM (
  SELECT
    user_dim.app_info.app_instance_id AS user_id,
    user_dim.geo_info.country AS country,
    COUNT(event_dim.name) WITHIN RECORD noOfEvents
  FROM
    [com_retail_example_IOS.app_events_20160723],
    [com_retail_example_ANDROID.app_events_20160723]
    )
GROUP BY
  1
ORDER BY
  2 DESC

BigQuery 内の Google アナリティクス スキーマについて

Firebase 向け Google アナリティクスを BigQuery に接続すると、Firebase は BigQuery に毎日データをエクスポートします。エクスポートされるデータは以下の形式になります。

データセット

Firebase 向け Google アナリティクスは、各 Firebase アプリに対して BigQuery に新しいデータセットを作成します。データセット名は [app_name]_[PLATFORM] の形式になり、app_name にはバンドル ID(iOS)またはパッケージ名(Android)が入ります。

Google アナリティクスは、BigQuery の命名規則に合わせるため、バンドル ID またはパッケージ名のピリオドをアンダースコアに変換します。アナリティクスは、Firebase の命名規則に合わせるため、プラットフォーム名を大文字で指定します。

たとえば、バンドル ID として「com.username.myapp」を持つ iOS アプリに対応するデータセットは、com_username_myapp_IOS という名前のデータセットになります。

テーブル

Google アナリティクスは、アプリに対応する BigQuery データセット内に新しいテーブルを毎日作成します。テーブルには、パターン app_events_YYYYMMDD を使用して名前が付けられ、指定された日に記録されたイベントが含まれます。

イベントのバンドルに対応するテーブル内の各行。バンドルのサイズは、Firebase 向け Google アナリティクス SDK の呼び出しでデータを送信するアプリによって決定されます。

Google アナリティクスは、カスタムデータ イベントを含む列としてユーザー イベントをエクスポートします。BigQuery にエクスポートされる標準列のリストについては、Firebase ヘルプ ドキュメントで BigQuery Export のスキーマをご覧ください。

BigQuery での Firebase Crashlytics データの操作

次の例は、Crashlytics データに対して実行できるクエリを示しています。これらのクエリは、Crashlytics ダッシュボードでは提供されないレポートを生成します。

Crashlytics クエリの例

次の例は、障害イベントデータを、より簡単に理解できる概要に集約するレポートを生成する方法を示しています。

例 1:

Friendly Pix の主任開発者は、できるだけ多くのバグを潰すことに取り組んだ後、ついに新しい写真共有アプリをリリースする準備ができたと考えています。リリースする前に、彼らは過去 1 か月間の 1 日あたりの障害件数を確認し、アプリがバグバッシュによって時間の経過とともに安定したことを確認したいと考えています。

#standardSQL
SELECT
  COUNT(DISTINCT event_id) AS number_of_crashes,
  FORMAT_TIMESTAMP("%F", event_timestamp) AS date_of_crashes
FROM
  `projectId.crashlytics.package_name_ANDROID`
GROUP BY
  date_of_crashes
ORDER BY
  date_of_crashes DESC
LIMIT
  30;

例 2:

PineapplePlusPlus のプロジェクト マネージャーは、生産計画の優先順位付けを正しく行うために、自社製品で最も多い障害を指摘する方法を思案しています。データの適切なポイントを提供するクエリを生成します。

#standardSQL
SELECT
  DISTINCT issue_id,
  COUNT(DISTINCT event_id) AS number_of_crashes,
  COUNT(DISTINCT installation_uuid) AS number_of_impacted_user,
  blame_frame.file,
  blame_frame.line
FROM
  `projectId.crashlytics.package_name_ANDROID`
WHERE
  event_timestamp >= TIMESTAMP_SUB(CURRENT_TIMESTAMP(),INTERVAL 168 HOUR)
  AND event_timestamp < CURRENT_TIMESTAMP()
GROUP BY
  issue_id,
  blame_frame.file,
  blame_frame.line
ORDER BY
  number_of_crashes DESC
LIMIT
  10;

例 3:

秋は新しいスマートフォンのシーズンです。Planned Obsolescence、Inc. のデベロッパーは、秋は新しいデバイス固有の問題のシーズンでもあるということを知っています。今後の互換性の問題を先取りするために、先週最も多く障害が発生した 10 台のデバイスを特定するためのクエリを作成しました。

#standardSQL
SELECT
  device.model,
  COUNT(DISTINCT event_id) AS number_of_crashes
FROM
  `projectId.crashlytics.package_name_ANDROID`
WHERE
  event_timestamp >= TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 168 HOUR)
  AND event_timestamp < CURRENT_TIMESTAMP()
GROUP BY
  device.model
ORDER BY
  number_of_crashes DESC
LIMIT
  10;

例 4:

「Mecha Hamster 2: Hammy's Revenge」のゲーム デベロッパーは、ゲームのどのレベルで最も多くの障害が発生するかを知りたいと思っています。その統計情報を追跡するために、カスタムの Crashlytics キー current_level を設定し、ユーザーが新しいレベルになるたびにこのキーを更新します。

iOS - Objective C

[CrashlyticsKit setIntValue:3 forKey:@"current_level"];

iOS - Swift

Crashlytics.sharedInstance().setIntValue(3, forKey: "current_level")

Android - Java

Crashlytics.setInt("current_level", 3);

次に、BigQuery のエクスポートのそのキーを使用して、current_level 値の分布を各障害イベントに関連付けて報告するクエリを記述します。

#standardSQL
SELECT
  COUNT(DISTINCT event_id) AS num_of_crashes,
  value
FROM
  `projectId.crashlytics.package_name_ANDROID`,
  UNNEST(custom_keys)
WHERE
  key = "current_level"
GROUP BY
  key,
  value
ORDER BY
  num_of_crashes DESC

例 5:

Mostly Okay Software のデベロッパーは、早期アクセスのアプリを開発しました。ほとんどのユーザーはそのアプリを気に入っていますが、ごく一部のユーザーは異常な数の障害を経験しています。問題の根本原因を突き止めるために、それらのユーザーのすべての障害イベントを、そのユーザーの ID を使用して取得するクエリを作成します。

#standardSQL
SELECT
  *
FROM
  `projectId.crashlytics.package_name_ANDROID`
WHERE
  user.id IN ("userid1",
    "userid2",
    "userid3")
ORDER BY
  user.id

BigQuery 内の Firebase Crashlytics スキーマについて

Crashlytics と BigQuery をリンクすると、Firebase はリンクの 2 日前までのイベントを含む、最近の致命的な障害イベントおよび致命的でない障害イベントをエクスポートします。その時点からユーザーがリンクを無効にするまで、Firebase は Crashlytics イベントを毎日エクスポートします。各エクスポート後に BigQuery でデータを利用できるようになるまでに数分かかることがあります。

データセット

Firebase Crashlytics は、BigQuery に Crashlytics データ用の新しいデータセットを作成します。そのデータセットは、複数のアプリがある場合でもプロジェクト全体をカバーしますが、アナリティクスのエクスポートは含まれません。

テーブル

Firebase Crashlytics はプロジェクト内の各アプリに対して、そのアプリのデータのエクスポートを無効にしない限り、データセット内にテーブルを作成します。Firebase は、アプリのバンドル ID に基づいてテーブルの名前を付けます。ピリオドはアンダースコアに変換され、最後にプラットフォーム名が追加されます。例えば、ID が com.google.test のアプリのデータは、名前が com_google_test_ANDROID のテーブルにあります。

テーブルの各行は、アプリで発生したエラーを表します。

テーブルの列は、致命的なエラーの場合も致命的でないエラーの場合も同じです。BigQuery にエクスポートされる列のリストは、Crashlytics BigQuery Export スキーマをご覧ください。

データポータルを使用してエクスポートされた Crashlytics データの可視化

Google データポータルを使うと、BigQuery の Crashlytics データセットを、読みやすく、共有ができ、全面的にカスタマイズ可能なレポートに変換できます。

データポータルの使用方法の詳細については、データポータル クイックスタート ガイドのデータポータルへようこそを試してください。

Crashlytics レポート テンプレートを使用する

データポータルには、エクスポートされた Crashlytics BigQuery スキーマからの包括的なディメンションと指標のセットを含む Crashlytics のサンプル レポートがあります。このサンプルをテンプレートとして使用して、独自アプリの生のクラッシュ データを元にして簡単に新しいレポートを作成し、可視化できます。

  1. Crashlytics データポータル ダッシュボード テンプレートを開きます。
  2. 右上にある [Use Template] をクリックします。
  3. [Select a datasource] プルダウンで、[Create New Data Source] を選択します。
  4. BigQuery カードの [Select] をクリックします。
  5. [My Projects] > [プロジェクト名] > [firebase_crashlytics] > [テーブル名] を選択して、エクスポートされた Crashlytics データを含むテーブルを選択します。
  6. [Configuration] で、[Crashlytics Template level] を [Default] に設定します。
  7. [Connect] をクリックして新しいデータソースを作成します。
  8. [Add to Report] をクリックして Crashlytics テンプレートに戻ります。
  9. 最後に、[Create Report] をクリックして Crashlytics データポータル ダッシュボード テンプレートのコピーを作成します。

クリーンアップ

このチュートリアルで使用するリソースについて、Google Cloud Platform アカウントに課金されないようにする手順は次のとおりです。

課金を停止する最も簡単な方法は、このチュートリアルで作成したプロジェクトを削除することです。Firebase プロジェクトと Cloud Platform プロジェクトはまったく同じであることから、Firebase コンソールまたは Cloud Platform Console のいずれかを使用して削除できます。

  1. GCP Console で [プロジェクト] ページに移動します。

    プロジェクト ページに移動

  2. プロジェクト リストで、削除するプロジェクトを選択し、[削除] をクリックします。
  3. ダイアログでプロジェクト ID を入力し、[シャットダウン] をクリックしてプロジェクトを削除します。

Cloud Platform と Firebase のプロジェクトを削除したくない場合は、BigQuery からプロジェクトのリンクを解除してコストを削減できます。

次のステップ

このページは役立ちましたか?評価をお願いいたします。

フィードバックを送信...