关于 gtm-setup
gtm-setup 是 Google Tag Manager 事件跟踪参考技能,面向需要实现跟踪或配置标签、触发器和变量的营销人员与开发者,并提供示例和排错指导。
主要功能
- 01dataLayer 事件示例
- 02触发器与变量参考
- 03GA4 标签配置指导
- 04调试与故障排查
- 05实施最佳实践
适用场景
- 01设置电商事件跟踪
- 02配置 SPA 页面变化触发器
- 03在 GTM Preview 中调试标签
- 04将 dataLayer 值映射到 GA4 事件
MCP 相关
如果可用 Cogny GTM MCP 工具,该技能可检查 GTM 容器中的标签、触发器和变量。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ cognyai/ claude-code-marketing-skills --skill gtm-setup安装后在 Claude Code 中输入/gtm-setup确认已加载。
详细介绍
GTM 事件跟踪与设置参考
Google Tag Manager 事件跟踪完整参考指南,包括 dataLayer 基础知识、触发器和变量类型、GA4 标签配置、调试模式以及实施最佳实践。
完整文档:https://cogny.com/docs/gtm-event-tracking
用法
/gtm-setup # Full GTM reference overview
/gtm-setup dataLayer # dataLayer fundamentals and syntax
/gtm-setup purchase # Show purchase event dataLayer.push()
/gtm-setup triggers # All trigger types explained
/gtm-setup variables # All variable types explained
/gtm-setup tags # GA4 tag configuration
/gtm-setup debug # Debug mode and troubleshooting
/gtm-setup best practices # Naming conventions, organization
/gtm-setup common mistakes # Race conditions, missing data, duplicates
说明
你是 Google Tag Manager 专家。请使用此参考帮助用户实施事件跟踪、配置标签/触发器/变量、调试 GTM 问题并遵循最佳实践。
用户提问时,请查找下方的相关章节,并提供准确、可操作且可直接使用的代码片段。
如果用户提供了具体主题作为参数,请重点介绍该主题。否则,请概述 GTM 概念,并询问用户需要什么帮助。
如果有 Cogny GTM MCP 工具可用,请使用这些工具检查用户实际的 GTM 容器,列出其标签/触发器/变量,并根据其真实配置提供建议。
dataLayer 基础知识
什么是 dataLayer?
dataLayer 是一个 JavaScript 数组,充当网站与 GTM 之间的消息总线。将对象推送到 dataLayer 后,GTM 会读取这些对象以触发触发器并填充变量。
初始化
在 GTM 代码段之前声明 dataLayer,以捕获早期推送的数据:
<script>
window.dataLayer = window.dataLayer || [];
</script>
dataLayer.push() 语法
// Push data AND fire a trigger (event key is required for trigger evaluation)
dataLayer.push({
'event': 'custom_event_name',
'key1': 'value1',
'key2': 'value2'
});
// Push data without firing a trigger (no 'event' key)
dataLayer.push({
'user_type': 'premium',
'user_id': '12345'
});
对象持久化与合并
后续推送的值会覆盖先前的值。嵌套对象采用浅合并(会替换整个嵌套对象,而非进行深度合并):
dataLayer.push({ 'user': { 'name': 'John', 'plan': 'free' } });
dataLayer.push({ 'user': { 'plan': 'premium' } });
// Result: user = { plan: 'premium' } — user.name is GONE
清除过期数据(对电商至关重要)
在电商事件之前始终推送 null,以防过期数据造成污染:
dataLayer.push({ ecommerce: null });
dataLayer.push({
'event': 'view_item',
'ecommerce': {
'items': [{ 'item_id': 'SKU-001', 'item_name': 'Blue T-Shirt', 'price': 29.99 }]
}
});
常见的 dataLayer 事件
page_view
dataLayer.push({
'event': 'page_view',
'page_location': window.location.href,
'page_title': document.title,
'page_referrer': document.referrer,
'content_group': 'blog'
});
对于 SPA(React、Next.js、Vue),请在路由变更时触发:
useEffect(() => {
dataLayer.push({
'event': 'page_view',
'page_location': window.location.href,
'page_title': document.title
});
}, [location.pathname]);
purchase
dataLayer.push({ ecommerce: null });
dataLayer.push({
'event': 'purchase',
'ecommerce': {
'transaction_id': 'T-20250211-001',
'value': 149.97,
'tax': 12.50,
'shipping': 5.99,
'currency': 'USD',
'coupon': 'SUMMER20',
'items': [
{
'item_id': 'SKU-001',
'item_name': 'Blue T-Shirt',
'item_brand': 'BrandName',
'item_category': 'Apparel',
'item_category2': 'T-Shirts',
'item_variant': 'Blue',
'price': 29.99,
'quantity': 2
},
{
'item_id': 'SKU-045',
'item_name': 'Running Shoes',
'item_brand': 'BrandName',
'item_category': 'Footwear',
'item_variant': 'Black/Size-10',
'price': 89.99,
'quantity': 1
}
]
}
});
add_to_cart
dataLayer.push({ ecommerce: null });
dataLayer.push({
'event': 'add_to_cart',
'ecommerce': {
'currency': 'USD',
'value': 29.99,
'items': [{
'item_id': 'SKU-001',
'item_name': 'Blue T-Shirt',
'item_brand': 'BrandName',
'item_category': 'Apparel',
'price': 29.99,
'quantity': 1
}]
}
});
remove_from_cart
dataLayer.push({ ecommerce: null });
dataLayer.push({
'event': 'remove_from_cart',
'ecommerce': {
'currency': 'USD',
'value': 29.99,
'items': [{
'item_id': 'SKU-001',
'item_name': 'Blue T-Shirt',
'price': 29.99,
'quantity': 1
}]
}
});
view_item
dataLayer.push({ ecommerce: null });
dataLayer.push({
'event': 'view_item',
'ecommerce': {
'currency': 'USD',
'value': 29.99,
'items': [{
'item_id': 'SKU-001',
'item_name': 'Blue T-Shirt',
'item_brand': 'BrandName',
'item_category': 'Apparel',
'price': 29.99
}]
}
});
view_item_list
dataLayer.push({ ecommerce: null });
dataLayer.push({
'event': 'view_item_list',
'ecommerce': {
'item_list_id': 'category_apparel',
'item_list_name': 'Apparel',
'items': [
{ 'item_id': 'SKU-001', 'item_name': 'Blue T-Shirt', 'index': 0, 'price': 29.99 },
{ 'item_id': 'SKU-002', 'item_name': 'Red T-Shirt', 'index': 1, 'price': 29.99 }
]
}
});
begin_checkout
dataLayer.push({ ecommerce: null });
dataLayer.push({
'event': 'begin_checkout',
'ecommerce': {
'currency': 'USD',
'value': 149.97,
'coupon': 'SUMMER20',
'items': [
{ 'item_id': 'SKU-001', 'item_name': 'Blue T-Shirt', 'price': 29.99, 'quantity': 2 },
{ 'item_id': 'SKU-045', 'item_name': 'Running Shoes', 'price': 89.99, 'quantity': 1 }
]
}
});
form_submit
dataLayer.push({
'event': 'form_submit',
'form_id': 'contact_form',
'form_name': 'Contact Us',
'form_destination': '/thank-you'
});
generate_lead
dataLayer.push({
'event': 'generate_lead',
'currency': 'USD',
'value': 50.00,
'lead_source': 'contact_form'
});
sign_up / login
dataLayer.push({ 'event': 'sign_up', 'method': 'google' });
dataLayer.push({ 'event': 'login', 'method': 'email' });
search
dataLayer.push({
'event': 'search',
'search_term': 'blue t-shirt',
'search_results_count': 42
});
scroll(自定义)
dataLayer.push({
'event': 'scroll',
'percent_scrolled': 90
});
视频事件
// video_start
dataLayer.push({
'event': 'video_start',
'video_title': 'Product Demo',
'video_url': 'https://youtube.com/watch?v=abc123',
'video_provider': 'youtube',
'video_duration': 180
});
// video_progress
dataLayer.push({
'event': 'video_progress',
'video_title': 'Product Demo',
'video_percent': 50,
'video_current_time': 90,
'video_duration': 180
});
// video_complete
dataLayer.push({
'event': 'video_complete',
'video_title': 'Product Demo',
'video_duration': 180
});
触发器类型
页面浏览触发器
| 子类型 | 触发时机 | 用例 |
|---|---|---|
| 页面浏览 | gtm.js(立即) | GA4 配置标签、同意状态检查 |
| DOM 就绪 | gtm.dom(DOM 已解析) | 读取 DOM 元素的标签 |
| 窗口已加载 | gtm.load(所有资源已加载) | 依赖图片/脚本的标签 |
可按 Page Path、Page Hostname 或 Page URL 筛选。
点击触发器
| 子类型 | 触发时机 | 用例 |
|---|---|---|
| 所有元素 | 点击任意元素 | 按钮、div、图片 |
| 仅链接 | 点击 <a> 元素 | 外部链接、下载 |
可用变量:Click Element、Click Classes、Click ID、Click Target、Click URL、Click Text。
自定义事件触发器
当特定的 event 值被推送到 dataLayer 时触发。将 Event Name 设置为与 event 键值匹配。支持正则表达式(例如 form_submit.*)。
dataLayer.push({ 'event': 'form_submit' });
// Fires trigger where Event Name = "form_submit"
元素可见性触发器
元素进入视口时触发。
| 设置 | 说明 |
|---|---|
| 选择方法 | CSS 选择器或元素 ID |
| 触发时机 | 每页一次/每个元素一次/每次 |
| 最小可见比例 | 默认为 50% |
| 最小屏幕显示时长 | 毫秒 |
计时器触发器
按设定的间隔(毫秒)触发。可设置上限,以限制触发次数。
滚动深度触发器
在指定的滚动阈值(百分比或像素)触发。支持垂直和水平滚动。
变量:Scroll Depth Threshold、Scroll Depth Units、Scroll Direction。
YouTube 视频触发器
内置支持嵌入式 YouTube 视频。捕获:开始、完成、暂停、拖动进度、缓冲、进度(可配置阈值)。
变量:视频提供方、视频状态、视频 URL、视频标题、视频时长、视频当前时间、视频百分比、视频是否可见。
表单提交触发器
在表单提交时触发。选项:等待代码(将提交延迟最多 2000ms)、检查验证(仅在通过浏览器验证时触发)。
变量:表单元素、表单类名、表单 ID、表单目标、表单 URL、表单文本。
历史记录更改触发器
在 URL 片段更改或 pushState/replaceState 时触发。对 SPA 至关重要。
变量:新的历史记录片段、旧的历史记录片段、新的历史记录状态、旧的历史记录状态、历史记录来源。
触发器组
组合多个触发器。只有当组中的所有触发器在页面生命周期内至少触发过一次时,代码才会触发。
变量类型
数据层变量
按键名从 dataLayer 读取值。对于嵌套值,请使用点号表示法(例如,ecommerce.transaction_id)。始终使用 Version 2。
JavaScript 变量
读取全局 JS 变量(例如,document.title、navigator.language)。
DOM 元素变量
通过 CSS 选择器或 ID 读取 DOM 元素的文本内容或属性。
URL 变量
提取 URL 组件:完整 URL、协议、主机名、端口、路径、查询(可选查询键)、片段。
常量变量
存储固定值。用于在多个代码之间共享的 Measurement ID、Pixel ID 和配置字符串。
自定义 JavaScript 变量
运行匿名函数并返回其值:
// Get viewport width
function() {
return window.innerWidth;
}
// Classify page type from URL
function() {
var path = window.location.pathname;
if (path === '/') return 'homepage';
if (path.indexOf('/product/') === 0) return 'product';
if (path.indexOf('/category/') === 0) return 'category';
if (path.indexOf('/blog/') === 0) return 'blog';
if (path.indexOf('/checkout') === 0) return 'checkout';
return 'other';
}
// Read a cookie
function() {
var match = document.cookie.match(new RegExp('(^| )user_segment=([^;]+)'));
return match ? match[2] : undefined;
}
查找表变量
将输入值(来自另一个变量)映射到输出值。例如:页面路径 / 映射为 Homepage,/pricing 映射为 Pricing。
正则表达式表变量
与查找表类似,但使用正则表达式模式。例如:^/product/.* 映射为 Product Page。支持捕获组和大小写敏感设置。
代码类型
GA4 配置代码
设置 GA4 测量数据流。在所有页面触发。
| 设置 | 描述 |
|---|---|
| Measurement ID | G-XXXXXXXXXX(使用常量变量) |
| Send page_view | 加载时自动发送 page_view |
| Fields to Set | debug_mode、send_page_view、user_id |
| User Properties | 用户级维度 |
GA4 事件代码
向 GA4 发送自定义事件。
| 设置 | 描述 |
|---|---|
| Configuration Tag | 你的 GA4 配置代码 |
| Event Name | GA4 事件名称(例如,generate_lead) |
| Event Parameters | 键值对(例如,transaction_id、value) |
自定义 HTML 代码
运行任意 HTML/JavaScript。始终使用 try/catch 包裹:
<script>
(function() {
try {
thirdPartySDK.track('event', { value: {{DLV - Value}} });
} catch (e) {
console.warn('GTM Custom HTML error:', e);
}
})();
</script>
自定义图片代码
触发像素请求(1x1 图片)。使用跟踪参数配置图片 URL。启用缓存清除。
内置变量
点击变量
点击元素、点击类名、点击 ID、点击目标、点击 URL、点击文本
表单变量
表单元素、表单类名、表单 ID、表单目标、表单 URL、表单文本
页面变量
页面 URL、页面主机名、页面路径、引荐来源
滚动变量
滚动深度阈值、滚动深度单位、滚动方向
视频变量
视频提供方、视频状态、视频 URL、视频标题、视频时长、视频当前时间、视频百分比、视频是否可见
实用工具变量
事件、环境名称、容器 ID、容器版本、HTML ID、随机数、调试模式
调试模式
GTM 预览/调试
在 GTM 工作区中点击“Preview”。Tag Assistant 会打开并显示:
- 每个事件触发的代码 / 未触发的代码
- 每个事件发生时的 dataLayer 状态
- 变量及其解析后的值
控制台检查
// View entire dataLayer
console.table(dataLayer);
// Filter for specific events
dataLayer.filter(function(item) { return item.event === 'purchase'; });
// Watch pushes in real time
(function() {
var orig = dataLayer.push;
dataLayer.push = function() {
console.log('dataLayer.push:', arguments[0]);
return orig.apply(dataLayer, arguments);
};
})();
GA4 DebugView
在 GA4 Config 代码的字段中添加 debug_mode: true,然后前往 GA4 Admin > DebugView 查看事件。
网络面板
在 DevTools 网络面板中按 collect 筛选,查看 GA4 请求。验证负载参数。
最佳实践
命名规范
| 元素 | 规范 | 示例 |
|---|---|---|
| 标签 | [Platform] - [Action] - [Detail] | GA4 - Event - Purchase |
| 触发器 | [Type] - [Condition] | CE - form_submit |
| 变量 | [Type prefix] - [Name] | DLV - Transaction ID |
| 自定义事件 | snake_case | generate_lead |
| 文件夹 | 按平台或功能分类 | GA4、Meta、Consent |
文件夹组织
GA4/
GA4 - Config - All Pages
GA4 - Event - Purchase
GA4 - Event - Add to Cart
Meta/
Meta - Pixel - Base Code
Meta - Event - Purchase
Consent/
HTML - Consent Banner Init
HTML - Consent Mode Update
工作区管理
- 为每个项目使用功能工作区(例如,
Q1-2025-GA4-ecommerce) - 创建版本前始终先预览
- 删除或合并未使用的工作区
版本控制
- 在重大更改前后创建版本
- 编写描述性版本名称:“v42 - 添加了 GA4 电商结账漏斗”
- 如果发布后出现问题,请回滚
标签排序
使用标签排序,确保设置标签先于依赖它的标签触发。如果同一触发器上的顺序很重要,请使用标签触发优先级(数字越大,越先触发)。
Consent Mode v2
// Default (before user choice)
dataLayer.push({
'event': 'consent_default',
'consent': {
'ad_storage': 'denied',
'analytics_storage': 'denied',
'ad_user_data': 'denied',
'ad_personalization': 'denied'
}
});
// After user grants consent
dataLayer.push({
'event': 'consent_update',
'consent': {
'ad_storage': 'granted',
'analytics_storage': 'granted',
'ad_user_data': 'granted',
'ad_personalization': 'granted'
}
});
常见错误
1. 竞态条件
标签在 dataLayer 包含所需数据之前触发。解决方法:使用与特定 event 推送关联的自定义事件触发器,而非页面浏览触发器。
2. 触发器触发不正确
标签在所有页面触发,而不是仅在特定页面触发。解决方法:始终添加触发器过滤条件(例如,Page Path 等于 /thank-you)。
3. 缺少电商数据空值重置
之前推送的陈旧数据污染了事件。解决方法:在电商事件前始终执行 dataLayer.push({ ecommerce: null })。
4. 标签重复
同一事件被发送多次。原因:存在多个触发器、条件过于宽泛或触发选项错误。解决方法:使用“每页一次”,或检查触发器条件。
5. 自定义 HTML 导致页面故障
自定义 HTML 中的 JS 错误会阻止其他标签运行。解决方法:将所有自定义 HTML 包装在 try/catch 中。
6. 数据层变量返回 Undefined
原因:键名不匹配(区分大小写)、触发器触发后才推送数据、DLV 版本错误或点号路径不正确。
7. 未跟踪 SPA 页面浏览
未捕获路由更改。解决方法:使用历史记录更改触发器,或在路由更改时推送自定义 page_view 事件:
// Next.js App Router
'use client';
import { usePathname } from 'next/navigation';
import { useEffect } from 'react';
export function GTMPageView() {
const pathname = usePathname();
useEffect(() => {
dataLayer.push({
'event': 'page_view',
'page_location': window.location.href,
'page_title': document.title
});
}, [pathname]);
return null;
}
8. 跨域跟踪问题
用户在不同域名下被计为新会话。解决方法:在 GA4 Config 标签中配置跨域链接器,或前往 GA4 Admin > Data Streams > Configure your domains 进行配置。
9. 预览流量导致分析数据膨胀
解决方法:添加阻止型触发器,条件为 Debug Mode 等于 true;或通过 traffic_type 参数过滤内部流量。
资源
- GTM 开发者指南: https://developers.google.com/tag-platform/tag-manager
- GA4 事件参考: https://developers.google.com/analytics/devguides/collection/ga4/reference/events
- GTM 社区图库: https://tagmanager.google.com/gallery
- Consent Mode: https://developers.google.com/tag-platform/security/guides/consent
- Cogny 完整文档: https://cogny.com/docs/gtm-event-tracking