【GA4×BigQuery】ランディングごとの「閲覧ページ数(出口まで)」をセッション単位で可視化する

導入(このSQLで解決できる課題)

Webサイトの改善において「ユーザーがどのページから訪問を開始し、その後どれくらいページを見ているか」を把握することは非常に重要です。

特にLP(ランディングページ)は、最初の印象でユーザーの滞在時間や深掘り行動を左右するため、広告効果測定やSEO施策の改善にも直結します。

しかし、GA4の標準レポートでは「ランディングページごとの平均閲覧ページ数」を柔軟に抽出することは難しく、カスタム探索を作り込んでも制限が多いのが現実です。

そこで今回紹介するSQLでは、GA4の生データを用いて「ランディングページごとのセッション数」と「その後に平均何ページ閲覧されたか」を算出できます。

これにより次のような課題を解決できます。

  • どのLPが深いセッションを生み出しているか比較できる

  • 離脱しやすいランディングを特定できる

  • 広告LPの改善優先度を明確化できる

特に広告投資を行う場面では「流入の量」だけでなく「質(深掘り行動)」を可視化できる点が強みです。

2. 実行結果イメージ

読み方:

  • sessions_count…そのランディングから始まったセッション数

  • avg_pages_viewed_before_exit…ランディングから同一セッション内で閲覧されたページ数の平均(高いほど深く回遊)

3. 背景・利用シーン

このSQLは以下のような実務シーンで役立ちます。

  • 広告LPの改善効果測定
    「広告で流入したユーザーが、どのくらいサイトを深く見たか」を定量化し、媒体別やクリエイティブ別の比較に活用できる。

  • SEO記事の質の評価
    流入の多い記事が「他ページ閲覧につながっているか」を把握でき、ナビゲーションや内部リンクの改善余地を見つけやすい。

  • 直帰率の補完指標
    直帰率だけでなく「何ページ見たか」を把握することで、単ページ完結型コンテンツか、回遊導線が不足しているのかを切り分け可能。

  • コンテンツ戦略の優先順位づけ
    回遊性の高いランディングを強化し、弱いランディングは改善施策の対象にできる。

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

マーケ担当A: 「この記事から入った人は3ページ以上見てますね。」
分析担当B: 「内部リンクが機能している証拠です。関連記事をもっと増やしましょう。」

分析担当B: 「TOPページはセッション数は多いけど、平均1.4ページで浅いですね。」
マーケ担当A: 「初回体験が弱い証拠です。ファーストビューを改善すべきかも。」

マーケ担当A: 「広告LPは平均2.8ページでした。」
分析担当B: 「最低限の効果は出てますが、フォーム導線をもっと強調したほうが良さそうです。」

分析担当B: 「商品ページ直着だと平均1.9ページ止まりですね。」
マーケ担当A: 「スペック比較ページへの導線を増やせば、回遊が伸びるかもしれません。」

マーケ担当A: 「記事からの流入は数は少ないけど、滞在が深い。」
分析担当B: 「ナーチャリングに効いてます。SEO記事をもっと投資対象にすべきですね。」

    4. SQLコード(コメント付き分解)

    -- ▼ テーブルはあなたの環境に置換してください:`PROJECT.DATASET.events_*`
    WITH session_data AS (
      SELECT
        user_pseudo_id,
        -- セッションID(user_pseudo_id + ga_session_id)
        CONCAT(
          CAST(user_pseudo_id AS STRING), "_",
          CAST((SELECT ep.value.int_value
                FROM UNNEST(event_params) ep
                WHERE ep.key = 'ga_session_id') AS STRING)
        ) AS session_id,
    
        -- 完全URL(必要に応じてパス化・正規化は「注意点」を参照)
        (SELECT ep.value.string_value
         FROM UNNEST(event_params) ep
         WHERE ep.key = 'page_location') AS page_location,
    
        event_timestamp,
    
        -- セッション内の page_view 順(最初=1)
        ROW_NUMBER() OVER (
          PARTITION BY user_pseudo_id,
                       CONCAT(
                         CAST(user_pseudo_id AS STRING), "_",
                         CAST((SELECT ep.value.int_value
                               FROM UNNEST(event_params) ep
                               WHERE ep.key = 'ga_session_id') AS STRING)
                       )
          ORDER BY event_timestamp
        ) AS page_view_rank
      FROM
        `PROJECT.DATASET.events_*`
      WHERE
        _TABLE_SUFFIX BETWEEN FORMAT_DATE('%Y%m%d', DATE_ADD(CURRENT_DATE(), INTERVAL -300 DAY))
                          AND FORMAT_DATE('%Y%m%d', CURRENT_DATE())
        AND event_name = 'page_view'
    ),
    
    -- ★ セッションの「最初の」page_view をランディングとして1行に固定
    landing_pages AS (
      SELECT
        user_pseudo_id,
        session_id,
        page_location AS landing_page,
        event_timestamp AS landing_timestamp
      FROM session_data
      QUALIFY page_view_rank = 1
    ),
    
    -- ランディング時刻以降のそのセッション内 page_view をカウント
    page_views AS (
      SELECT
        sd.user_pseudo_id,
        sd.session_id,
        lp.landing_page,
        COUNT(*) AS pages_viewed_before_exit
      FROM session_data sd
      JOIN landing_pages lp
        ON sd.user_pseudo_id = lp.user_pseudo_id
       AND sd.session_id     = lp.session_id
       AND sd.event_timestamp >= lp.landing_timestamp
      GROUP BY
        sd.user_pseudo_id, sd.session_id, lp.landing_page
    )
    
    -- ランディング単位に集計
    SELECT
      pv.landing_page,
      COUNT(*) AS sessions_count,
      AVG(pv.pages_viewed_before_exit) AS avg_pages_viewed_before_exit
    FROM page_views pv
    GROUP BY pv.landing_page
    ORDER BY sessions_count DESC;
    

    各パートの役割

    • session_data:セッション内のpage_viewに連番を付与

    • landing_pagesQUALIFY page_view_rank=1ランディングを一意に取得

    • page_views:ランディング時刻以降の閲覧数をセッション単位でカウント

    • 最終SELECT:ランディングURLごとにセッション数と平均閲覧ページ数を算出

    確認すべきポイント

    • URLの正規化
      現状はフルURLをそのまま使用。REGEXP_REPLACE でドメイン除去し、パス単位で集計するのがおすすめ。

    • 期間の調整
      _TABLE_SUFFIX で「直近300日」を指定しているが、分析目的に応じて変更可能。

    • 単ページ完結コンテンツの解釈
      平均ページ数が低い=悪いとは限らない。単ページで完結するLPやブログ記事も存在する。

    • 広告流入との組み合わせ
      traffic_source.mediumcampaign をJOINすると、媒体別に深さ比較が可能。

    6. まとめ(SQLの効果と使いどころ)

    このSQLは、ランディングページ別に「セッション数」と「平均ページ閲覧数」を明確に示すことができます。

    • LP改善の優先度づけ

    • SEO記事の評価

    • 離脱要因の特定

    といった実務に直結する分析が可能になり、単なる「直帰率」よりも実態に即した改善施策を導き出せます。

     

    おすすめの記事