mcpField
G
gtm-testing

gtm-testing

github.com/aimonk2025测试与质量9130 次安装35 周前更新
代码仓库

关于 gtm-testing

用于指导 GTM 跟踪实现测试与故障排查的技能,适合验证网站上的 dataLayer 事件及 GA4 标签。它优先采用 Playwright 自动化测试,并提供从浏览器控制台到 GA4 DebugView 的分层检查流程。

主要功能

  1. 01Playwright 无头自动化测试
  2. 02捕获并检查 dataLayer 事件
  3. 03通过 GTM API 检查容器配置
  4. 04浏览器控制台事件验证
  5. 05GTM Preview 标签检查
  6. 06GA4 DebugView 端到端验证

适用场景

  1. 01自动检查网站跟踪事件
  2. 02定位未触发的 GTM 标签
  3. 03核对事件参数和测量 ID
  4. 04确认事件是否到达 GA4

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/aimonk2025/google-tag-manager-automation --skill gtm-testing

安装后在 Claude Code 中输入/gtm-testing确认已加载。

附带文件examples/sample.md

详细介绍

GTM 测试 - 验证与调试

引导用户全面测试 GTM 跟踪实现。尽可能优先使用自动化无头测试,而不是手动步骤。

测试理念

按自动化程度排序的四级验证方法:

  • 第 0 级(自动化):Playwright 无头测试(无需浏览器,完全自动化)
  • 第 1 级(手动):通过浏览器控制台验证 dataLayer
  • 第 2 级(手动):通过 GTM 预览模式验证标签触发情况
  • 第 3 级(手动):通过 GA4 DebugView 端到端验证

如果用户询问“你能自己完成吗”,或希望进行自动化测试,始终从第 0 级开始。只有在验证 GTM 容器和 GA4 时才退回手动级别,因为这些步骤需要浏览器会话。


阶段 0:加载业务背景(如有)

检查项目根目录中是否存在 gtm-context.md:

  • 如果存在:静默读取,并在本次技能运行过程中使用其中的业务背景(网站类型和已知缺口有助于确定重点验证步骤)
  • 如果不存在:正常继续

此文件由 gtm-analytics-audit 在首次运行结束时自动创建。


第 0 级:自动化 Playwright 测试(首选)

首先运行此级别。无需用户进行任何浏览器交互,Claude 可独立完成。

检查前置条件
# Check if Playwright is installed
npx playwright --version

# If not installed as a project dependency:
npm install --save-dev playwright
npx playwright install chromium

# Check if dev server is running
curl -s -o /dev/null -w "%{http_code}" http://localhost:3000
# If not running, start it:
# npm run dev
核心辅助函数:captureDataLayerEvents

此辅助函数会拦截操作期间所有 dataLayer.push() 调用,并返回捕获到的事件。请在每项测试中使用它。

async function captureDataLayerEvents(page, action) {
  await page.evaluate(() => {
    window.__testEvents = [];
    const original = window.dataLayer.push.bind(window.dataLayer);
    window.dataLayer.push = function (...args) {
      window.__testEvents.push(args[0]);
      return original(...args);
    };
  });

  await action();
  await page.waitForTimeout(300);

  return await page.evaluate(() => window.__testEvents || []);
}
常见元素类型的关键模式

Next.js Link 组件(导航、课程按钮): 不要使用 page.click()——它会在 onClick 处理程序触发前触发导航。请改用 dispatchEvent:

await page.evaluate(() => {
  const btn = document.querySelector('a.js-module_nav');
  if (btn) btn.dispatchEvent(new MouseEvent('click', { bubbles: true, cancelable: true }));
});
await page.waitForTimeout(400);

出站链接(href 指向外部域名): 阻止导航,以便页面在事件触发期间保持加载:

await page.route('**github.com**', route => route.abort());
// Then use dispatchEvent as above

普通按钮和内部操作: 直接使用标准点击即可:

await page.locator('#element-id').click({ force: true });
测试脚本模板

在项目根目录中创建 scripts/test-tracking.js:

const { chromium } = require('playwright');

const BASE_URL = 'http://localhost:3000';
const results = { passed: [], failed: [], warnings: [] };

function pass(test, detail = '') {
  results.passed.push({ test, detail });
  console.log(`  PASS  ${test}${detail ? ' - ' + detail : ''}`);
}
function fail(test, detail = '') {
  results.failed.push({ test, detail });
  console.log(`  FAIL  ${test}${detail ? ' - ' + detail : ''}`);
}
function warn(test, detail = '') {
  results.warnings.push({ test, detail });
  console.log(`  WARN  ${test}${detail ? ' - ' + detail : ''}`);
}

async function captureDataLayerEvents(page, action) {
  await page.evaluate(() => {
    window.__testEvents = [];
    const original = window.dataLayer.push.bind(window.dataLayer);
    window.dataLayer.push = function (...args) {
      window.__testEvents.push(args[0]);
      return original(...args);
    };
  });
  await action();
  await page.waitForTimeout(300);
  return await page.evaluate(() => window.__testEvents || []);
}

async function runTests() {
  const browser = await chromium.launch({ headless: true });
  const context = await browser.newContext();

  console.log('\n=== GTM dataLayer Event Tests ===\n');

  // TEST: dataLayer initialisation
  console.log('Test: dataLayer initialisation');
  {
    const page = await context.newPage();
    await page.goto(BASE_URL, { waitUntil: 'networkidle' });
    const hasDataLayer = await page.evaluate(() => Array.isArray(window.dataLayer));
    hasDataLayer ? pass('dataLayer initialised') : fail('dataLayer not found');
    const gtmEvent = await page.evaluate(() => window.dataLayer.find(e => e['gtm.start']));
    gtmEvent ? pass('GTM bootstrap event present') : fail('GTM bootstrap event missing - container may not be installed');
    await page.close();
  }

  // TEST: cta_click event
  // Adjust selector to match your actual element ID
  console.log('\nTest: cta_click event');
  {
    const page = await context.newPage();
    await page.goto(BASE_URL, { waitUntil: 'networkidle' });
    const events = await captureDataLayerEvents(page, async () => {
      const el = await page.$('#your-cta-id');
      if (el) await page.evaluate(el => el.dispatchEvent(new MouseEvent('click', { bubbles: true })), el);
    });
    const e = events.find(e => e.event === 'cta_click');
    e ? pass('cta_click fired', `location=${e.cta_location}`) : fail('cta_click did not fire');
    await page.close();
  }

  // Add more tests following the same pattern...

  // RESULTS
  await browser.close();
  console.log('\n=== RESULTS ===');
  console.log(`  Passed:   ${results.passed.length}`);
  console.log(`  Failed:   ${results.failed.length}`);
  console.log(`  Warnings: ${results.warnings.length}`);
  if (results.failed.length > 0) {
    console.log('\nFailed:');
    results.failed.forEach(f => console.log(`  - ${f.test}: ${f.detail}`));
  }
  process.exit(results.failed.length > 0 ? 1 : 0);
}

runTests().catch(err => { console.error('Fatal:', err.message); process.exit(1); });
查找正确的元素选择器

编写测试前,务必检查页面实际渲染的内容。使用此发现脚本:

// Add to test script or run as a separate debug script
const page = await context.newPage();
await page.goto(`${BASE_URL}/your-page`, { waitUntil: 'networkidle' });

const tracked = await page.evaluate(() => {
  return Array.from(document.querySelectorAll('[id], .js-track, [data-track]')).map(el => ({
    id: el.id,
    tag: el.tagName,
    class: el.className,
    text: el.textContent.trim().substring(0, 40),
    href: el.getAttribute('href'),
  }));
});
console.log(JSON.stringify(tracked, null, 2));
通过 API 验证 GTM 容器配置

运行浏览器测试前,请确认 GTM 容器本身配置正确。这可以发现孤立的触发器引用和缺失的衡量 ID。

// scripts/audit-gtm-coverage.js
// Uses googleapis + gtm-credentials.json + gtm-token.json + gtm-config.json

// Critical checks:
// 1. Base GA4 config tag (googtag) - must fire on Page View trigger
//    If firingTriggerId references a non-existent trigger, NO pages are tracked
// 2. GA4 event tags (gaawe) - must have measurementIdOverride set
//    Parameter key is "measurementIdOverride" NOT "measurementId"
// 3. All triggers must be used by at least one tag
// 4. All tags must have at least one firing trigger

需要留意的关键 GTM API 错误:gaawe(GA4 Event)标签类型使用 measurementIdOverride 和 eventSettingsTable(而非 measurementId 或 eventParameters)。正确的参数结构如下:

// CORRECT structure for gaawe tags via API
{
  type: 'gaawe',
  parameter: [
    { type: 'boolean', key: 'sendEcommerceData', value: 'false' },
    { type: 'template', key: 'eventName', value: 'your_event_name' },
    { type: 'template', key: 'measurementIdOverride', value: 'G-XXXXXXXXXX' },
    {
      type: 'list',
      key: 'eventSettingsTable',
      list: [
        {
          type: 'map',
          map: [
            { type: 'template', key: 'parameter', value: 'param_name' },
            { type: 'template', key: 'parameterValue', value: '{{DL - Variable Name}}' },
          ],
        },
      ],
    },
  ],
}
运行并解读结果
node scripts/test-tracking.js

退出代码 0 = 所有测试均通过。退出代码 1 = 存在失败项。

结果类型:

  • PASS - 事件已触发,且参数正确
  • FAIL - 事件未触发,或未找到所需元素
  • WARN - 组件包含跟踪代码,但尚未在任何页面上渲染(这不是错误)

常见失败原因及修复方法:

失败情况原因修复方法
dataLayer not found<head> 中缺少 GTM 代码片段将 GTM 容器代码片段添加到布局中
事件未触发测试中使用了错误的元素选择器使用发现脚本查找真实的 ID/类名
事件已触发,但页面已卸载点击了 Next.js <Link>使用 dispatchEvent,而非 page.click()
未捕获出站点击页面在捕获前已跳转使用 page.route() 阻止外部导航
页面加载时没有事件GTM 基础标签引用了孤立的触发器通过 GTM API 或界面修复——重新分配到 Page View 触发器

第 1 级:浏览器控制台测试(手动)

需要在与网站交互时手动验证事件时使用。

步骤 1:检查 dataLayer 是否存在
window.dataLayer
// Expected: [...] array
// If undefined: GTM not installed
步骤 2:实时监控 dataLayer
const _push = window.dataLayer.push.bind(window.dataLayer);
window.dataLayer.push = function(...args) {
  console.log('%c dataLayer.push', 'background:#222;color:#0f0;padding:2px 6px', args[0]);
  return _push(...args);
};
// Now every push is logged in green
步骤 3:测试每个事件

逐个点击元素,并确认控制台输出符合预期:

Expected for cta_click:
{
  event: "cta_click",
  cta_location: "hero",
  cta_type: "primary",
  cta_text: "Start Course",
  cta_destination: "/claude-code"
}
验证清单 - Tier 1
  • window.dataLayer 是一个数组
  • 存在 GTM 引导事件(gtm.start)
  • 每个事件触发时使用正确的 event 名称
  • 所有必需参数均存在且非空
  • 单击时不会重复触发事件
  • 控制台中没有 JavaScript 错误

Tier 2:GTM 预览模式(手动)

确认 GTM 容器接收事件并触发标签。需要访问 GTM UI。

设置
  1. 前往 tagmanager.google.com
  2. 选择容器
  3. 点击 预览
  4. 输入网站 URL,然后点击 连接
  5. 网站底部会出现调试面板
验证内容

对于每个事件,预览面板应显示:

Event fired: "cta_click"
  Triggers: CE - CTA Click  [FIRED]
  Tags:      GA4 - CTA Click [FIRED]

点击已触发的标签以验证:

  • measurementIdOverride 使用了正确的 GA4 ID
  • 所有事件参数均已填充(不是空的 {{DL - ...}} 字符串)
验证清单 - Tier 2
  • 预览模式成功连接
  • 页面加载时触发 GA4 配置标签(没有孤立标签)
  • 事件列表中显示每个自定义事件
  • 每个事件均触发了正确的触发器
  • 每个触发器均触发了正确的标签
  • 标签参数显示已解析的值(不是未解析的变量引用)
  • 没有意外触发的标签

Tier 3:GA4 DebugView(手动)

确认事件已携带正确参数传达到 GA4。需要访问 GA4 媒体资源。

启用调试模式

选项 A - URL 参数:在页面 URL 后追加 ?debug_mode=true

选项 B - Chrome 扩展程序:安装 Google Analytics Debugger 并启用

打开 DebugView

GA4 > 管理员 > 媒体资源 > DebugView

你与网站交互时,事件会实时显示。

验证内容
  • 显示事件名称(例如,cta_click)
  • 显示所有参数及其正确值
  • 每次页面导航时都会触发 page_view 事件
  • 重复操作时事件计数会递增
验证清单 - Tier 3
  • 所有页面均会触发 page_view 事件
  • 自定义事件会在触发后 1-3 秒内显示
  • 所有事件参数均可见且值正确
  • 事件归属于正确的页面路径
  • 没有意外事件

常见问题参考

问题发现层级原因修复方法
dataLayer 未定义1缺少 GTM 代码片段将 GTM 代码片段添加到 <head>
事件已触发,但触发器未触发2事件名称不匹配(区分大小写)确认触发器使用 {{_event}},且等于准确的事件名称
触发器已触发,但标签未触发2触发器孤立或标签配置错误检查标签是否分配了有效的触发器
页面浏览标签从未触发2基础标签上的触发器引用孤立将基础标签重新分配给有效的页面浏览触发器
参数显示为 {{DL - X}}2未创建数据层变量使用正确的 dataLayer 键名创建 DLV
预览中有事件,但 DebugView 中没有3GA4 媒体资源错误或未开启调试模式确认测量 ID 匹配,并启用调试模式
GA4 中缺少参数3未在标签的 eventSettingsTable 中映射在 GTM 标签配置中添加参数映射

完整工作流

1. Run Tier 0 (automated)
   PASS → proceed to publish GTM
   FAIL → fix code or GTM config, re-run

2. Run Tier 1 (console) — optional manual spot-check
   PASS → proceed
   FAIL → fix before Tier 2

3. Run Tier 2 (GTM Preview)
   PASS → proceed
   FAIL → fix GTM tags/triggers/variables

4. Run Tier 3 (GA4 DebugView)
   PASS → publish GTM container
   FAIL → fix GA4 config or parameter mappings

5. Publish GTM → GTM UI > Submit > Publish version
6. Disable debug mode in production
7. Monitor GA4 Reports > Engagement > Events

参考资料

  • references/debugging-guide.md - 扩展版问题诊断指南
  • references/test-checklist.md - 可打印的清单模板
  • examples/sample.md - 测试运行输出示例,展示 PASS/FAIL/WARN 格式和常见故障修复方法
  • 相关技能:gtm-implementation、gtm-analytics-audit、gtm-reporting

评论

支持 Markdown