Google 애널리틱스 4 및 BigQuery로 성능 측정 및 디버그

Web Vitals 데이터를 Google 애널리틱스 4 속성으로 전송하고 BigQuery 및 Looker Studio에서 분석할 수 있도록 데이터를 내보내는 방법을 알아보세요.

Google은 여러 가지 도구를 제공하여 콘솔, PageSpeed Insights (PSI) Chrome 사용자 환경 신고 (CrUX)를 통해 개발자는 Core Web을 기준으로 사이트의 성능을 확인할 수 있습니다. Google 애널리틱스의 실제 사용자에 대한 수치 필드입니다.

이러한 도구는 사이트의 상태를 개괄적으로 보여준다는 점에서 사용할 수 있으며 설정 없이도 사용을 시작할 수 있습니다.

하지만 이 기능에 의존하고 싶지 않은 몇 가지 중요한 이유가 있습니다. 도구만 사용하여 사이트 실적을 측정할 수 있습니다.

  • CrUX 기반 도구는 데이터를 월별 또는 이전 28일 기간별로 보고합니다. 따라서 변경 후에는 오랜 시간이 지난 후에야 변경사항을 적용할 수 있습니다. 결과를 볼 수 있습니다.
  • CrUX 기반 도구는 제한된 수의 측정기준으로만 분류할 수 있습니다(예: 국가, 연결 유형, 기기 카테고리 (데스크톱 또는 모바일)를 파악할 수 있습니다. 할 수 없습니다. 내 비즈니스에 맞는 측정기준 (예: 참여, 특정 실험 그룹의 사용자 등).
  • CrUX 기반 도구는 어떤 실적인지는 알려주지만 이유를 설명합니다. 분석 도구를 사용하면 추적에 도움이 되는 추가 데이터를 전송할 수 있습니다. 디버그 문제를 해결할 수 있습니다

따라서 모든 사이트 소유자는 Core Web Vitals 측정항목을 모니터링하는 것이 좋습니다. 데이터를 분석할 수 있습니다 이 게시물에서는 이를 위해 Google이 제공하는 도구를 사용했습니다.

설정을 완료하면 다음과 같은 대시보드를 만들 수 있습니다.

웹 바이탈 커넥터 보고서 스크린샷

웹 바이탈 커넥터 보고서 스크린샷

여기에 설명된 모든 단계를 시각적으로 보려면 Google I/O '21의 강연을 확인하세요.

측정

지금까지는 Google 애널리틱스를 사용해 실적을 측정할 수 있는데, 맞춤 측정항목을 지원하지만 Google 애널리틱스의 새로운 기능 몇 가지를 4 (GA4)는 특히 기대해 볼 만합니다

Google 애널리틱스 웹 인터페이스에는 강력한 분석 도구가 있지만 쿼리를 사용하여 원시 이벤트 데이터에 액세스하는 기능과 유연성을 이미 알고 있을 가능성이 높은 언어입니다.

Google 애널리틱스 4 및 BigQuery를 사용하여 Core Web Vitals 측정을 시작하려면 다음 세 가지 작업을 수행해야 합니다.

  1. Google 애널리틱스 4 만들기 속성BigQuery 프로젝트.
  2. BigQuery 내보내기를 사용 설정합니다. Google 애널리틱스 속성 구성에 포함되어 있으므로 수신되는 모든 데이터는 BigQuery 프로젝트 테이블에 자동으로 채워집니다.
  3. web-vitals JavaScript 추가 코어 웹 바이탈 측정항목을 측정하고 Google 애널리틱스로 4에는 기여 분석 데이터가 포함됩니다.

분석

설정을 완료하면 BigQuery 테이블에 이벤트 데이터가 채워지는 것을 다음과 같이 데이터를 쿼리할 수 있습니다.

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

다음은 이 쿼리의 결과를 미리보기한 것입니다.

BigQuery의 Web Vitals 이벤트 데이터

Web Vitals 데이터 쿼리

웹 바이탈 이벤트 데이터 쿼리를 시작하기 전에 데이터가 집계되는 방식을 이해할 수 있습니다.

가장 중요한 것은 경우에 따라 여러 이벤트가 일 수 있습니다. 수신됨 한 페이지에서 동일한 측정항목을 사용할 수 있습니다. 이는 측정항목 값이 업데이트된 값이 보고됩니다 (CLS에서 흔히 발생하는 현상).

웹 바이탈 이벤트의 경우 마지막으로 전송된 값이 항상 가장 정확하므로 분석을 수행하기 전에 해당 값만 필터링하는 것이 중요합니다. web-vitals JavaScript 라이브러리에서 제공하는 코드 스니펫은 Google 애널리틱스 4에서는 측정항목당 고유 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
)

이 게시물에서 참조하는 다른 모든 쿼리는 하위 쿼리의 경우

쿼리 예

다음 섹션에서는 Google 애널리틱스 4를 이용해 볼 수 있는 일반적인 웹 바이탈 검색어의 정의할 수 있습니다

전체 사이트에서 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

디버그

이전 쿼리는 웹 바이탈 측정항목 데이터를 쿼리하는 방법을 보여주므로 현재 실적 및 시간 경과에 따른 추세를 이해하는 데 도움이 됩니다. 하지만 실적이 기대보다 나쁘지만 확신이 들지 않으면 어떻게 해야 할까요? 왜 그럴까요?

조치를 취할 수 없는 경우에는 점수가 어느인지 아는 것이 도움이 되지 않습니다. 문제를 해결할 수 있습니다

필드에서 성능 디버그에서 방법을 설명합니다. 애널리틱스 데이터와 함께 추가 디버그 정보를 보낼 수 있습니다. 만약 해당 게시물에 나와 있는 지침을 따르면 BigQuery에도 표시됩니다

쿼리 예

다음 쿼리는 debug_target 이벤트 매개변수를 사용하여 성능 문제의 근본 원인을 파악할 수 있습니다

CLS에 기여하는 주요 요소

debug_target는 다음 요소의 요소에 해당하는 CSS 선택자 문자열입니다. 가장 관련성이 높은 페이지를 찾습니다.

CLS를 사용하면 debug_target은 가장 큰 요소에서 가장 큰 요소를 나타냅니다. CLS 값에 기여한 레이아웃 변경입니다. 변경된 요소가 없으면 debug_target 값은 null이 됩니다.

다음 쿼리는 75번째 CLS에 따라 최악의 페이지에서 가장 좋은 순으로 페이지를 나열합니다. 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'

다시 한 번 이 모듈의 디버그 성능 입력란을 참조하세요. 각 Core Web Vitals 측정항목의 디버그 정보를 전송합니다.

시각화

쿼리 결과만 보고 유용한 정보를 얻는 것이 어려울 수 있음 합니다. 예를 들어 다음 쿼리는 데이터 세트의 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
  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

이러한 쿼리 결과에서는 단순히 쿼리를 실행하는 것만으로는 추세나 이상점을 데이터를 살펴볼 수 있습니다.

일일 측정항목 값 쿼리 결과

이러한 경우 데이터를 시각화하면 더 빠르게 유용한 정보를 도출할 수 있습니다.

Looker Studio에서 쿼리 결과 시각화

BigQuery는 데이터를 통해 쿼리 결과를 빠르게 시각화할 수 있는 방법을 제공합니다. 있습니다. Looker Studio는 무료로 사용할 수 있는 대시보드 도구입니다. 쿼리 결과를 시각화하려면 BigQuery UI에서 쿼리를 실행한 후 데이터 탐색 버튼을 클릭합니다. Looker Studio로 탐색을 선택합니다.

BigQuery의 Looker Studio로 탐색 옵션

그러면 탐색 분석 중에 BigQuery에서 Looker Studio로 직접 연결되는 링크가 생성됩니다. 합니다. 이 뷰에서는 시각화할 필드를 선택하고, 차트 유형, 필터 설정, 빠른 시각적 분석을 위한 임시 차트를 만들 수 있습니다. 이전 쿼리 결과에서 이 선 차트를 만들어 시간 경과에 따른 LCP 값:

Looker Studio의 일일 LCP 값 선 차트

BigQuery와 Looker Studio를 직접 연결하면 시각적 분석을 수행할 수 있습니다. 그러나 추가 분석을 할 때 그래프에서 여러 차트를 확인하고 싶을 수 있습니다. 대시보드를 통해 보다 종합적인 정보를 확인하거나 삽입해야 합니다. 편리한 대시보드 덕분에 쿼리를 작성할 필요가 없습니다. 측정항목을 분석할 때마다 수동으로 차트를 생성할 수 있습니다.

기본 BigQuery API를 사용하여 Looker Studio에서 커넥터 - 커넥터에 연결합니다. 이렇게 하려면 datastudio.google.com으로 이동하여 새 BigQuery 커넥터를 선택한 후 원하는 데이터 세트를 선택하세요. 호환 기기:

Looker Studio에서 BigQuery 네이티브 커넥터 사용

Web Vitals 데이터 구체화

앞서 설명한 대로 웹 바이탈 이벤트 데이터의 대시보드를 만들 때 Google 애널리틱스 4 내보내기 데이터 세트를 직접 사용하는 것은 비효율적입니다. 이로 인해 웹 바이탈에 필요한 GA4 데이터의 구조와 전처리를 쿼리의 일부가 여러 번 실행됩니다. 이렇게 하면 BigQuery 비용입니다

BigQuery 샌드박스 모드를 무료로 사용할 수 있습니다. BigQuery의 무료 사용 등급이 아닌 매월 1TB까지는 쿼리 데이터가 무료로 처리됩니다. 분석 방법의 경우 다량의 데이터 세트를 사용하거나 정기적으로 데이터 세트에 많은 쿼리를 실행하고 있으므로 50%가 무료로 제공됩니다. 그러나 트래픽이 많은 웹사이트에서 빠른 대화형 대시보드를 사용하여 다양한 측정항목을 정기적으로 모니터링하고, 웹 바이탈 데이터를 전처리하고 구체화하는 방법을 파티셔닝, 클러스터링, 캐싱과 같은 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, 사용자 유형 (신규 사용자 vs. 재방문), 세션 참여 정보 열에서 바로 사용할 수 있습니다.
  • 테이블은 파티션 나누기 기준 날짜 및 클러스터링됨 측정항목 이름으로 표시됩니다 이렇게 하면 일반적으로 각 시스템에서 처리되는 데이터의 양이 쿼리합니다.
  • 이 테이블을 쿼리하는 데 와일드 카드를 사용할 필요가 없으므로 쿼리 결과는 최대 24시간 동안 캐시됩니다 이렇게 하면 동일한 쿼리합니다.
  • BigQuery BI 엔진을 사용하면 최적화된 SQL 함수와 연산자에 대해 표에서 확인할 수 있습니다.

BigQuery UI 내에서 구체화된 이 테이블을 직접 쿼리하거나 테이블을 사용할 수 있습니다. BigQuery 커넥터로 Looker Studio에서 실행할 수 있습니다

Web Vitals 커넥터 사용

대시보드를 처음부터 만드는 것은 시간이 많이 걸리기 때문에 솔루션에서 템플릿 대시보드를 생성해 줍니다. 먼저 이전 쿼리를 사용하여 Web Vitals 테이블을 구체화했습니다. 그런 다음 다음 링크를 사용하는 Looker Studio용 Web Vitals 커넥터 goo.gle/web-vitals-connector

일회성 승인을 제공하면 다음과 같이 표시됩니다. 구성 화면:

Web Vitals 커넥터 승인 화면

구체화된 BigQuery 테이블 ID (즉, 대상 테이블)와 BigQuery 결제 프로젝트 ID입니다. 연결을 클릭하면 Looker Studio에서 새 템플릿 대시보드를 만들고 데이터를 여기에 연결합니다 수정, 수정, 원하는 대로 대시보드를 공유할 수 있습니다. 대시보드를 한 번 만들면 여러 링크를 만들 수 있는 경우가 아니라면 커넥터 링크를 다시 방문해야 여러 데이터 세트의 대시보드가 포함됩니다

대시보드를 탐색하면서 Web Vitals의 일일 추세를 확인할 수 있습니다. 측정항목 및 일부 사용 정보(예: 사용자 수, 세션 수)를 볼 수 있습니다. 요약

사용자 분석 탭에서 측정항목을 선택한 다음 측정항목 백분위수, 다양한 사용량 및 비즈니스별 사용자 수 측정항목입니다.

페이지 경로 분석 탭을 이용하면 있습니다. 여기에서 측정항목을 선택하여 개요를 볼 수 있습니다. 하지만 y축에 백분위수 값이 있는 모든 페이지 경로의 분산형 지도 및 레코드 x축에서 계산합니다. 분산형 지도는 더 높다는 것을 알 수 있습니다. 분산형 차트를 사용하여 페이지를 선택한 후에는 페이지 경로 표의 차트를 맞춤설정하면 다음과 같은 방법으로 문제 영역을 더 상세히 살펴볼 수 있습니다. Debug Target 테이블 확인

수익 분석 탭은 비즈니스를 모니터링하는 방법의 한 가지 예입니다. 확인할 수 있습니다 이 섹션에는 다음과 같은 모든 세션이 표시됩니다. 사용자가 구매했습니다. 발생한 수익과 사용자 경험을 비교할 수 있습니다. 특정 세션 중 .

고급 사용법

데이터 세트에 익숙해지면 대시보드를 수정하고 자체 차트를 사용하여 더 풍부하고 타겟팅된 분석을 할 수 있습니다. 대시보드를 다음 단계를 따르세요.

  • BigQuery에서 예약된 쿼리를 설정하여 업데이트된 데이터를 가져옵니다. 구체화 해당 시점의 데이터 스냅샷만 찍습니다. 만약 대시보드를 새로운 데이터로 업데이트하려는 경우 예약된 대시보드를 실행하여 매일 실행되고 구체화된 테이블에 새 데이터를 수집하는 데 사용됩니다
  • 퍼스트 파티 데이터 (예: CRM)를 조인하여 유용한 비즈니스 정보를 확보합니다. 구체화된 표에서 user_id을 별도의 열로 추가할 수 있습니다. 그러면 퍼스트 파티 데이터를 활용할 수 있습니다 퍼스트 파티 데이터가 BigQuery에 없는 경우 데이터를 로드하거나 통합 데이터를 사용하여 소스를 참고하세요.
  • 사이트 또는 앱 버전을 Google에 전송하는 데이터의 매개변수로 보고 분석을 클릭하고 구체화된 테이블의 열로 추가합니다. 그런 다음 차트에서 해당 버전 데이터를 측정기준으로 사용하여 쉽게 볼 수 있음 성능에 영향을 미칩니다
  • 직접 유료 버전의 BigQuery BI를 사용해 엔진을 참조하세요.

요약

이 게시물에서는 Google 애널리틱스 4와 BigQuery를 사용하여 현장에서 수집된 실제 사용자 데이터로 성능을 측정하고 디버그합니다. 그것은 Looker Studio를 사용해 자동화된 보고서 및 대시보드를 만드는 방법도 설명했습니다. Web Vitals 커넥터를 통해 데이터를 최대한 쉽게 시각화할 수 있습니다

이 게시물의 핵심 내용은 다음과 같습니다.

  • 실제 사용자 데이터로 실적을 측정하는 것은 디버깅 및 최적화에 대해 알아보도록 하겠습니다.
  • 실적 측정항목과 비즈니스 실적 비교 시 더욱 자세하고 유용한 정보를 얻을 수 있습니다. 모두 동일한 시스템에 있습니다 Google 애널리틱스와 BigQuery는 있습니다.
  • Google 애널리틱스 원시 데이터를 BigQuery로 내보내면 심층적인 맞춤 분석을 할 수 있습니다.
  • Google은 Looker Studio와 같은 다양한 API 및 시각화 도구를 제공하여 원하는 대로 정확하게 보고서를 작성할 수 있습니다. 빌드되었습니다.