GA4の計測検証をBigQueryを使って行う

概要
GA4の計測の検証はBigQueryエクスポートを使って行うのが普通になる。検証の方法にはいくつかあるのだが、ほかの方法だと欠点がある。 リアルタイムレポートではイベントが発生し、パラメータに値が入ってきているのはわかるが、どのイベントでどのパラメータの値が入っているかまではわからない。DebugViewは有効化しないと使えない。
BigQueryエクスポートを使うとすべてのサイト訪問に対して計測して数分以内には各パケット(イベント)でどのパラメータにどの値が入っているかがわかるし、詳細な検証ができる。 GA4のBigQueryデータはパラメータやユーザープロパティがネストされているため、クエリでは毎回それをフラット化する手続きをする必要があり、やや面倒。 検証の目的に合わせて使うクエリがパターン化されるのでこの記事ではそれを紹介する。
検証用のおすすめ設定
ログのストリーミング出力設定
GA4のBigQueryエクスポート設定でログ出力をストリーミングにする。これを有効にすることでイベント発生から数分以内にログがBigQueryに取り込まれる。この指定をしないと1日1回しかデータが取り込まれず、翌日の朝にならないと検証ができない。設定方法は以下の「頻度」の「ストリーミング」のチェックを入れる。
計測のバージョン番号をパラメータ設定する
送信する変数(イベントパラメータ、ユーザープロパティ)をバージョン管理するといい。 イベントパラメータに現在の設定のバージョン番号を記録し、全イベントでそれを送る。 GTMで送信するパラメータ/ユーザープロパティを変更する都度、バージョンを更新する。 計測された値がどの設定によるものなのか、簡単に照合できる。
全イベントで共通して送るのでイベントタグでなく設定タグに入れておく。
計測バージョン番号の確認
各計測バージョンがいつからいつまで計測されていたのか、計測されたイベントの数(行数)を確認する
select
p.value.string_value v_name,
min(timestamp_micros(event_timestamp)) min_time,
max(timestamp_micros(event_timestamp)) max_time,
count(0) n_events
from `prj.analytics_99999999.events_*` t1, unnest(event_params) p
where p.key = 'config_version'
group by 1
order by 2 desc

ページビューIDについて
同じページビューで発生したイベントをグルーピングするためのIDとして、GA4のBigQueryエクスポートにはbatch_page_idが含まれている。同じページビューで発生したイベントはこの値が同じになるため、「あるページでバナーを閲覧→そのバナーをクリックした」などの行動を把握できる。
以前はカスタムのページビューIDをGTMで設定する必要があったが、batch_page_idがデフォルトで計測されるようになったため、通常はこちらを使えばよい。
ページの読み込み開始タイムスタンプをパラメータ設定する
ページの読み込み開始からイベント発生までどのくらい時間が経過したのか、検証の観点からもユーザ行動把握の観点からも必要である。
イベント発生のタイムスタンプは常に計測される(event_timestamp)が、経過時間の起点としてページの読み込み開始タイムスタンプをイベントパラメータに入れておくと、その差分からイベント発生までにかかった時間がわかる。
ブラウザに格納されているページの読み込み処理のタイムスタンプにはいろいろ候補があるが、Navigation Timing API Level 2のPerformanceNavigationTimingを使うのがよい。
function(){
var entries = performance.getEntriesByType('navigation');
if (entries.length > 0) {
return Math.round(entries[0].startTime + performance.timeOrigin);
}
return null;
}
そのままGTMのカスタムJavaScript変数として登録すればいい。
計測されているパラメータ数を見る
イベントごとに計測されているパラメータの種類を一覧にする
select
event_name,
p.key key,
count(0) cnt
from `prj.analytics_99999999.events_*`, unnest(event_params) p
group by 1,2
order by 1,2
;

ユーザープロパティの場合はunnest(event_params)をunnest(user_properties)に書き換えればいい。これは以下すべて共通。
select
event_name,
p.key key,
count(0) cnt
from `prj.analytics_99999999.events_*`, unnest(user_properties) p
group by 1,2
order by 1,2
;
unnest(event_params)ですべてのパラメータを展開する。イベント数×パラメータ数の行が生成される。この結果をLooker Studioにエクスポートするとピボットテーブルにできる。
バージョン番号別に
select
(select p2.value.string_value from unnest(event_params) p2 where p2.key = 'config_version') config_version,
event_name,
p.key key,
count(0) cnt
from `prj.analytics_99999999.events_*`, unnest(event_params) p
group by 1,2,3
order by 1,2,3
config_versionの列が追加になる。
(高度)BigQueryだけでピボットテーブル化
パラメータ名が英数字だけの場合はBigQuery Scriptingを使ってBigQueryだけでもピボットテーブルを生成できる。このような感じになる。
イベントごとに計測されているパラメータの種類を型別にカウント
想定した型で計測されているかどうかを見る
select
(select p2.value.string_value from unnest(event_params) p2 where p2.key = 'config_version') config_version,
event_name,
p.key key,
count(0) cnt,
sum(case when p.value.string_value is not null then 1 else 0 end) cnt_string,
sum(case when p.value.int_value is not null then 1 else 0 end) cnt_int,
sum(case when p.value.float_value is not null then 1 else 0 end) cnt_float,
sum(case when p.value.double_value is not null then 1 else 0 end) cnt_double
from `prj.analytics_99999999.events_*`, unnest(event_params) p
group by 1,2,3
order by 1,2,3
;

パラメータの値を確認する
イベント名やパラメータ名を絞り込んでパラメータの値を確認する
select
user_pseudo_id,
timestamp_micros(event_timestamp) event_timestamp,
p.key,
p.value.string_value,
p.value.int_value,
p.value.double_value
from `prj.analytics_99999999.events_*`, unnest(event_params) p
where event_name = 'page_view' -- イベント名で絞り込み
and (p.key like 'number%' or p.key like 'string%') -- パラメータ名で絞り込み
order by user_pseudo_id, event_timestamp, key
;

イベントに対するIDがないため、ユーザの識別子(user_pseudo_id)とタイムスタンプの組み合わせをイベントのIDとみなして集約している。
これをLooker Studioにエクスポートすると見やすい形になる。
(高度)バージョン番号で絞り込む場合
やや面倒だが、特定のバージョン番号のイベントが発生したuser_pseudo_idとタイムスタンプを抽出し、それにマッチする行のみ抽出するというロジックにしている。
with t1 as (
select distinct
user_pseudo_id,
event_timestamp
from `prj.analytics_99999999.events_*`, unnest(event_params) p2
where p2.key = 'string001' and p2.value.string_value = '000-num70-str70-v1'
), t3 as (
select
user_pseudo_id,
timestamp_micros(event_timestamp) event_timestamp,
p.key,
p.value.string_value,
p.value.int_value,
p.value.double_value
from `prj.analytics_99999999.events_*` t2, unnest(event_params) p
inner join t1 using (user_pseudo_id, event_timestamp)
where event_name = 'page_view' -- イベント名で絞り込み
and (p.key like 'number%' or p.key like 'string%') -- パラメータ名で絞り込み
)
select * from t3
order by user_pseudo_id, event_timestamp, key
;
t1とt2をinner joinすることで絞り込んでいる。
バージョン番号で絞り込んでユーザープロパティの一覧を表示する場合は以下のように書き換えればいい
from `prj.analytics_99999999.events_*` t2, unnest(event_params) p
inner join t1 using (user_pseudo_id, event_timestamp)
where event_name = 'page_view' -- イベント名で絞り込み
and (p.key like 'number%' or p.key like 'string%') -- パラメータ名で絞り込み
↓
from `prj.analytics_99999999.events_*` t2, unnest(user_properties) p
inner join t1 using (user_pseudo_id, event_timestamp)
where event_name = 'page_view' -- イベント名で絞り込む場合
(高度)BigQueryだけでピボットテーブル化
上の結果をLooker Studioに出力してピボットテーブルを作るのがおすすめだが、こちらもBigQueryだけでピボットテーブル化することもできる。
まさにユーザーエクスプローラのようになる。数値型の変数もstringに統一している(同じ列で複数の型が混在することはNGのため、同じパラメータで型は合わせる必要がある)
- [2021年1月6日公開]
- [2021年1月12日修正]
