GA4

[GA4 SQL] セッションあたりの平均エンゲージメント時間とは

セッションあたりの平均エンゲージメント時間とは

GA4の「セッションあたりの平均エンゲージメント時間」(Average engagement time per session)とはブラウザがフォーカス状態にあった合計時間(ユーザーエンゲージメント)をセッションの合計数で割った値ことを指す。つまりセッションあたりのページが閲覧されていた平均時間を正確に算出することができる指標となる。似たような指標に「アクティブユーザーあたりの平均エンゲージメント」があり、違いは分母がアクティブユーザーなのかセッションなのかの違いである。基本的にはセッションを元に平均エンゲージメント時間を算出することの方が多くなるだろう。また、平均エンゲージメント時間は基本的にはサイトにどれだけ長く滞在してくれたかの指標であるため、時間は長くなる方が望ましい。

セッションあたりの平均エンゲージメント時間 = ユーザーエンゲージメントの合計時間 / セッション数の合計

参考:セッションあたりの平均エンゲージメント時間 – アナリティクス ヘルプ

【探索】セッションあたりの平均エンゲージメント時間

ディメンション
 ・日付
指標
 ・ユーザーエンゲージメント
 ・セッション
 ・セッションあたりの平均エンゲージメント時間

【Looker Studio】セッションあたりの平均エンゲージメント時間

現時点(24年12月)ではLooker Studioの指標で「セッションあたりの平均エンゲージメント時間」を選択することはできないが計算フィールドで同一の指標を作成することは可能。

参考:計算フィールドの追加、編集、トラブルシューティング – Looker Studioのヘルプ

【SQL】セッションあたりの平均エンゲージメント時間

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

WITH
  ENG_SS_Daily AS (
    SELECT
      e.ymd,
      e._engagement_time_seconds,
      s._ssuu,
      FLOOR(e._engagement_time_seconds / s._ssuu) AS _avrEngSS,
      FORMAT_TIMESTAMP(
        '%H時間 %M分 %S秒',
        TIMESTAMP_SECONDS(CAST(FLOOR(e._engagement_time_seconds / s._ssuu) AS INT64))
      ) AS format_second
    FROM (
      SELECT
        ymd,
        _engagement_time_seconds,
      FROM (
        SELECT
          ymd,
          SUM(FLOOR(SAFE_DIVIDE(COALESCE(_engagement_time_msec, 0), 1000))) AS _engagement_time_seconds
        FROM (
          SELECT
            PARSE_DATE("%Y%m%d", event_date) AS ymd,
            (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
          _engagement_time_msec <> 0
        GROUP BY
          ymd
      )
    ) AS e
    INNER JOIN (
      SELECT
        ymd,
        COUNT(DISTINCT ssid) AS _ssuu
      FROM (
        SELECT
          ymd,
          CONCAT(user_pseudo_id, '-', CAST(ga_session_id AS STRING)) AS ssid
        FROM (
          SELECT
            PARSE_DATE("%Y%m%d", event_date) AS ymd,
            user_pseudo_id,
            (SELECT value.int_value FROM UNNEST(event_params) WHERE key = 'ga_session_id') AS ga_session_id
          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
    ) AS s
    ON
      e.ymd = s.ymd
  )

SELECT
  *
FROM
  ENG_SS_Daily
ORDER BY
  ymd ASC

セッションあたりの平均エンゲージメント時間を分析に活かすには?

日次の「セッションあたりの平均エンゲージメント時間」とは、つまりサイト全体のセッションあたりの平均エンゲージメント時間の推移であり、よりサイト改善につなげるにはより詳細に分析していく必要がある。

ランディングページのセッションあたりの平均エンゲージメント時間

ランディングページにおけるセッションあたりの平均エンゲージメント時間とは、ランディングページ1ページのみの平均エンゲージメント時間が表示されているのではなく、ランディングページを起点として、そのセッションの後続に閲覧された全てのページのユーザーエンゲージメント(ページ閲覧時間)をセッションで割った値がランディングページに紐づけられている。つまり、そのセッションのエンゲージメント時間の評価を起点であるランディングページに割り当てたものといえる。要するに、どのランディングページに着地すれば閲覧時間が長くなるのかを分析することができるのが、ランディングページのセッションあたりの平均エンゲージメント時間となる。

参考:[GA4] ランディング ページ レポート – アナリティクス ヘルプ

【探索】LPのセッションあたりの平均エンゲージメント時間

ディメンション
 ・ランディング ページ + クエリ文字列
指標
 ・ユーザーエンゲージメント
 ・セッション
 ・セッションあたりの平均エンゲージメント時間

【SQL】LPのセッションあたりの平均エンゲージメント時間

CREATE TEMP FUNCTION date_from() RETURNS STRING AS ('20241101');
CREATE TEMP FUNCTION date_to() RETURNS STRING AS ('20241130');

WITH
  LP_ENG_SS AS (
    SELECT
      s.ymd,
      s.landing_page,
      e._engagement_time_seconds,
      s._ssuu,
      FLOOR(e._engagement_time_seconds / s._ssuu) AS _avg_eng_time_per_ss,
    FROM (
      SELECT
        ymd,
        page_location AS landing_page,
        SUM(entrances) AS _ssuu
      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) p WHERE p.key = 'entrances') AS entrances
        FROM
          `<project>.<dataset>.events_*`
        WHERE
          _TABLE_SUFFIX BETWEEN date_from() AND date_to()
        AND
          event_name = 'page_view'
      )
      GROUP BY
        ymd,
        page_location
    ) AS s
    LEFT JOIN (
      SELECT
        lp2.ymd,
        lp2.landing_page,
        SUM(e._engagement_time_seconds) AS _engagement_time_seconds
      FROM (
        SELECT
          f.ymd,
          f.user_pseudo_id,
          f.ga_session_id,
          l.page_location AS landing_page
        FROM (
          SELECT
            PARSE_DATE("%Y%m%d", event_date) AS ymd,
            user_pseudo_id,
            (SELECT value.int_value FROM UNNEST(event_params) WHERE key = 'ga_session_id') AS ga_session_id,
            MIN(event_timestamp) AS first_event_timestamp
          FROM
            `<project>.<dataset>.events_*`
          WHERE
            _TABLE_SUFFIX BETWEEN date_from() AND date_to()
          AND
            event_name = 'page_view'
          GROUP BY
            ymd,
            user_pseudo_id,
            ga_session_id
        ) AS f
        INNER JOIN (
          SELECT
            PARSE_DATE("%Y%m%d", event_date) AS ymd,
            user_pseudo_id,
            (SELECT value.int_value FROM UNNEST(event_params) WHERE key = 'ga_session_id') AS ga_session_id,
            REGEXP_REPLACE((SELECT value.string_value FROM UNNEST(event_params) WHERE key = 'page_location'), r"\?.*", "") AS page_location,
            event_timestamp
          FROM
            `<project>.<dataset>.events_*`
          WHERE
            _TABLE_SUFFIX BETWEEN date_from() AND date_to()
          AND
            event_name = 'page_view'
        ) AS l
        ON
          f.ymd = l.ymd
        AND
          f.user_pseudo_id = l.user_pseudo_id
        AND
          f.ga_session_id = l.ga_session_id
        AND
          f.first_event_timestamp = l.event_timestamp
      ) AS lp2
      INNER JOIN (
        SELECT
          ymd,
          user_pseudo_id,
          ga_session_id,
          SUM(FLOOR(SAFE_DIVIDE(COALESCE(_engagement_time_msec, 0), 1000))) AS _engagement_time_seconds
        FROM (
          SELECT
            PARSE_DATE("%Y%m%d", event_date) AS ymd,
            user_pseudo_id,
            (SELECT value.int_value FROM UNNEST(event_params) WHERE key = 'ga_session_id') AS ga_session_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 date_to()
        )
        WHERE
          _engagement_time_msec <> 0  
        GROUP BY
          ymd,
          user_pseudo_id,
          ga_session_id
      ) AS e
      ON
        lp2.ymd = e.ymd
      AND    
        lp2.user_pseudo_id = e.user_pseudo_id
      AND
        lp2.ga_session_id = e.ga_session_id
      GROUP BY
        lp2.ymd,
        lp2.landing_page
    ) AS e
    ON 
      s.ymd = e.ymd
    AND
      s.landing_page = e.landing_page
  )

SELECT
  * ,
  FORMAT_TIMESTAMP(
    '%H時間 %M分 %S秒',
    TIMESTAMP_SECONDS(CAST(_avg_eng_time_per_ss AS INT64))
  ) AS format_second
FROM
  LP_ENG_SS
ORDER BY
  ymd ASC

Tipsランディングページのセッション数はentrancesパラメータの値を元に集計しているためGA4の探索のセッション数とは僅かにズレる。そのため平均エンゲージメント時間もズレることになるが、entrancesパラメータの値をランディングページのセッション数と見なすことに問題はない。

関連記事

【GA4 SQL】新規ユーザーのユーザーセグメントを日次で適用

【GA4 SQL】再帰CTEで同一ページを除いた「2ページ目」を取得 BigQuery WITH RECURSIVE

【GA4 SQL】新規ユーザー数・リピーター数の取得

おすすめ記事

最近の記事
おすすめ記事
  1. GA4の「セッション」とは?図解で分かりやすく解説

  2. SQL不要でSearch Consoleを深掘り!BigQuery「会話型分析」で実現する次世代SEOデータ分析 Conversational Analytics

  3. Search ConsoleのデータをBigQueryにエクスポートする全手順

  1. 【BigQuery】データセットのテーブルを一括削除するSQL

  2. 【GA4 SQL】新規ユーザーのユーザーセグメントを日次で適用

  3. BigQuery(SQL)を使わないLooker Studioのテンプレートが無価値である理由

PAGE TOP