【BigQuery】特定期間のイベントparamsを取得する方法
この記事はFirebaseをバックエンドサービスとして使っていて、本格的にデータの収集・分析を開始しようと思いFirebase Analyticsを使って色んなイベントを設定したは良いが今度は以下の問題に突き当たっている方が対象読者になります:
・Firebase Analyticsを設定したはいいが、管理画面からは合計で10個のパラメータ(*イベントではない)しか見ることができない。
・さらに1つのイベントに複数のパラメータを設定している場合、管理画面からだとパラメータ同士がまとまっていない。
・地域やユーザー情報もパラメータと紐づいていない
この記事ではBigQueryを使って設定した期間中のイベントのパラメータをクエリする方法を書いていきます。
下準備
BigQueryをFirebaseにリンクするにはFirebaseを従量制のプラン にアップグレードする必要があります。
以下の手順 にしたがって管理画面からリンクすることができます。
- Firebase にログインします。
- 歯車マークのボタンをクリックして、「プロジェクトの設定」 を選択します。
- 「プロジェクトの設定」 ページで 「統合」タブをクリックします。
- BigQuery カードで、「リンク」 をクリックします。
プロジェクトで課金が有効になっていない場合は、「アップグレードしてリンク」をクリックします。Google 標準の課金設定プロセスに沿って操作します。 - 広告 ID をデータセットの一部としてエクスポートするかどうかを選択します。
BigQuery Export のスキーマ
イベントデータを出す前に、まずはAnalytics SDKがどんな情報を取得しているのかを理解しましょう。Firebaseの公式ドキュメント によると、Analytics SDKは以下の2種類の情報をロギングしています:
- イベント: ユーザーの操作、システム イベント、エラーなど、アプリで起こっていること。
- ユーザー プロパティ: 言語や地域など、ユーザー層を示す属性。自由に定義できます。
具体的なスキーマ は以下のようになっています:
フィールド名 | データ型 | 説明 |
---|---|---|
アプリ | ||
app_info | RECORD | アプリについての情報を格納するレコード。 |
app_info.id | 文字列 | アプリのパッケージ名またはバンドル ID。 |
app_info.firebase_app_id | 文字列 | アプリに関連付けられている Firebase アプリ ID。 |
app_info.install_source | 文字列 | アプリをインストールしたストア。 |
app_info.version | 文字列 | アプリの versionName(Android の場合)または short bundle version。 |
端末 | ||
device | RECORD | 端末の情報を格納するレコード。 |
device.category | 文字列 | 端末のカテゴリ(モバイル、タブレット、PC)。 |
device.mobile_brand_name | 文字列 | 端末のブランド名。 |
device.mobile_model_name | 文字列 | 端末のモデル名。 |
device.mobile_marketing_name | 文字列 | 端末のマーケティング名。 |
device.mobile_os_hardware_model | 文字列 | OS から直接取得した端末のモデル情報。 |
device.operating_system | 文字列 | 端末の OS。 |
device.operating_system_version | 文字列 | OS のバージョン。 |
device.vendor_id | 文字列 | IDFV(IDFA を収集していない場合にのみ使用)。 |
device.advertising_id | 文字列 | 広告 ID / IDFA。 |
device.language | 文字列 | OS の言語。 |
device.time_zone_offset_seconds | INTEGER | GMT との時差(秒単位)。 |
device.is_limited_ad_tracking | BOOLEAN | 端末の「広告トラッキング抑制」が有効になっているかどうか。 |
ストリームとプラットフォーム | ||
stream_id | 文字列 | ストリームの数値 ID。 |
platform | 文字列 | アプリケーションが構築されているプラットフォーム。 |
ユーザー | ||
user_first_touch_timestamp | INTEGER | ユーザーが初めてアプリを開いた時刻(ミリ秒単位)。 |
user_id | 文字列 | setUserId API によって設定されるユーザー ID。 |
user_pseudo_id | 文字列 | ユーザーの仮の ID(アプリ インスタンス ID など)。 |
user_properties | RECORD | setUserProperty API によって設定される、ユーザー プロパティの繰り返しレコード。 |
user_properties.key | 文字列 | ユーザー プロパティの名前。 |
user_properties.value | RECORD | ユーザー プロパティの値を格納するレコード。 |
user_properties.value.string_value | 文字列 | ユーザー プロパティの文字列値。 |
user_properties.value.int_value | INTEGER | ユーザー プロパティの整数値。 |
user_properties.value.double_value | FLOAT | ユーザー プロパティの倍精度値。 |
user_properties.value.float_value | FLOAT | このフィールドは現在使用されていません。 |
user_properties.value.set_timestamp_micros | INTEGER | ユーザー プロパティが最後に設定された時刻(ミリ秒単位)。 |
user_ltv | RECORD | ユーザーのライフタイム バリューに関する情報を格納するレコード。このフィールドは当日テーブルでは使用されません。 |
user_ltv.revenue | FLOAT | ユーザーのライフタイム バリュー(収益)。このフィールドは当日テーブルでは使用されません。 |
user_ltv.currency | 文字列 | ユーザーのライフタイム バリュー(通貨)。このフィールドは当日テーブルでは使用されません。 |
キャンペーン | 注: traffic_source のアトリビューションは、クロスチャネルのラストクリック に基づいています。traffic_source の値は、ユーザーがインストール後に次のキャンペーンを操作しても変更されません。 | |
traffic_source | RECORD | ユーザーを最初に獲得したトラフィック ソースの名前。このフィールドは当日テーブルでは使用されません。 |
traffic_source.name | 文字列 | ユーザーを最初に獲得したマーケティング キャンペーンの名前。このフィールドは当日テーブルでは使用されません。 |
traffic_source.medium | 文字列 | ユーザーを最初に獲得したメディアの名前(有料検索、オーガニック検索、メールなど)。このフィールドは当日テーブルでは使用されません。 |
traffic_source.source | 文字列 | ユーザーを最初に獲得したネットワークの名前。このフィールドは当日テーブルでは使用されません。 |
地域 | ||
geo | RECORD | ユーザーの位置情報を格納するレコード。 |
geo.continent | 文字列 | イベントが報告された大陸(IP アドレス ベース)。 |
geo.sub_continent | 文字列 | イベントが報告された亜大陸(IP アドレスベース)。 |
geo.country | 文字列 | イベントが報告された国(IP アドレス ベース)。 |
geo.region | 文字列 | イベントが報告された地域(IP アドレス ベース)。 |
geo.metro | 文字列 | イベントが報告された大都市圏(IP アドレスベース)。 |
geo.city | 文字列 | イベントが報告された都市(IP アドレス ベース)。 |
イベント | ||
event_date | 文字列 | イベントが記録された日付(アプリの登録タイムゾーンにおける日付を YYYYMMDD 形式で示したもの)。 |
event_timestamp | INTEGER | 該当クライアントでイベントが記録された時刻(ミリ秒単位、UTC)。 |
event_previous_timestamp | INTEGER | 該当クライアントで前回イベントが記録された時刻(ミリ秒単位、UTC)。 |
event_name | 文字列 | イベントの名前です。 |
event_params | RECORD | このイベントに関連付けられたパラメータを格納する繰り返しレコード。 |
event_params.key | 文字列 | イベント パラメータのキー。 |
event_params.value | RECORD | イベント パラメータの値を格納するレコード。 |
event_params.value.string_value | 文字列 | イベント パラメータの文字列値。 |
event_params.value.int_value | INTEGER | イベント パラメータの整数値。 |
event_params.value.double_value | FLOAT | イベント パラメータの倍精度値。 |
event_params.value.float_value | FLOAT | イベント パラメータの浮動小数点値。このフィールドは現在使用されていません。 |
event_value_in_usd | FLOAT | イベントの「値」パラメータの通貨換算値(米ドル単位)。 |
event_bundle_sequence_id | INTEGER | これらのイベントをまとめたアップロード用バンドルのシーケンシャル ID。 |
event_server_timestamp_offset | INTEGER | データの収集時とアップロード時のタイムスタンプの間隔(マイクロ秒単位)。 |
ウェブ | ||
web_info | RECORD | ウェブデータの情報のレコード。 |
web_info.hostname | 文字列 | ログに記録されたイベントに関連付けられたホスト名。 |
web_info.browser | 文字列 | ユーザーがコンテンツを閲覧したブラウザ。 |
web_info.browser_version | 文字列 | ユーザーがコンテンツを閲覧したブラウザのバージョン。 |
特定期間のイベントパラメータの取得
冒頭でも書いた通り、特定期間のイベントパラメータを取得することを目標とします。例えば、Youtubeのような動画再生アプリの場合はどの動画が再生されたのか、どのアカウントが再生したかなどのデータが取られていると思います。
掻い摘んだ例として、以下のようなイベントが設定されていたとしましょう:
param A key = “video_id” //動画のID
param B key = “account_id” //再生したユーザーのアカウントID
先ほどのデータスキーマをもう一度見てみましょう。取得したいデータは「イベント」項目の中にあります。
フィールド名 | データ型 | 説明 |
---|---|---|
event_name | 文字列 | イベントの名前です。 |
event_params | RECORD | このイベントに関連付けられたパラメータを格納する繰り返しレコード。 |
event_params.key | 文字列 | イベント パラメータのキー。 |
event_params.value | RECORD | イベント パラメータの値を格納するレコード。 |
event_params.value.string_value | 文字列 | イベント パラメータの文字列値。 |
event_params.value.int_value | INTEGER | イベント パラメータの整数値。 |
event_params.value.double_value | FLOAT | イベント パラメータの倍精度値。 |
event_params.value.float_value | FLOAT | イベント パラメータの浮動小数点値。このフィールドは現在使用されていません。 |
次に、パラメータの情報は全て「event_params」というレコードの中に格納されています。
この「event_params」の中にはさらに
- key //今回の例でいうと「video_id」や「account_id」にあたります。
- value //今回の例でいうと「再生された動画のid」や「再生したユーザーのアカウントid」に当たります。
があり、「value」の中にはそれぞれ
- string_value
- int_value
- double_value
- float_value
が格納されています。これは実際にイベントのパラメータの値の型に合わせて取得する必要があります。
*文字列として送信しているのであればstring_valueになります。
それでは実際のクエリ構文を見ていきましょう。上記の例に当てはめると、以下のようになります:
1 2 3 4 5 6 7 8 |
SELECT (SELECT value.int_value FROM UNNEST(event_params) AS x WHERE x.key = "video_id") AS video_id, (SELECT value.int_value FROM UNNEST(event_params) AS x WHERE x.key = "account_id") AS account_id, FROM `{DATA SET ID}.events_*` WHERE _TABLE_SUFFIX BETWEEN '{YYYYMMDD}' AND '{YYYYMMDD}' AND event_name = 'user_played_video' |
読み砕いていきましょう。
1 |
(SELECT value.int_value FROM UNNEST(event_params) AS x WHERE x.key = "video_id") AS video_id, |
ここでは各イベントパラメータの値をキーごとに取得しています。
UNNEST演算子は配列の要素が1行となる値テーブルを返します。そしてサブクエリでWHEREを使って返ってきたテーブルをフィルタリング出来るので、event_params.keyが「video_id」のint_valueをSELECTしています。
つまり、以下のようなイベントデータがあった場合:
event_name | event_params.key | event_params.value.string_value | event_params.value.int_value | event_params.value.float_value | event_params.value.double_value |
---|---|---|---|---|---|
user_played_video | video_id | null | 3 | null | null |
account_id | null | 77 | null | null |
返ってくる値テーブルは以下のような形になります:
| video_id | account_id |
+——————–+———————+
| 3 | 77 |
+——————–+———————+
続くクエリ構文は説明いらずかもしれませんが、
1 |
FROM `{DATA SET ID}.events_*` |
の「`」が少し特殊で「’」だとエラーになります。以前、コピペでメモ帳などに貼り付けた時に勝手に変換されてエラーになってハマったことがあったので、この部分でエラーが出ている方は公式が出しているクエリのサンプルページ からコピペしてみてください。
イベント以外のデータ
②ではイベントのパラメータのみを取得しましたが、Firebaseが自動で収集しているデータと組み合わせると分析に役立つかもしれません。
-この値はイベントが送信された時のIPアドレスがベースになっているので、基地局の設定次第では位置情報に大きなブレがあったりします。
・プラットフォーム
-iOSやAndroidなど
・デバイスの情報
-デバイスのモデル、ブランド、OSなど
先ほどのクエリ構文に、自動で収集している情報の一部を組み合わせた例が下記です:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
SELECT (SELECT value.int_value FROM UNNEST(event_params) AS x WHERE x.key = "video_id") AS video_id, (SELECT value.int_value FROM UNNEST(event_params) AS x WHERE x.key = "account_id") AS account_id, (SELECT TIMESTAMP_MICROS(event_timestamp)) AS event_time, (SELECT geo.country) AS country, (SELECT geo.city) AS city, (SELECT traffic_source.medium) AS traffic_medium, (SELECT traffic_source.source) AS traffic_source, (SELECT platform) AS platform FROM `{DATA SET ID}.events_*` WHERE _TABLE_SUFFIX BETWEEN '{YYYYMMDD}' AND '{YYYYMMDD}' AND event_name = 'user_played_video' |
クエリの保存
毎回クエリ構文をコピペするのも面倒なので、割と最近クエリの保存機能が追加されました。「実行」ボタンの隣の「クエリを保存」ボタンから名前付きで複数のクエリを保存することができます。
保存したクエリは左の「保存したクエリ」メニューの「個人用クエリ」か「プロジェクトクエリ」から開くことができます。
BigQueryの料金
BigQuery(asia-northeast1)の料金表 は以下です:
オペレーション | 料金 | 詳細 |
---|---|---|
アクティブ ストレージ | $0.023 per GB | 毎月 10 GB まで無料。詳細については、ストレージの料金 をご覧ください。 |
長期保存 | $0.016 per GB | 毎月 10 GB まで無料。詳細については、ストレージの料金 をご覧ください。 |
BigQuery Storage API | Unavailable | BigQuery Storage API は無料枠 に含まれません。 |
ストリーミング挿入 | $0.012 per 200 MB | 挿入に成功した行が課金対象になります。最小サイズ 1 KB で各行が計算されます。詳細については、ストリーミングの料金 をご覧ください。 |
クエリ(オンデマンド) | $8.55 per TB | 毎月 1 TB まで無料。詳細はオンデマンド料金 をご覧ください。 |
クエリ(月定額) | $12,000 per 500 slots | 追加のスロットは 500 スロット単位でご購入いただけます。詳細については、月定額 料金をご覧ください。 |
クエリ(年定額) | $10,200 per 500 slots | 追加のスロットは 500 スロット単位でご購入いただけます。請求は月単位で行われます。詳細については、年定額 料金をご覧ください。 |
毎日大量のデータをクエリしない限りは大体無料枠に収まると思います。
とはいえ、何も確認せずに使い続けると痛い目を見ることも・・・
「まぁ、多分大丈夫だろう」なんて高を括らずデータ処理量に応じた費用を計算することが大事です。
BigQueryにはdry run というオプションが用意されており、実際にクエリを走らせる前に走査バイト数を知ることが出来ます。これで費用の大体の予測は可能ですね。BigQueryの料金面に関しては下記の記事が参考になります。
以上、BigQueryを使って特定期間のイベントparamsを取得する方法でした。少しでもご参考になりましたら幸いです。