これはなに
BigQueryでFirebase Analyticsイベントをファネル分析する上で、これをwalkthroughしたメモ。
デモアプリ
- 分析事、実務プロジェクトでやってもよいが、リアルに課金が発生するのを気にしてしまうのと、個人プロジェクトでは分析対象のデータがそもそも揃えるのが難しい。
- sandboxな環境で分析事を試せる十分なデータセットがあるプロジェクト、Google先生が公開してくれているFirebaseデモプロジェクトがある。親切。
- デモプロジェクトのiOSアプリでは、Flood-It!という実在するパズルゲームアプリのアナリティクスデータをつかって分析を行う
指定された手数以内で盤面を一色に塗りつぶすパズルゲームです
ゴール
no_more_extra_steps
を受けたユーザの内、どれだけspend_virtual_currency
につながったか、を知りたい- 2stepファネルをつくる
カダイ
- はFirebase ConsoleでつくるとOpen Funnelになること(以下画像は上記ブログ記事から拝借したもの)
- 実際にデモプロジェクトのFirebase Consoleでファネルをつくろうとしたが、現在は権限が制限されているのか、新規の目標到達プロセスの作成ができなかった..
- ファネルをみると、step1よりstep2の方が大きい値になってしまっている。step1に関係なくstep2イベントがカウントされている。
- いわゆるオープンファネルになってしまっている。いまつくりたいのはクローズドファネル。
- ちなみに、GA4ではクローズドな目標到達プロセスも作成できる(後述のイベント間の時間区間指定もできるし、イベントパラメータ指定などもできる。GUIポチポチで完結するので便利。)
- 今回はFirebase EventsログをBigQueryで弄ぶ主旨なのでBQでやっていく
BigQueryでどうやる
以降はFlood-It!アプリイベントのBigQueryデータセットのクエリエディタで叩いて進めていく
1.) まずは1日分のデータでユーザIDベースで発生イベントを時系列に出してみると
SELECT
event_name,
user_pseudo_id,
event_timestamp
FROM
`firebase-public-project.analytics_153293282.events_20180720`
ORDER BY
user_pseudo_id, event_timestamp
LIMIT
1000
- こんなふうに
2.) 次に、no_more_extra_stepsとspend_virtual_currencyイベントに絞ってみると、
SELECT
event_name, user_pseudo_id , event_timestamp
FROM
`firebase-public-project.analytics_153293282.events_20180720`
WHERE
(event_name = "no_more_extra_steps" OR event_name = "spend_virtual_currency")
ORDER BY
user_pseudo_id, event_timestamp
- こんなふうに
- クエリ結果の4,5行目をみると、たしかに同一ユーザによってno_more_extra_steps -> spend_virtual_currencyの順でイベント発生してることがわかる
- ので、こういうかんじのをいい感じに抽出していく
- 「次のアレがアレ」という条件がほしい
3.) LEADウィンドウ関数をつかって、「次の結果レコード」についての条件を追加する
SELECT
event_name,
user_pseudo_id,
event_timestamp,
-- PARTITION BYで擬似ユーザID毎のグループに分ける(でないと同一ユーザによる「次」が担保できない)
-- ORDER BYで時系列的な並びを担保する
LEAD(event_name, 1) OVER (PARTITION BY user_pseudo_id ORDER BY event_timestamp) AS next_event
FROM
`firebase-public-project.analytics_153293282.events_20180720`
WHERE
(event_name = "no_more_extra_steps" OR event_name = "spend_virtual_currency")
ORDER BY
user_pseudo_id, event_timestamp
- こんなふうに
- 「次のイベント」をnext_eventとして抽出できるようになったので
- これに対してファネル条件追加してやればよい
4.) no_more_extra_steps
イベントの直後にspend_virtual_currency
イベントが来るケースをカウントするクエリ
SELECT
COUNTIF (event_name = "no_more_extra_steps") AS funnel_1_total,
COUNTIF (event_name = "no_more_extra_steps" AND next_event = "spend_virtual_currency") AS funnel_2_total
FROM (
SELECT
event_name,
user_pseudo_id,
event_timestamp,
LEAD(event_name, 1) OVER (PARTITION BY user_pseudo_id ORDER BY event_timestamp) AS next_event
FROM
`firebase-public-project.analytics_153293282.events_20180720`
WHERE
(event_name = "no_more_extra_steps" OR event_name = "spend_virtual_currency")
ORDER BY
user_pseudo_id, event_timestamp
)
- こんなふうに
- 25回のno_more_extra_stepsの内22回がspend_virtual_currencyっぽい
5.) ユーザ数ベースでみると、
SELECT
COUNT(DISTINCT funnel_1_total) AS f1_users,
COUNT(DISTINCT funnel_2_total) AS f2_users
FROM (
SELECT
IF (event_name = "no_more_extra_steps", user_pseudo_id, NULL) AS funnel_1_total,
IF (event_name = "no_more_extra_steps" AND next_event = "spend_virtual_currency", user_pseudo_id, NULL) AS funnel_2_total
FROM (
SELECT
event_name,
user_pseudo_id,
event_timestamp,
LEAD(event_name, 1) OVER (PARTITION BY user_pseudo_id ORDER BY event_timestamp) AS next_event
FROM
`firebase-public-project.analytics_153293282.events_20180720`
WHERE
(event_name = "no_more_extra_steps" OR event_name = "spend_virtual_currency")
ORDER BY
user_pseudo_id, event_timestamp
)
)
- こんなふうに
6.) この抽出には問題がある。
- たとえば
no_more_extra_steps
後何時間か経過した後にspend_virtual_currency
イベントが発生していた場合 - この場合、
no_more_extra_steps
が直接spend_virtual_currency
に寄与したかというと考えにくい。 - ので、こうしたイベント間の時間経過も考慮したフィルタ条件を書く必要がある(かもしれない。実際は要件による。)
- ここでは、1分以内に後続のファネルイベントが起きた場合、を条件に追加したいとする
7.) 「次のイベントのtimestamp」カラムをSevent_name同様追加した上で、timestampの差の範囲指定条件を追加する
SELECT
COUNT(DISTINCT funnel_1) AS f1_users,
COUNT(DISTINCT funnel_2) AS f2_users
FROM (
SELECT
IF (event_name = "no_more_extra_steps", user_pseudo_id, NULL) AS funnel_1,
IF (
event_name = "no_more_extra_steps" AND
next_event = "spend_virtual_currency" AND
-- `no_more_extra_steps`の後1分以内に`spend_virtual_currency`イベントが発生したかどうか
-- timestampはmicrosecond単位なので1000 * 1000
next_timestamp - event_timestamp < 60 * 1000 * 1000,
user_pseudo_id, NULL) AS funnel_2
FROM (
SELECT
event_name,
user_pseudo_id,
event_timestamp,
LEAD(event_name, 1) OVER (PARTITION BY user_pseudo_id ORDER BY event_timestamp) AS next_event,
-- next_timestampを追加
LEAD(event_timestamp, 1) OVER (PARTITION BY user_pseudo_id ORDER BY event_timestamp) AS next_timestamp
FROM
`firebase-public-project.analytics_153293282.events_20180720`
WHERE
(event_name = "no_more_extra_steps" OR event_name = "spend_virtual_currency")
ORDER BY
user_pseudo_id, event_timestamp
)
)
- こんなふうに
- イベント時間区間指定なしの場合より減ってるが、こっちがリアルな数値。
8.) 1ヶ月分のデータを日別で取得してデータポータルで可視化してみる
SELECT
day,
COUNT(DISTINCT funnel_1) AS f1_users,
COUNT(DISTINCT funnel_2) AS f2_users
FROM (
SELECT
-- 日別をとる
FORMAT_TIMESTAMP('%F', TIMESTAMP_MICROS(event_timestamp)) as day,
IF (event_name = "no_more_extra_steps", user_pseudo_id, NULL) AS funnel_1,
IF (
event_name = "no_more_extra_steps" AND
next_event = "spend_virtual_currency" AND
next_timestamp - event_timestamp < 60 * 1000 * 1000,
user_pseudo_id, NULL) AS funnel_2
FROM (
SELECT
event_name,
user_pseudo_id,
event_timestamp,
LEAD(event_name, 1) OVER (PARTITION BY user_pseudo_id ORDER BY event_timestamp) AS next_event,
LEAD(event_timestamp, 1) OVER (PARTITION BY user_pseudo_id ORDER BY event_timestamp) AS next_timestamp
FROM
`firebase-public-project.analytics_153293282.events_*`
WHERE
(event_name = "no_more_extra_steps" OR event_name = "spend_virtual_currency")
AND _TABLE_SUFFIX BETWEEN '20180629' AND '20180728'
ORDER BY
user_pseudo_id, event_timestamp
)
)
GROUP BY
day
ORDER BY
day
- こんなふうに
- せっかくなのでデータポータルに展開して
- 可視化
以上、BigQueryでFirebase Analyticsイベントの2stepなクローズドファネルやっていきでした。