【GA4×BigQuery】特定ページからの“本当に進んでいるページ”を正確に把握

このSQLで解決できる課題

LPや商品詳細、料金ページの改善では、ユーザーが“次に”どこへ進んだかを把握するのが近道です。

GA4の標準レポートでもナビゲーション概要は見られますが、自社のKPIに合わせた粒度(特定ページのみ・重複除外・URL正規化・セッション母数に対する遷移率など)まで落とし込むのは難しく、改善会議で「どの導線を強化/削除するか」を即断できないことが多いはず。


本SQLは、GA4の events_* から page_view だけを抽出し、同一ユーザー×セッション内の時系列LEAD() を使って**“次ページ”を決定。

対象の起点ページ(YOUR_TRIGGER_PAGE)を訪れた全セッションの母数と、そこから実際に別ページへ遷移したセッション数遷移先ごと**に集計します。


出力は、起点パス / 遷移先パス / 遷移セッション数 / 起点母数 / 遷移率

これにより「LPからそのままカートに行った割合」「FAQへ逸れてしまう割合」「別商品の詳細に流れてしまう割合」を数字で比較でき、CTA配置の見直しFAQ要点のLP内包無駄な外部リンク削減など、施策に直結する意思決定が可能になります。

実行結果イメージ

-

背景・利用シーン

    • LP改善の優先順位付け:カート・フォームへの直行が低いなら、ファーストビューやCTA配置の見直し。

    • FAQ/ヘルプ流入の最適化:FAQ遷移が多いなら、LP側に要点を前倒しして**“行かなくても済むFAQ”**へ。

    • 商品回遊の導線設計:似た商品へ流れるなら、比較表おすすめの並びを改善。

    • 広告整合性の検証:意図した次ステップに進んでいるか、キーワード/クリエイティブの整合性を確認。

抽出結果からできる議論(会話例)

マーケ担当A: 「LPからカートに直行するのは24%しかないですね。」
分析担当B: 「FAQに10%流れているのが気になります。LPに情報を追記するべきかも。」

マーケ担当A: 「この商品ページに誘導したいのに、別商品の詳細に流れてますね。」
分析担当B: 「一覧ページでの見せ方を変える必要がありそうです。」

分析担当B: 「コンタクトフォームに進む割合が6%しかないですね。」
マーケ担当A: 「ボタン配置を見直したほうが良さそうです。」

マーケ担当A: 「広告経由のユーザーは、意外と商品詳細よりFAQに行ってますね。」
分析担当B: 「LPの説得力が弱い証拠です。改善ポイントが見えてきました。」

マーケ担当A: 「遷移率が高い導線は、そのまま強化したいですね。」
分析担当B: 「逆に低い導線は、思い切って削除するのもアリです。」

SQLコードと解説

-- ============================================================
-- 🚀 ページA → 次ページBの遷移率(セッション単位)
--     手動入力は「★1:期間」「★2:起点ページ」「★3:テーブルパス」だけ!
-- ============================================================

-- ▼ ★1:解析期間を手動で指定(YYYY-MM-DD 形式)
DECLARE start_date STRING DEFAULT '2025-10-01';  -- 解析開始日
DECLARE end_date   STRING DEFAULT '2025-10-・・';  -- 解析終了日

-- ▼ ★2:起点ページの正規表現(正規化後のパスにマッチさせる)
-- 例)'^/contact$'、'^/cars/[^/]+/detail$'、'^/campaign'
DECLARE trigger_path_pattern STRING DEFAULT '^/$';  -- トップページの場合はこれでOK

-- ▼ 内部用(編集不要)
DECLARE sfx_start STRING;
DECLARE sfx_end   STRING;
SET sfx_start = REPLACE(start_date, '-', '');
SET sfx_end   = REPLACE(end_date,   '-', '');

-- ▼ ★3:参照テーブルパス(あなたの環境に一度だけ置換)
--    例)`myproject.analytics_123456789.events_*`
-- ============================================================

-- ① page_viewのみ抽出しURLを正規化(小文字化・ドメイン除去・クエリ除去・末尾スラ削除)
WITH base_events AS (
  SELECT
    user_pseudo_id,
    (SELECT value.int_value FROM UNNEST(event_params) WHERE key = 'ga_session_id') AS ga_session_id,
    event_timestamp,
    -- 元URL(確認用)
    (SELECT value.string_value FROM UNNEST(event_params) WHERE key = 'page_location') AS page_location_raw,
    -- 正規化処理(ドメイン削除 → クエリ削除 → 末尾スラ吸収)
    IF(p != '/' AND RIGHT(p, 1) = '/', SUBSTR(p, 1, LENGTH(p) - 1), p) AS page_path
  FROM (
    SELECT
      user_pseudo_id,
      event_timestamp,
      event_params,
      REGEXP_REPLACE(
        REGEXP_REPLACE(
          LOWER((SELECT value.string_value FROM UNNEST(event_params) WHERE key = 'page_location')),
          r'^https?://[^/]+', ''   -- ドメイン除去
        ),
        r'[\?#].*$', ''             -- クエリ・アンカー除去
      ) AS p,
      (SELECT value.int_value FROM UNNEST(event_params) WHERE key = 'ga_session_id') AS ga_session_id
    FROM `・・・.analytics_・・・.events_*`  -- ★3:ここを環境に合わせて置換
    WHERE event_name = 'page_view'
      AND _TABLE_SUFFIX BETWEEN sfx_start AND sfx_end
  )
  WHERE ga_session_id IS NOT NULL
),

-- ② 同一セッション内の次ページを特定
page_views AS (
  SELECT
    user_pseudo_id,
    ga_session_id,
    event_timestamp,
    page_path,
    LEAD(page_path) OVER (
      PARTITION BY user_pseudo_id, ga_session_id
      ORDER BY event_timestamp
    ) AS next_path
  FROM base_events
),

-- ③ 起点ページを踏んだセッション(母数)
trigger_sessions AS (
  SELECT DISTINCT
    user_pseudo_id,
    ga_session_id
  FROM page_views
  WHERE REGEXP_CONTAINS(page_path, trigger_path_pattern)
),

-- ④ 有効な遷移(直後に別ページへ遷移)
valid_transitions AS (
  SELECT DISTINCT
    pv.user_pseudo_id,
    pv.ga_session_id,
    pv.page_path AS trigger_page_path,
    pv.next_path AS target_page_path
  FROM page_views pv
  JOIN trigger_sessions ts
    ON pv.user_pseudo_id = ts.user_pseudo_id
   AND pv.ga_session_id  = ts.ga_session_id
  WHERE REGEXP_CONTAINS(pv.page_path, trigger_path_pattern)
    AND pv.next_path IS NOT NULL
    AND pv.page_path != pv.next_path
),

-- ⑤ 遷移先ごとのセッション数
transition_counts AS (
  SELECT
    trigger_page_path,
    target_page_path,
    COUNT(DISTINCT ga_session_id) AS transitioned_sessions
  FROM valid_transitions
  GROUP BY trigger_page_path, target_page_path
),

-- ⑥ 起点ページを踏んだユニークセッション数(母数)
trigger_base AS (
  SELECT COUNT(DISTINCT ga_session_id) AS total_trigger_sessions
  FROM trigger_sessions
)

-- ⑦ 出力(母数と遷移率)
SELECT
  tc.trigger_page_path,
  tc.target_page_path,
  tc.transitioned_sessions,
  tb.total_trigger_sessions,
  SAFE_DIVIDE(tc.transitioned_sessions, tb.total_trigger_sessions) AS transition_rate
FROM transition_counts tc
CROSS JOIN trigger_base tb
ORDER BY tc.transitioned_sessions DESC, tc.target_page_path
LIMIT 100;



 

 


確認すべきポイント

    • 対象の起点指定
      YOUR_TRIGGER_PAGEパスで指定(例:/lp/campaign2025)。クエリ差異を吸収したい場合は、前段でクエリ除去+小文字化REGEXP_EXTRACT(LOWER(page_location), r'^https?://[^/]+([^?]+)'))を推奨。
    • 期間とタイムゾーン
      期間フィルタが無いので、必要なら event_date 由来の _TABLE_SUFFIX 条件を追加。Asia/Tokyo集計にするなら TIMESTAMPDATETIME 変換で日付境界を合わせる。

    • セッション粒度の揺れ
      ga_session_id の生成はGA4側ロジック依存。Consentやクロスデバイスでセッション分断が起きる点は前提として共有。

    • 外部/内部リンクの扱い
      外部遷移は次ページが NULL になりやすい(サイト外ログが無い)。内部導線評価に使う前提でOK。

    • ページ階層の統合
      /product/abc/?ref=... など表記ゆれは事前正規化で吸収。末尾スラッシュ大文字小文字も統一を。

    • ランキングの読み方
      遷移率が高い=必ず良いではない。FAQ・利用規約への高遷移は「LP不足」を示唆する場合がある。文脈で解釈を。

    • 深掘り拡張
      “次ページ”ではなく**“n手先”**(LEAD(..., n))を見る、流入別traffic_source.medium)でセグメントするなど拡張可能。

まとめ

このSQLを使うと、「特定ページからユーザーがどこへ進むのか」 を明確に把握できる。

    • 起点ページからの“次の一歩”を、セッション集合の母数と並べて遷移率で比較できる。

    • LPや商品詳細、価格ページで強い導線/弱い導線がはっきりするため、CTA配置・FAQ内包・関連リンクの改善に直結。

    • URL正規化・期間/TZ・セッション粒度を押さえれば、毎週の改善会議で回せる定例レポートのコアになる。

おすすめの記事