如何在关联GA4的Google BigQuery中统计页面浏览量与退出次数?
GA4 BigQuery 查询:统计页面浏览量与退出次数
问题描述
在关联GA4的Google BigQuery环境中,需要统计页面浏览量和退出次数(退出次数指会话最后一个事件发生在特定页面的次数,即会话结束于该页面路径的次数)。目前已实现页面浏览量统计,但无法完成退出次数统计,现有代码及数据Schema如下:
现有页面浏览量查询代码
SELECT event_params.value.string_value AS page_path, COUNT(*) AS page_views FROM `MY_ga4_dataset.events_*`, UNNEST(event_params) AS event_params WHERE _table_suffix BETWEEN '20230207' AND '20230207' AND event_name = 'page_view' AND event_params.key = 'page_location' GROUP BY page_path ORDER BY page_views DESC
GA4 BigQuery 数据Schema
| fullname | mode | type | description |
|---|---|---|---|
| event_date | NULLABLE | STRING | |
| event_timestamp | NULLABLE | INTEGER | |
| event_name | NULLABLE | STRING | |
| event_params | REPEATED | RECORD | |
| event_previous_timestamp | NULLABLE | INTEGER | |
| event_value_in_usd | NULLABLE | FLOAT | |
| event_bundle_sequence_id | NULLABLE | INTEGER | |
| event_server_timestamp_offset | NULLABLE | INTEGER | |
| user_id | NULLABLE | STRING | |
| user_pseudo_id | NULLABLE | STRING | |
| privacy_info | NULLABLE | RECORD | |
| user_properties | REPEATED | RECORD | |
| user_first_touch_timestamp | NULLABLE | INTEGER | |
| user_ltv | NULLABLE | RECORD | |
| device | NULLABLE | RECORD | |
| geo | NULLABLE | RECORD | |
| app_info | NULLABLE | RECORD | |
| traffic_source | NULLABLE | RECORD | |
| stream_id | NULLABLE | STRING | |
| platform | NULLABLE | STRING | |
| event_dimensions | NULLABLE | RECORD | |
| ecommerce | NULLABLE | RECORD | |
| items | REPEATED | RECORD | |
| event_params.key | NULLABLE | STRING | |
| event_params.value | NULLABLE | RECORD | |
| event_params.value.string_value | NULLABLE | STRING | |
| event_params.value.int_value | NULLABLE | INTEGER | |
| event_params.value.float_value | NULLABLE | FLOAT | |
| event_params.value.double_value | NULLABLE | FLOAT | |
| privacy_info.analytics_storage | NULLABLE | STRING | |
| privacy_info.ads_storage | NULLABLE | STRING | |
| privacy_info.uses_transient_token | NULLABLE | STRING | |
| user_properties.key | NULLABLE | STRING | |
| user_properties.value | NULLABLE | RECORD | |
| user_properties.value.string_value | NULLABLE | STRING | |
| user_properties.value.int_value | NULLABLE | INTEGER | |
| user_properties.value.float_value | NULLABLE | FLOAT | |
| user_properties.value.double_value | NULLABLE | FLOAT | |
| user_properties.value.set_timestamp_micros | NULLABLE | INTEGER | |
| user_ltv.revenue | NULLABLE | FLOAT | |
| user_ltv.currency | NULLABLE | STRING | |
| device.category | NULLABLE | STRING | |
| device.mobile_brand_name | NULLABLE | STRING | |
| device.mobile_model_name | NULLABLE | STRING | |
| device.mobile_marketing_name | NULLABLE | STRING | |
| device.mobile_os_hardware_model | NULLABLE | STRING | |
| device.operating_system | NULLABLE | STRING | |
| device.operating_system_version | NULLABLE | STRING | |
| device.vendor_id | NULLABLE | STRING | |
| device.advertising_id | NULLABLE | STRING | |
| device.language | NULLABLE | STRING | |
| device.is_limited_ad_tracking | NULLABLE | STRING | |
| device.time_zone_offset_seconds | NULLABLE | INTEGER | |
| device.browser | NULLABLE | STRING | |
| device.browser_version | NULLABLE | STRING | |
| device.web_info | NULLABLE | RECORD | |
| device.web_info.browser | NULLABLE | STRING | |
| device.web_info.browser_version | NULLABLE | STRING | |
| device.web_info.hostname | NULLABLE | STRING | |
| geo.continent | NULLABLE | STRING | |
| geo.country | NULLABLE | STRING | |
| geo.region | NULLABLE | STRING | |
| geo.city | NULLABLE | STRING | |
| geo.sub_continent | NULLABLE | STRING | |
| geo.metro | NULLABLE | STRING | |
| app_info.id | NULLABLE | STRING | |
| app_info.version | NULLABLE | STRING | |
| app_info.install_store | NULLABLE | STRING | |
| app_info.firebase_app_id | NULLABLE | STRING | |
| app_info.install_source | NULLABLE | STRING | |
| traffic_source.name | NULLABLE | STRING | |
| traffic_source.medium | NULLABLE | STRING | |
| traffic_source.source | NULLABLE | STRING | |
| event_dimensions.hostname | NULLABLE | STRING | |
| ecommerce.total_item_quantity | NULLABLE | INTEGER | |
| ecommerce.purchase_revenue_in_usd | NULLABLE | FLOAT | |
| ecommerce.purchase_revenue | NULLABLE | FLOAT | |
| ecommerce.refund_value_in_usd | NULLABLE | FLOAT | |
| ecommerce.refund_value | NULLABLE | FLOAT | |
| ecommerce.shipping_value_in_usd | NULLABLE | FLOAT | |
| ecommerce.shipping_value | NULLABLE | FLOAT | |
| ecommerce.tax_value_in_usd | NULLABLE | FLOAT | |
| ecommerce.tax_value | NULLABLE | FLOAT | |
| ecommerce.unique_items | NULLABLE | INTEGER | |
| ecommerce.transaction_id | NULLABLE | STRING | |
| items.item_id | NULLABLE | STRING | |
| items.item_name | NULLABLE | STRING | |
| items.item_brand | NULLABLE | STRING | |
| items.item_variant | NULLABLE | STRING | |
| items.item_category | NULLABLE | STRING | |
| items.item_category2 | NULLABLE | STRING | |
| items.item_category3 | NULLABLE | STRING | |
| items.item_category4 | NULLABLE | STRING | |
| items.item_category5 | NULLABLE | STRING | |
| items.price_in_usd | NULLABLE | FLOAT | |
| items.price | NULLABLE | FLOAT | |
| items.quantity | NULLABLE | INTEGER | |
| items.item_revenue_in_usd | NULLABLE | FLOAT | |
| items.item_revenue | NULLABLE | FLOAT | |
| items.item_refund_in_usd | NULLABLE | FLOAT | |
| items.item_refund | NULLABLE | FLOAT | |
| items.coupon | NULLABLE | STRING | |
| items.affiliation | NULLABLE | STRING | |
| items.location_id | NULLABLE | STRING | |
| items.item_list_id | NULLABLE | STRING | |
| items.item_list_name | NULLABLE | STRING | |
| items.item_list_index | NULLABLE | STRING | |
| items.promotion_id | NULLABLE | STRING | |
| items.promotion_name | NULLABLE | STRING | |
| items.creative_name | NULLABLE | STRING | |
| items.creative_slot | NULLABLE | STRING |
解决方案
要统计退出次数,核心是先识别每个会话的最后一个事件,再判断该事件是否为page_view并关联对应的页面路径。以下是合并页面浏览量和退出次数的完整查询:
WITH session_last_events AS ( -- 获取每个会话的最后一个事件时间戳 SELECT user_pseudo_id, (SELECT value.int_value FROM UNNEST(event_params) WHERE key = 'ga_session_id') AS session_id, MAX(event_timestamp) AS last_event_timestamp FROM `MY_ga4_dataset.events_*` WHERE _table_suffix BETWEEN '20230207' AND '20230207' GROUP BY user_pseudo_id, session_id ), exit_pages AS ( -- 匹配会话最后事件对应的页面路径(仅统计最后事件为page_view的情况) SELECT ep.value.string_value AS page_path, COUNT(*) AS exits FROM `MY_ga4_dataset.events_*` e JOIN session_last_events sle ON e.user_pseudo_id = sle.user_pseudo_id AND (SELECT value.int_value FROM UNNEST(e.event_params) WHERE key = 'ga_session_id') = sle.session_id AND e.event_timestamp = sle.last_event_timestamp LEFT JOIN UNNEST(e.event_params) ep ON ep.key = 'page_location' WHERE _table_suffix BETWEEN '20230207' AND '20230207' AND e.event_name = 'page_view' GROUP BY page_path ), page_views AS ( -- 复用原有页面浏览量统计逻辑 SELECT event_params.value.string_value AS page_path, COUNT(*) AS page_views FROM `MY_ga4_dataset.events_*`, UNNEST(event_params) AS event_params WHERE _table_suffix BETWEEN '20230207' AND '20230207' AND event_name = 'page_view' AND event_params.key = 'page_location' GROUP BY page_path ) -- 合并浏览量与退出次数,确保所有页面都能展示数据 SELECT COALESCE(p.page_path, e.page_path) AS page_path, COALESCE(p.page_views, 0) AS page_views, COALESCE(e.exits, 0) AS exits FROM page_views p FULL OUTER JOIN exit_pages e ON p.page_path = e.page_path ORDER BY page_views DESC
逻辑说明
- session_last_events:通过
user_pseudo_id(用户标识)和ga_session_id(GA4会话ID)分组,提取每个会话的最后事件时间戳。 - exit_pages:将原始事件表与会话最后事件表关联,筛选出会话最后一个事件是
page_view的记录,统计每个页面的退出次数。 - page_views:直接复用你原有的页面浏览量统计逻辑。
- 最后通过全外连接合并两个结果集,确保所有页面都能展示浏览量和退出次数(无对应数据时显示0)。
注意事项
- 确认
ga_session_id参数存在:GA4默认会在事件中携带该参数,若未找到需检查事件采集配置。 - 统一时间范围:所有CTE中的
_table_suffix过滤条件需保持一致,避免数据不匹配。
内容的提问来源于stack exchange,提问作者John Owen
相关产品推荐
相关产品推荐

