診断系のページを作っていると、page_view だけではほとんど何も分からない場面があります。
ラブキャラ診断64という診断ページを実装したときも、単に「ページが何回見られたか」では足りませんでした。
見たかったのは、次のようなことです。
- どの入口から診断に入ったのか
- 何問目あたりで離脱しているのか
- 未回答のまま次へ進もうとしている人が多いのか
- 診断完了後、結果ページやシェア導線まで進んでいるのか
- 新しい診断を追加したことで、サイト全体の滞在時間は増えたのか
- それとも、既存のメイン診断の時間を新しい診断が奪っただけなのか
対象ページはこちらです。
この記事では、診断ページのGA4イベント設計と、GA4のカスタムディメンション設定をCodexから自動化するために作った ga4-ops Skill について書きます。
page_viewでは診断ファネルを見られない
診断ページは、普通の記事ページというより小さなプロダクトのファネルに近いです。
今回の実装では、ユーザーの状態遷移を次のように分けました。
Entry -> Start -> Answer -> Complete -> Result action
└-> Blocked / Exit
代表的なイベントは次の通りです。
love_character64_entry_attributed
love_character64_quiz_started
love_character64_answer_selected
love_character64_quiz_page_advanced
love_character64_quiz_blocked
love_character64_quiz_completed
love_character64_quiz_exited
love_character64_result_viewed
love_character64_result_action_clicked
ここで大事なのは、イベント名を増やすこと自体ではありません。
quiz_started と quiz_completed だけを送っても、「どこで詰まったのか」「なぜ完了しなかったのか」は見えません。未回答でブロックされたのか、途中でページを閉じたのか、結果ページまでは見たがシェアしなかったのかを分ける必要があります。
パラメータ設計で分析できる粒度を決める
イベント名だけでは、後から切り分けできません。
そこで、共通パラメータをそろえました。
{
flow_id: "love_character64_quiz",
event_category: "love_character64",
action,
action_status,
locale,
page_type,
source_page,
source_action,
ui_section,
}
診断中のイベントでは、質問や進捗に関する情報を入れます。
{
question_id,
question_index,
question_axis,
question_kind,
question_count,
answered_count,
answer_value,
}
完了時や結果ページでは、結果タイプを分析できるようにします。
{
result_code,
result_type1,
result_type2,
duration_ms,
share_mode,
}
一方で、何でも送るわけではありません。
ユーザーID、メールアドレス、自由入力テキスト、長すぎるURL、秒単位の細かすぎる値などは、GA4の分析にも向きませんし、プライバシーや高カーディナリティの問題も出ます。
page_type、ui_section、source_action、result_code のように、後から比較・集計に使える粒度に絞るほうが扱いやすくなります。
新しい診断は「増分」か「分流」か
既にメインの診断があるサイトに新しい診断を追加した場合、新しい診断の完了数だけを見ても判断を誤ります。
本当に知りたいのは、次の区別です。
main_only メイン診断だけを開始・完了した
love64_only 新しい64タイプ診断だけを開始・完了した
both_flows 両方の診断に触れた
この分類のために、各診断フローには flow_id を持たせています。
kuma_love_type_quiz
love_character64_quiz
この分類ができると、たとえば次のような見方ができます。
| 見たいこと | 見るポイント |
|---|---|
| 新しい診断が回遊を増やしたか |
both_flows の平均エンゲージメント時間や完了率を見る |
| 既存診断から時間を奪っただけか |
main_only が減り、love64_only だけが増えていないかを見る |
| 新しい検索入口を作れているか | 検索流入の love64_only が増えているかを見る |
| メイン診断に悪影響が出ていないか | サイト全体の滞在時間だけでなく、メイン診断の完了率も見る |
ここで必要になるのが、flow_id だけではありません。
source_page、source_action、entry_source_type、page_type も一緒に持っておくと、メイン診断の結果ページから64タイプ診断へ移動したのか、検索から直接64タイプ診断へ入ったのかを分けられます。
前者はサイト内回遊の増加かもしれません。後者は新しい検索入口の獲得かもしれません。
もちろん、GA4だけで因果関係を完全に証明できるわけではありません。正確に見るなら、リリース前後の期間比較、流入チャネル別の比較、必要に応じてBigQuery Exportでのセッション単位分析も検討します。
ただ、flow_id と入口・導線パラメータを最初から入れておけば、「新機能を入れたら数字が増えた気がする」で終わらず、増分なのか分流なのかを後から検証しやすくなります。
重要イベントを落とさないためにやったこと
診断ページでは、途中離脱と診断完了の扱いが特に重要でした。
途中離脱は、ユーザーがタブを閉じたり別ページへ移動したりするため、通常のクリックイベントだけでは拾えません。
そこで、回答済みでまだ完了していない場合は、pagehide や visibilitychange をきっかけに love_character64_quiz_exited を送るようにしました。
{
action: "exit_quiz",
action_status: "abandoned",
answered_count,
question_count,
source_action: "pagehide",
transport_type: "beacon",
}
診断完了時は、結果ページへ遷移する前にイベントを送ります。
gtag("event", "love_character64_quiz_completed", {
result_code: nextResult.typeCode,
duration_ms,
event_callback: () => {
window.location.assign(resultUrl);
},
event_timeout: 800,
});
完全に保証できるわけではありませんが、完了イベントのような重要なシグナルは、ページ遷移で落ちにくい形にしておく価値があります。
GA4で分析できる形にする
GA4では、イベントパラメータを送っただけでは、すぐに自由にレポートで分解できるわけではありません。
分析に使うパラメータは、カスタムディメンションやカスタムメトリクスとして登録する必要があります。
今回の設計では、次のように考えました。
| 分析したいこと | 主なパラメータ | GA4側の扱い |
|---|---|---|
| 診断フロー別に見る | flow_id |
event-scoped custom dimension |
| 入口や導線を見る |
entry_source_type, source_page, source_action
|
event-scoped custom dimension |
| ページやUI位置で見る |
page_type, ui_section
|
event-scoped custom dimension |
| 質問単位の詰まりを見る |
question_axis, question_kind
|
event-scoped custom dimension |
| 結果タイプ別に見る |
result_code, result_type1, result_type2
|
event-scoped custom dimension |
| シェア行動を見る | share_mode |
event-scoped custom dimension |
| 進捗や所要時間を見る |
answered_count, question_count, missing_count, duration_ms
|
custom metric候補 |
ここまで含めて設計しないと、「イベントは送っているのに、GA4の画面で知りたい切り口が見られない」という状態になります。
ga4-opsでGA4設定を自動化する
イベントを増やすたびにGA4の管理画面を開き、カスタムディメンションを1つずつ追加するのは地味に面倒です。
プロジェクトが増えると、あるサイトでは source_page が登録されているが、別のサイトでは忘れている、というズレも起きます。
そこで、GA4の運用をCodexから扱えるようにするために ga4-ops という Skill を作りました。
ga4-ops は、GA4 Admin APIを使って、CodexからGA4まわりの運用を実行できるようにした Skill です。イベント設計そのものを置き換えるものではなく、GA4側の設定確認や登録を自動化するためのものです。
主に次のようなことをできます。
- GA4プロパティの作成
- Web data stream の作成
-
GOOGLE_ANALYTICS_IDとGOOGLE_ANALYTICS_PROPERTY_IDの.env書き戻し - 本番サイトにGA4が入っているかの検証
- GA4のデータ取得チェック
- カスタムディメンション / カスタムメトリクスの一覧取得
- 必要なカスタム定義の登録
たとえば、対象プロパティのカスタム定義を確認できます。
npx tsx ~/.codex/skills/ga4-ops/scripts/ga4.ts list-custom-definitions \
--property-id=GA4_PROPERTY_ID
プリセット化した定義は、dry-runで確認してから登録できます。
npx tsx ~/.codex/skills/ga4-ops/scripts/ga4.ts register-custom-definitions \
--property-id=GA4_PROPERTY_ID \
--preset=saas-behavior \
--dry-run=true
実運用では、イベント設計側で「このパラメータは分析に必要なのでカスタムディメンションにする」と決め、ga4-ops 側で登録状況を確認して、プリセットに落とし込んだ定義を追加する流れにしています。
この分担にしておくと、Codexに作業を依頼するときも「イベントを追加しただけで終わり」になりにくくなります。
イベントを追加するなら、同時に「GA4でどう分析するのか」「必要なカスタム定義は登録されているのか」まで確認する、というルールにできます。
まとめ
診断ページのGA4設計では、ページビューよりも、ユーザーの状態遷移をどうイベント化するかが重要でした。
今回の実装では、開始、回答、未回答ブロック、ページ進行、完了、離脱、結果閲覧、共有アクションを分けてイベント化しました。
さらに、flow_id、source_page、source_action、entry_source_type を持たせることで、新しい診断がサイト全体の回遊を増やしたのか、それとも既存診断から時間を移しただけなのかを後から検証しやすくしています。
ただし、イベントパラメータは送るだけでは不十分です。分析に使うパラメータは、GA4側でカスタムディメンションやカスタムメトリクスとして登録する必要があります。
その作業を毎回手作業で行うと漏れやすいため、ga4-ops Skill を作り、CodexからGA4 Admin API経由で設定確認や追加をできるようにしました。
小さな診断ページでも、イベント設計とGA4運用を最初からセットで考えておくと、リリース後に「見たい数字が見られない」という問題をかなり減らせます。



