GA4

【GA4 SQL】ページ単位のエンゲージメント分析

GA4において「エンゲージメント」という概念が取り入れられた。この「エンゲージメント」は一般的な用語としても使われ、GA4の指標の中にも「エンゲージメント」といった用語が付くものが多く、それぞれの「エンゲージメント」の付く指標の違いを理解しておく必要がある。また、この理解がないとコンテンツ単位のエンゲージメント分析をする際に間違った解釈をしてしまうこともあるため、先に「エンゲージメント」とは?の解説から入る必要がある。ここでいう「ページ」とは「コンテンツ」のことを指し、両者を同じ意味として扱う。

「エンゲージメント」の整理

GA4における「エンゲージメント」とは、時間のエンゲージメントと、肯定的なアクションについてのエンゲージメントに分けると理解しやすくなる。前者は「ユーザーエンゲージメント」と呼ばれる指標で、探索における説明では「サイトまたはアプリがユーザーのデバイスのフォアグラウンドで動作している時間の合計(秒)です」と表記される時間の値である。後者は肯定的なアクションのエンゲージメントのいずれかが発生した場合に、セッション単位で「エンゲージメントのあったセッション数」とカウントされる指標となる。肯定的なアクションとは「10秒を超えたサイト閲覧」「コンバージョン イベントが発生」「2回以上のページビューの発生」の3つを指す。

ざっくりまとめてしまうと、「ユーザーエンゲージメント」という時間的概念と、いずれかの肯定的なアクションを起こしたエンゲージメントを含むセッションが「エンゲージメントのあったセッション数」としてカウントされる指標となる。この両者は別物であり、この2つを2軸で整理すると理解がしやすくなる。

ページにエンゲージメントを適用することは可能か?

GA4の「探索」で「エンゲージのあったセッション数」や「エンゲージメント率」が選択できるため、これにディメンションに「ページ ロケーション」を選択すれば、ページごとのエンゲージメント率を出せるかと思われるかもしれないが、これはできない。

間違った「エンゲージメントの高いコンテンツの分析」

一見すると、ページごとのエンゲージメント率を正しく可視化できているように見えるかもしれないが、これは意図した結果とはなっていない。なぜか?

求めたい結果を得るためにはスコープの範囲を合わせる必要があるが、このケースでは「ページ ロケーション」のページに対して、セッション単位で計測される「エンゲージのあったセッション数」を掛け合わせているため、正しい計算ができていない。「エンゲージのあったセッション数」は、session_startイベントのsession_engagedパラメータの数値を集計したものであり、エンゲージメントのあったセッションでは、後続のイベントは「10秒以上の閲覧」の有無に関わらずsession_engagedパラメータには1が付く。そのため、ディメンションのページロケーションとエンゲージのあったセッション数の指標を掛け合わせてもページ単位のエンゲージメント率は算出できないし、そもそも、探索上でそのような組み合わせは表示・可視化できない。

また、GA4におけるエンゲージメントの条件である「CVの発生」と「2ページ目の遷移」もセッション単位での集計で成り立っているため、これをページと組み合わせることはできない。論理的に破綻する。

結果、探索においてコンテンツ単位・ページ単位のエンゲージメント率を算出することはできない。

BigQueryを活用したページ単位のエンゲージメント分析

BigQueryを活用することでページスコープの集計が可能になるため、ページ単位(コンテンツ)の分析が可能になる。また、BigQueryを活用することで「エンゲージメント」の条件もカスタマイズすることも可能になる。というよりも、ページ単位の分析では、そのままセッション単位である「エンゲージメント」の条件を当てはめることはできないため、カスタマイズする必要がある。

ページ単位「30秒以上の閲覧」でエンゲージメントとするクエリ

CREATE TEMP FUNCTION date_from() RETURNS STRING AS ('20240401');

WITH
  ENG_Time AS (
    SELECT
      ymd,
      page_location,
      SUM(_flag_eng) AS _flag_eng,
      SUM(_cnt_record) AS _cnt_record,
      SUM(_flag_eng) / SUM(_cnt_record) AS rate_eng
    FROM (
      SELECT
        ymd,
        page_location,
        batch_page_id,
        SUM(FLOOR(SAFE_DIVIDE(COALESCE(_engagement_time_msec, 0), 1000))) AS _engagement_time_seconds,
        IF(SUM(FLOOR(SAFE_DIVIDE(COALESCE(_engagement_time_msec, 0), 1000))) > 30, 1,0) AS _flag_eng,
        1 AS _cnt_record
      FROM (
        SELECT
          PARSE_DATE("%Y%m%d", event_date) AS ymd,
          REGEXP_REPLACE((SELECT value.string_value FROM UNNEST(event_params) WHERE key = 'page_location'), r"\?.*", "") AS page_location,
          (SELECT value.int_value FROM UNNEST(event_params) WHERE key = 'batch_page_id') AS batch_page_id,
          (SELECT value.int_value FROM UNNEST(event_params) WHERE key = 'engagement_time_msec') AS _engagement_time_msec
        FROM
          `<project>.<dataset>.events_*`
        WHERE
          _TABLE_SUFFIX BETWEEN date_from() AND FORMAT_DATE('%Y%m%d', DATE_SUB(CURRENT_DATE(), INTERVAL 1 DAY))
      )
      GROUP BY
        ymd,
        page_location,
        batch_page_id
    )
    GROUP BY
      ymd,
      page_location
    
  )

SELECT
  *
FROM
  ENG_Time
ORDER BY
  ymd ASC

クエリ解説

GA4のスコープには、「ユーザー」「セッション」「イベント」とあるが、このスコープを使ってページ単位の分析をすることはできない。ページ単位の分析とは、そのページに滞在しているそのスコープの中で分析する必要があり、「セッション」スコープを採用するとページ間の遷移まで含まれてしまうからだ。その問題を解決するために、他のスコープを採用する必要があり、それが「batch_page_id」となる。

IF(SUM(FLOOR(SAFE_DIVIDE(COALESCE(_engagement_time_msec, 0), 1000))) > 30, 1,0) AS _flag_eng

エンゲージメントとする閲覧時間の調整は上記の「30」秒の箇所の数値を変更することで、他の時間へと変更可能。

ページ単位「30秒閲覧」+「スクロールイベント」でエンゲージメントとするクエリ

ページ閲覧の中で、「30秒以上の滞在」+デフォルト指標である90%到達した「スクロール」イベントの2つを満たした際にエンゲージメントとする条件も「batch_page_id」を活用することで集計可能になる。

CREATE TEMP FUNCTION date_from() RETURNS STRING AS ('20240301');

WITH
  Common_Table AS (
    SELECT
      ymd,
      page_location,
      event_name,
      batch_page_id,
      _engagement_time_msec
    FROM (
      SELECT
        PARSE_DATE("%Y%m%d", event_date) AS ymd,
        REGEXP_REPLACE((SELECT value.string_value FROM UNNEST(event_params) WHERE key = 'page_location'), r"\?.*", "") AS page_location,
        event_name,
        (SELECT value.int_value FROM UNNEST(event_params) WHERE key = 'batch_page_id') AS batch_page_id,
        (SELECT value.int_value FROM UNNEST(event_params) WHERE key = 'engagement_time_msec') AS _engagement_time_msec
      FROM
        `<project>.<dataset>.events_*`
      WHERE
        _TABLE_SUFFIX BETWEEN date_from() AND FORMAT_DATE('%Y%m%d', DATE_SUB(CURRENT_DATE(), INTERVAL 1 DAY))
    )
    WHERE
      page_location IS NOT NULL --'page_location'がNULLを出力するカスタムイベントを定義している場合除外が必要
  ),
  ENG_Time_01 AS (
    SELECT
      ymd,
      page_location,
      batch_page_id,
      SUM(FLOOR(SAFE_DIVIDE(COALESCE(_engagement_time_msec, 0), 1000))) AS _engagement_time_seconds, --検証用
      IF(SUM(FLOOR(SAFE_DIVIDE(COALESCE(_engagement_time_msec, 0), 1000))) > 30, 1,0) AS _flag_eng,
      1 AS _cnt_record
    FROM (
      SELECT
        *
      FROM
        Common_Table
    )
    GROUP BY
      ymd,
      page_location,
      batch_page_id
  ),
  ENG_scroll_01 AS (
    SELECT
      ymd,
      page_location,
      batch_page_id,
      SUM(_flag_scroll) AS _flag_scroll
    FROM (
      SELECT
        *,
        IF(event_name = 'scroll',1,0) AS _flag_scroll
      FROM
        Common_Table
    )
    GROUP BY
      ymd,
      page_location,
      batch_page_id
  ),
  JOIN_Time_Scroll AS (
    SELECT
      t.ymd,
      t.page_location,
      t.batch_page_id,
      t._flag_eng,
      s._flag_scroll,
      IF(t._flag_eng = 1 AND s._flag_scroll = 1,1, 0) AS _flag_total,
      t._cnt_record
    FROM
      ENG_Time_01 AS t
    LEFT JOIN
      ENG_scroll_01 AS s
    ON
      t.ymd = s.ymd 
    AND
      t.page_location = s.page_location
    AND
      t.batch_page_id = s.batch_page_id
  ),
  Master_01 AS (
    SELECT
      ymd,
      page_location,
      SUM(_flag_eng) AS _flag_eng,
      SUM(_flag_scroll) AS _flag_scroll,
      SUM(_flag_total) AS _flag_total,
      SUM(_cnt_record) AS _cnt_record
    FROM
      JOIN_Time_Scroll
    GROUP BY
      ymd,
      page_location
  )

SELECT
  *
FROM
  Master_01

関連記事

ランディングページ改善のためのコンテンツ評価分析

【GA4 SQL】ページごとのページビュー数をBigQueryから集計

【GA4 SQL】デバイス/OS/ブラウザ別のセッション数をBigQueryから集計

PAGE TOP