Google アナリティクス 4 と BigQuery によるパフォーマンスの測定とデバッグ

ウェブに関する指標のデータを Google アナリティクス 4 プロパティに送信し、そのデータをエクスポートして BigQuery と Looker Studio で分析する方法について説明します。

Google は、Search ConsolePageSpeed Insights(PSI)、Chrome ユーザー エクスペリエンス レポート(CrUX)などのさまざまなツールを提供しています。これらのツールを使用すると、デベロッパーは、現場の実際のユーザーに対して、サイトの Core Web Vitals 指標のパフォーマンスを確認できます。

これらのツールは、サイトの実際のユーザー パフォーマンスの概要を把握できる点で優れています。また、使用を開始するための設定は一切不要です。

ただし、これらのツールのみを使用してサイトのパフォーマンスを測定することはおすすめしません。その理由は次のとおりです。

  • CrUX ベースのツールは、月別または過去 28 日間のデータを報告します。そのため、変更を加えた後、結果を確認できるようになるまでに長い時間がかかります。
  • CrUX ベースのツールでは、国、接続タイプ、デバイス カテゴリ(パソコンまたはモバイル)など、限られた数のディメンションでのみセグメント化できます。ビジネスに固有のディメンション(エンゲージメント ユーザー、特定のテストグループ内のユーザーなど)でデータを分割することはできません。
  • CrUX ベースのツールは、パフォーマンスの内容を知ることはできますが、理由を知ることはできません。アナリティクス ツールを使用すると、問題の追跡とデバッグに役立つ追加データを送信できます。

こうした理由から、すべてのサイト所有者は、既存の分析ツールを使用して Core Web Vitals 指標をモニタリングすることをおすすめします。この記事では、Google が提供する無料ツールを使用して、この作業を行う方法について説明します。

すべての設定が完了すると、次のようなダッシュボードを作成できるようになります。

ウェブに関する指標コネクタ レポートのスクリーンショット

ウェブに関する指標コネクタ レポートのスクリーンショット

上記のすべての手順を視覚的に確認するには、Google I/O '21 での Google の講演をご覧ください。

測定

Google アナリティクスでは、これまでもカスタム指標を使用してパフォーマンスを測定できましたが、Google アナリティクス 4(GA4)には、特にデベロッパーの皆様にお役立ていただける新機能がいくつかあります。

Google アナリティクスのウェブ インターフェースには強力な分析ツールがありますが、おなじみのクエリ言語では、未加工のイベントデータへのアクセスのパワーと柔軟性に勝るものはありません。

Google アナリティクス 4 と BigQuery を使用して Core Web Vitals の測定を開始するには、次の 3 つのことを行う必要があります。

  1. Google アナリティクス 4 プロパティBigQuery プロジェクトを作成します。
  2. Google アナリティクス プロパティの設定で BigQuery Export を有効にすると、受信したすべてのデータが BigQuery プロジェクト テーブルに自動的に入力されます。
  3. web-vitals JavaScript ライブラリをサイトに追加すると、Core Web Vitals の指標を測定し、アトリビューション データを含む Google アナリティクス 4 にデータを送信できるようになります。

分析

設定が完了すると、BigQuery インターフェースにイベントデータが入力され、次のようにデータをクエリできるようになります。

SELECT * FROM `my_project_id.analytics_XXXXX.events_*`
WHERE event_name IN ('LCP', 'INP', 'CLS')

クエリの結果のプレビューを次に示します。

BigQuery のウェブバイタル イベントデータ

Web Vitals データのクエリ

ウェブバイタルのイベントデータのクエリを開始する前に、データの集計方法を理解しておくことが重要です。

理解しておくべき最も重要な点は、同じページ上の同じ指標に対して複数のイベントが受信される可能性があるということです。これは、指標値が変更され、更新された値がレポートされた場合に発生することがあります(CLS でよく発生します)。

ウェブ バイタルズ イベントの場合、最後に送信された値が常に最も正確な値であるため、分析を行う前に、それらの値のみをフィルタすることが重要です。Google アナリティクス 4 にデータを送信するために web-vitals JavaScript ライブラリが提供しているコード スニペットでは、指標ごとに一意の ID を送信しています。そのため、次のクエリを使用して、各指標 ID について最後に受信した値のみに結果を絞り込むことができます。

# Subquery all Web Vitals events from the last 28 days
WITH web_vitals_events AS (
  SELECT event_name as metric_name, * EXCEPT(event_name, is_last_received_value) FROM (
    SELECT *, IF (ROW_NUMBER() OVER (
      PARTITION BY (SELECT value.string_value FROM UNNEST(event_params) WHERE key = 'metric_id')
      ORDER BY (SELECT COALESCE(value.double_value, value.int_value) FROM UNNEST(event_params) WHERE key = 'metric_value') DESC
    ) = 1, true, false) AS is_last_received_value
    FROM `bigquery_project_id.analytics_XXXXX.events_*`
    WHERE event_name in ('CLS', 'INP', 'LCP') AND
      _TABLE_SUFFIX BETWEEN FORMAT_DATE('%Y%m%d', DATE_SUB(CURRENT_DATE, INTERVAL 28 DAY)) AND FORMAT_DATE('%Y%m%d', DATE_SUB(CURRENT_DATE, INTERVAL 1 DAY))
  ) WHERE is_last_received_value
)

この投稿で紹介している他のすべてのクエリは、このサブクエリで始まります。

クエリの例

以降のセクションでは、実行する必要がある一般的なウェブバイタル クエリの例をいくつか示します。

サイト全体の 75% パーセンタイル(p75)の LCP、INP、CLS

# Subquery all Web Vitals events from the last 28 days
WITH web_vitals_events AS (
  SELECT event_name as metric_name, * EXCEPT(event_name, is_last_received_value) FROM (
    SELECT *, IF (ROW_NUMBER() OVER (
      PARTITION BY (SELECT value.string_value FROM UNNEST(event_params) WHERE key = 'metric_id')
      ORDER BY (SELECT COALESCE(value.double_value, value.int_value) FROM UNNEST(event_params) WHERE key = 'metric_value') DESC
    ) = 1, true, false) AS is_last_received_value
    FROM `bigquery_project_id.analytics_XXXXX.events_*`
    WHERE event_name in ('CLS', 'INP', 'LCP') AND
      _TABLE_SUFFIX BETWEEN FORMAT_DATE('%Y%m%d', DATE_SUB(CURRENT_DATE, INTERVAL 28 DAY)) AND FORMAT_DATE('%Y%m%d', DATE_SUB(CURRENT_DATE, INTERVAL 1 DAY))
  ) WHERE is_last_received_value
)
# Main query logic
SELECT
  metric_name,
  APPROX_QUANTILES(metric_value, 100)[OFFSET(75)] AS p75,
  COUNT(1) as count
FROM (
  SELECT
    metric_name,
    ROUND((SELECT COALESCE(value.double_value, value.int_value) FROM UNNEST(event_params) WHERE key = "metric_value"), 3) AS metric_value,
  FROM web_vitals_events
)
GROUP BY 1

すべての個々の LCP 値(高い順)

# Subquery all Web Vitals events from the last 28 days
WITH web_vitals_events AS (
  SELECT event_name as metric_name, * EXCEPT(event_name, is_last_received_value) FROM (
    SELECT *, IF (ROW_NUMBER() OVER (
      PARTITION BY (SELECT value.string_value FROM UNNEST(event_params) WHERE key = 'metric_id')
      ORDER BY (SELECT COALESCE(value.double_value, value.int_value) FROM UNNEST(event_params) WHERE key = 'metric_value') DESC
    ) = 1, true, false) AS is_last_received_value
    FROM `bigquery_project_id.analytics_XXXXX.events_*`
    WHERE event_name in ('CLS', 'INP', 'LCP') AND
      _TABLE_SUFFIX BETWEEN FORMAT_DATE('%Y%m%d', DATE_SUB(CURRENT_DATE, INTERVAL 28 DAY)) AND FORMAT_DATE('%Y%m%d', DATE_SUB(CURRENT_DATE, INTERVAL 1 DAY))
  ) WHERE is_last_received_value
)
# Main query logic
SELECT
  ROUND((SELECT COALESCE(value.double_value, value.int_value) FROM UNNEST(event_params) WHERE key = "metric_value"), 3) AS metric_value,
FROM web_vitals_events
WHERE metric_name = 'LCP'
ORDER BY metric_value DESC
# Subquery all Web Vitals events from the last 28 days
WITH web_vitals_events AS (
  SELECT event_name as metric_name, * EXCEPT(event_name, is_last_received_value) FROM (
    SELECT *, IF (ROW_NUMBER() OVER (
      PARTITION BY (SELECT value.string_value FROM UNNEST(event_params) WHERE key = 'metric_id')
      ORDER BY (SELECT COALESCE(value.double_value, value.int_value) FROM UNNEST(event_params) WHERE key = 'metric_value') DESC
    ) = 1, true, false) AS is_last_received_value
    FROM `bigquery_project_id.analytics_XXXXX.events_*`
    WHERE event_name in ('CLS', 'INP', 'LCP') AND
      _TABLE_SUFFIX BETWEEN FORMAT_DATE('%Y%m%d', DATE_SUB(CURRENT_DATE, INTERVAL 28 DAY)) AND FORMAT_DATE('%Y%m%d', DATE_SUB(CURRENT_DATE, INTERVAL 1 DAY))
  ) WHERE is_last_received_value
)
# Main query logic
SELECT
  page_path,
  APPROX_QUANTILES(metric_value, 100)[OFFSET(75)] AS LCP,
  COUNT(1) as count
FROM (
  SELECT
    REGEXP_SUBSTR((SELECT value.string_value FROM UNNEST(event_params) WHERE key = "page_location"), r'\.com(\/[^?]*)') AS page_path,
    ROUND((SELECT COALESCE(value.double_value, value.int_value) FROM UNNEST(event_params) WHERE key = "metric_value"), 3) AS metric_value,
  FROM web_vitals_events
  WHERE metric_name = 'LCP'
)
GROUP BY 1
ORDER BY count DESC
LIMIT 10

CLS が悪い上位 10 ページ(p75)

# Subquery all Web Vitals events from the last 28 days
WITH web_vitals_events AS (
  SELECT event_name as metric_name, * EXCEPT(event_name, is_last_received_value) FROM (
    SELECT *, IF (ROW_NUMBER() OVER (
      PARTITION BY (SELECT value.string_value FROM UNNEST(event_params) WHERE key = 'metric_id')
      ORDER BY (SELECT COALESCE(value.double_value, value.int_value) FROM UNNEST(event_params) WHERE key = 'metric_value') DESC
    ) = 1, true, false) AS is_last_received_value
    FROM `bigquery_project_id.analytics_XXXXX.events_*`
    WHERE event_name in ('CLS', 'INP', 'LCP') AND
      _TABLE_SUFFIX BETWEEN FORMAT_DATE('%Y%m%d', DATE_SUB(CURRENT_DATE, INTERVAL 28 DAY)) AND FORMAT_DATE('%Y%m%d', DATE_SUB(CURRENT_DATE, INTERVAL 1 DAY))
  ) WHERE is_last_received_value
)
# Main query logic
SELECT
  page_path,
  APPROX_QUANTILES(metric_value, 100)[OFFSET(75)] AS CLS,
  COUNT(1) as count
FROM (
  SELECT
    REGEXP_SUBSTR((SELECT value.string_value FROM UNNEST(event_params) WHERE key = "page_location"), r'\.com(\/[^?]*)') AS page_path,
    ROUND((SELECT COALESCE(value.double_value, value.int_value) FROM UNNEST(event_params) WHERE key = "metric_value"), 3) AS metric_value,
  FROM web_vitals_events
  WHERE metric_name = 'CLS'
)
GROUP BY 1
HAVING count > 50 # Limit to relatively popular pages
ORDER BY CLS DESC
LIMIT 10

デバッグ

上記のクエリは、現在のパフォーマンスと時間の経過に伴う傾向を把握するのに役立つ、Core Web Vitals 指標データをクエリする方法を示しています。ただし、パフォーマンスが期待値を下回っていて、その原因がわからない場合はどうすればよいでしょうか。

スコアが何であるかを知っても、問題に対処して解決できない場合は役に立ちません。

フィールドでパフォーマンスをデバッグするでは、アナリティクス データとともに追加のデバッグ情報を送信する方法について説明しています。その投稿に記載されている手順に沿って操作すると、BigQuery にもデバッグ情報が表示されます。

クエリの例

次のクエリは、debug_target イベント パラメータを使用してパフォーマンスの問題の根本原因を特定する方法を示しています。

CLS に影響を与えている上位の要素

debug_target は、ページ上の要素のうち指標値に最も関連するものに対応する CSS セレクタ文字列です。

CLS では、debug_target は CLS 値に寄与した最大のレイアウト シフトから最大の要素を表します。シフトされた要素がない場合、debug_target の値は null です。

次のクエリは、CLS 値の低いものから高いものまでページをリストします(75 パーセンタイル、debug_target でグループ化)。

# Subquery all Web Vitals events from the last 28 days
WITH web_vitals_events AS (
  SELECT event_name as metric_name, * EXCEPT(event_name, is_last_received_value) FROM (
    SELECT *, IF (ROW_NUMBER() OVER (
      PARTITION BY (SELECT value.string_value FROM UNNEST(event_params) WHERE key = 'metric_id')
      ORDER BY (SELECT COALESCE(value.double_value, value.int_value) FROM UNNEST(event_params) WHERE key = 'metric_value') DESC
    ) = 1, true, false) AS is_last_received_value
    FROM `bigquery_project_id.analytics_XXXXX.events_*`
    WHERE event_name in ('CLS', 'INP', 'LCP') AND
      _TABLE_SUFFIX BETWEEN FORMAT_DATE('%Y%m%d', DATE_SUB(CURRENT_DATE, INTERVAL 28 DAY)) AND FORMAT_DATE('%Y%m%d', DATE_SUB(CURRENT_DATE, INTERVAL 1 DAY))
  ) WHERE is_last_received_value
)
# Main query logic
SELECT
  page_path,
  debug_target,
  APPROX_QUANTILES(metric_value, 100)[OFFSET(75)] AS CLS,
  COUNT(1) as count
FROM (
  SELECT
    REGEXP_SUBSTR((SELECT value.string_value FROM UNNEST(event_params) WHERE key = "page_location"), r'\.com(\/[^?]*)') AS page_path,
    (SELECT value.string_value FROM UNNEST(event_params) WHERE key = "debug_target") as debug_target,
    ROUND((SELECT COALESCE(value.double_value, value.int_value) FROM UNNEST(event_params) WHERE key = "metric_value"), 3) AS metric_value,
    *
  FROM web_vitals_events
  WHERE metric_name = 'CLS'
)
GROUP BY 1, 2
HAVING count > 50 # Limit to relatively popular pages
ORDER BY CLS DESC

CLS に寄与している上位要素のクエリ結果

ページ上のどの要素がシフトしているのかがわかれば、問題の根本原因の特定と修正が非常に容易になります。

ここでレポートされる要素は、ローカルでページをデバッグした際にシフトが確認される要素と同じでない可能性があることに留意してください。そのため、このデータを最初にキャプチャすることが非常に重要です。問題だと気付いていないものを修正することは非常に困難です。

他の指標をデバッグする

前述のクエリでは CLS 指標の結果が表示されますが、まったく同じ手法を使用して LCP と INP のデバッグ ターゲットをレポートできます。where 句を関連する指標に置き換えてデバッグするだけです。

WHERE metric_name = 'INP'
WHERE metric_name = 'LCP'

各ウェブに関する主な指標のデバッグ情報を収集して送信する方法については、フィールドでパフォーマンスをデバッグするをご覧ください。

可視化

クエリ結果のみを確認して分析情報を得るのは難しい場合があります。たとえば、次のクエリは、データセット内の LCP の 75 パーセンタイルの日次値を一覧表示します。

# Subquery all Web Vitals events from the last 28 days
WITH web_vitals_events AS (
  SELECT event_name as metric_name, * EXCEPT(event_name, is_last_received_value) FROM (
    SELECT *, IF (ROW_NUMBER() OVER (
      PARTITION BY (SELECT value.string_value FROM UNNEST(event_params) WHERE key = 'metric_id')
      ORDER BY (SELECT COALESCE(value.double_value, value.int_value) FROM UNNEST(event_params) WHERE key = 'metric_value') DESC
    ) = 1, true, false) AS is_last_received_value
    FROM `bigquery_project_id.analytics_XXXXX.events_*`
    WHERE event_name in ('CLS', 'INP', 'LCP') AND
      _TABLE_SUFFIX BETWEEN FORMAT_DATE('%Y%m%d', DATE_SUB(CURRENT_DATE, INTERVAL 28 DAY)) AND FORMAT_DATE('%Y%m%d', DATE_SUB(CURRENT_DATE, INTERVAL 1 DAY))
  ) WHERE is_last_received_value
)
# Main query logic
SELECT
  event_date,
  metric_name,
  APPROX_QUANTILES(ROUND(metric_value, 2), 100)[OFFSET(75)] AS p75
FROM
  (
    SELECT
      event_date,
      metric_name,
      ROUND((SELECT COALESCE(value.double_value, value.int_value) FROM UNNEST(event_params) WHERE key = 'metric_value'), 3) AS metric_value
    FROM web_vitals_events
    WHERE
      metric_name = 'LCP'
  )
GROUP BY
  1, 2
ORDER BY event_date

これらのクエリ結果から、データを見るだけでは傾向や外れ値を特定するのは困難です。

1 日あたりの指標値のクエリ結果

このような場合は、データを可視化することで、より迅速に分析情報を得ることができます。

Looker Studio でクエリ結果を可視化する

BigQuery では、データポータルを通じてクエリ結果をすばやく可視化できます。Looker Studio は、データの可視化とダッシュボードの機能を備えた、無料で使用できるツールです。クエリ結果を可視化するには、BigQuery UI でクエリを実行した後、[データを探索] ボタンをクリックし、[Looker Studio で調べる] を選択します。

BigQuery の Looker Studio オプションで調べる

これにより、探索ビューに BigQuery から Looker Studio への直接リンクが作成されます。このビューでは、可視化するフィールドの選択、グラフの種類の選択、フィルタの設定、アドホック グラフの作成を行って、視覚的な分析を迅速に行うことができます。前のクエリ結果から次の折れ線グラフを作成して、時間の経過に伴う LCP 値の傾向を確認できます。

Looker Studio による毎日の LCP 値の折れ線グラフ

こうした BigQuery と Looker Studio の直接リンクにより、任意のクエリから簡単なグラフを作成し、視覚的な分析を行うことができます。ただし、さらに分析する場合は、インタラクティブなダッシュボードで複数のグラフを確認して、全体像を把握するか、データを詳しく確認できるようにすることをおすすめします。便利なダッシュボードがあれば、指標を分析するたびにクエリを記述してグラフを手動で生成する必要がなくなります。

Looker Studio では、ネイティブ BigQuery コネクタを使用してダッシュボードを作成できます。これを行うには、datastudio.google.com に移動して新しいデータソースを作成し、BigQuery コネクタを選択して、操作するデータセットを選択します。

Looker Studio で BigQuery ネイティブ コネクタを使用する

ウェブに関する指標データを実体化する

前述のように、ウェブに関する指標のイベントデータのダッシュボードを作成する場合、Google アナリティクス 4 のエクスポート データセットを直接使用するのは効率的ではありません。GA4 データの構造とウェブに関する指標に前処理が必要であるため、クエリの一部が複数回実行されます。このため、ダッシュボードのパフォーマンスと BigQuery の費用という 2 つの問題が生じます。

BigQuery サンドボックス モードは無料で使用できます。BigQuery の無料枠では、処理されるクエリデータのうち、毎月最初の 1 TB までが無料です。この記事で説明している分析方法では、かなり大規模なデータセットを使用している場合や、データセットを定期的かつ頻繁にクエリしている場合を除き、毎月この無料枠の制限内に収まるはずです。ただし、トラフィック量の多いウェブサイトがあり、高速なインタラクティブ ダッシュボードを使用してさまざまな指標を定期的にモニタリングする場合は、パーティショニング、クラスタリング、キャッシュ保存などの BigQuery の効率化機能を利用しながら、ウェブに関する指標データの前処理と実体化を行うことをおすすめします。

次のスクリプトは、BigQuery データ(ソーステーブル)を前処理し、実体化テーブル(ターゲット テーブル)を作成します。このクエリを独自のデータセットに使用する場合は、ソーステーブルの期間を定義して、処理されるデータの量を減らすこともできます。

# Materialize Web Vitals metrics from GA4 event export data

# Replace target table name
CREATE OR REPLACE TABLE bigquery_project_id.ga4_demo_dev.web_vitals_summary
  PARTITION BY DATE(event_timestamp)
  CLUSTER BY metric_name
AS
SELECT
  ga_session_id,
  IF(
    EXISTS(SELECT 1 FROM UNNEST(events) AS e WHERE e.event_name = 'first_visit'),
    'New user',
    'Returning user') AS user_type,
  IF(
    (SELECT MAX(session_engaged) FROM UNNEST(events)) > 0, 'Engaged', 'Not engaged')
    AS session_engagement,
  evt.* EXCEPT (session_engaged, event_name),
  event_name AS metric_name,
  FORMAT_TIMESTAMP('%Y%m%d', event_timestamp) AS event_date
FROM
  (
    SELECT
      ga_session_id,
      ARRAY_AGG(custom_event) AS events
    FROM
      (
        SELECT
          ga_session_id,
          STRUCT(
            country,
            device_category,
            device_os,
            traffic_medium,
            traffic_name,
            traffic_source,
            page_path,
            debug_target,
            event_timestamp,
            event_name,
            metric_id,
            IF(event_name = 'LCP', metric_value / 1000, metric_value) AS metric_value,
            user_pseudo_id,
            session_engaged,
            session_revenue) AS custom_event
        FROM
          (
            SELECT
              (SELECT value.int_value FROM UNNEST(event_params) WHERE key = 'ga_session_id')
                AS ga_session_id,
              (SELECT value.string_value FROM UNNEST(event_params) WHERE key = 'metric_id')
                AS metric_id,
              ANY_VALUE(device.category) AS device_category,
              ANY_VALUE(device.operating_system) AS device_os,
              ANY_VALUE(traffic_source.medium) AS traffic_medium,
              ANY_VALUE(traffic_source.name) AS traffic_name,
              ANY_VALUE(traffic_source.source) AS traffic_source,
              ANY_VALUE(
                REGEXP_SUBSTR(
                  (SELECT value.string_value FROM UNNEST(event_params) WHERE key = 'page_location'),
                  r'^[^?]+')) AS page_path,
              ANY_VALUE(
                (SELECT value.string_value FROM UNNEST(event_params) WHERE key = 'debug_target'))
                AS debug_target,
              ANY_VALUE(user_pseudo_id) AS user_pseudo_id,
              ANY_VALUE(geo.country) AS country,
              ANY_VALUE(event_name) AS event_name,
              SUM(ecommerce.purchase_revenue) AS session_revenue,
              MAX(
                (
                  SELECT
                    COALESCE(
                      value.double_value, value.int_value, CAST(value.string_value AS NUMERIC))
                  FROM UNNEST(event_params)
                  WHERE key = 'session_engaged'
                )) AS session_engaged,
              TIMESTAMP_MICROS(MAX(event_timestamp)) AS event_timestamp,
              MAX(
                (
                  SELECT COALESCE(value.double_value, value.int_value)
                  FROM UNNEST(event_params)
                  WHERE key = 'metric_value'
                )) AS metric_value,
            FROM
              # Replace source table name
              `bigquery_project_id.analytics_XXXXX.events_*`
            WHERE
              event_name IN ('LCP', 'INP', 'CLS', 'first_visit', 'purchase')
            GROUP BY
              1, 2
          )
      )
    WHERE
      ga_session_id IS NOT NULL
    GROUP BY ga_session_id
  )
CROSS JOIN UNNEST(events) AS evt
WHERE evt.event_name NOT IN ('first_visit', 'purchase');

この実体化データセットには複数の利点があります。

  • データ構造がフラット化され、クエリしやすくなります。
  • 元の GA4 データセットのウェブに関する指標イベントのみが保持されます。
  • セッション ID、ユーザータイプ(新規かリピーターか)、セッション エンゲージメント情報を、列で直接利用できます。
  • テーブルが日付で分割され、指標名でクラスタ化されます。これにより、通常は各クエリで処理されるデータ量が削減されます。
  • このテーブルに対するクエリにワイルドカードを使用する必要はないため、クエリ結果は最大 24 時間キャッシュに保存されます。これにより、同じクエリを繰り返すことによる費用を削減できます。
  • BigQuery BI Engine を使用する場合は、最適化された SQL 関数と演算子をこのテーブルで実行できます。

この実体化テーブルは、BigQuery UI から直接クエリできます。また、BigQuery コネクタを使用して Looker Studio で使用することもできます。

ウェブに関する指標コネクタを使用する

ダッシュボードをゼロから作成するには時間がかかるため、テンプレート ダッシュボードを作成するパッケージ化されたソリューションを開発しました。まず、前のクエリを使用して Web Vitals テーブルが実体化されていることを確認します。次に、goo.gle/web-vitals-connector を使用して、Looker Studio のウェブに関する指標コネクタにアクセスします。

1 回限りの承認を設定すると、次の構成画面が表示されます。

Web Vitals コネクタの承認画面

実体化 BigQuery テーブル ID(ターゲット テーブル)と BigQuery の請求プロジェクト ID を指定します。[接続] をクリックすると、テンプレート化された新しいダッシュボードが作成され、データが関連付けられます。ダッシュボードは必要に応じて編集、変更、共有できます。ダッシュボードを一度作成すると、異なるデータセットから複数のダッシュボードを作成する場合を除き、コネクタリンクに再度アクセスする必要はありません。

ダッシュボードを操作すると、[サマリー] タブで、ウェブに関する指標の毎日の傾向と、ユーザーやセッションなどのウェブサイトの使用状況に関する情報を確認できます。

[ユーザー分析] タブでは、指標を選択し、ユーザー数だけでなく、種々の使用状況やビジネス指標別に指標のパーセンタイルの内訳を確認できます。

[ページパス分析] タブでは、ウェブサイト上の問題領域を特定できます。ここで指標を選択すると、概要が表示されます。すべてのページパスの散布図も表示されます(Y 軸はパーセンタイル値、X 軸はレコード数)。散布図では、指標の値が想定よりも低いページを特定できます。ページパス テーブルの散布図を使用してページを選択したら、デバッグ ターゲット テーブルを表示して、問題のある部分をさらに詳しく確認できます。

[収益分析] タブは、ビジネス指標とパフォーマンス指標を同じ場所でモニタリングする方法の一例です。このセクションでは、ユーザーが購入を行ったセッションがすべてプロットされます。特定のセッションで得た収益とユーザー エクスペリエンスを比較できます。

高度な使用方法

データセットに慣れてきたら、ダッシュボードを編集して独自のグラフを追加し、より詳細で的確な分析を行うことができます。ダッシュボードをより有用にするには、次の手順を行います。

  • BigQuery でスケジュール設定されたクエリを設定して、更新されたデータを取得します。前回実行した実体化クエリは、その時点でのデータのスナップショットを取得するだけです。ダッシュボードを新しいデータで常に更新する場合は、毎日実行されるスケジュールされたクエリを実行し、新しいデータをマテリアライズド テーブルに追加します。
  • 自社データ(CRM など)を結合してビジネス インサイトを取得します。マテリアライズド テーブルでは、user_id を別の列として追加できます。これにより、ファーストパーティ データを結合できます。自社データが BigQuery にまだない場合は、データを読み込むか、連携データソースを使用できます。
  • サイトまたはアプリのバージョンを、Google アナリティクスに送信するデータのパラメータとして報告し、マテリアライズド テーブルの列として追加します。その後、そのバージョン データをグラフのディメンションとして追加すると、バージョンの変更がパフォーマンスに与える影響を簡単に確認できます。
  • 直接クエリまたはダッシュボードを介してデータセットを大量に使用することが予想される場合は、有料バージョンの BigQuery BI Engine の使用を検討してください。

概要

この投稿では、Google アナリティクス 4 と BigQuery を使用して、現場で収集された実際のユーザーデータでパフォーマンスを測定、デバッグする方法の基本について説明しました。また、Looker Studio と ウェブに関する指標コネクタを使用して自動レポートとダッシュボードを作成し、データをできるだけ簡単に可視化する方法についても説明しました。

この投稿の重要なポイントは次のとおりです。

  • 実際のユーザーデータを使用してパフォーマンスを測定することは、サイトの理解、デバッグ、最適化に不可欠です。
  • パフォーマンス指標とビジネス指標が同じシステム内にあると、より詳細な分析情報を得ることができます。Google アナリティクスと BigQuery を使用すると、このことが可能になります。
  • Google アナリティクスの元データを BigQuery にエクスポートすると、すでにご存じのクエリ言語を使用して、詳細なカスタム分析を無制限に行うことができます。
  • Google には、Looker Studio などのさまざまな API と可視化ツールがあり、自由にレポートを作成できます。