gtm-testing

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

GTM Testing - Validation & Debugging

GTM测试 - 验证与调试

Guide users through comprehensive testing of GTM tracking implementation. Prefers automated headless testing over manual steps wherever possible.
引导用户完成GTM跟踪实现的全面测试。在任何可行的情况下,优先选择自动化无头测试而非手动步骤。

Testing Philosophy

测试理念

Four-tier validation approach, ordered by automation level:
  • Tier 0 (Automated): Playwright headless tests (no browser needed, fully automated)
  • Tier 1 (Manual): Browser Console dataLayer verification
  • Tier 2 (Manual): GTM Preview Mode tag firing verification
  • Tier 3 (Manual): GA4 DebugView end-to-end verification
Always start with Tier 0 if the user asks "can you do it yourself" or wants automated testing. Fall back to manual tiers only for GTM container and GA4 validation, which require a browser session.

采用四级验证方法,按自动化程度排序:
  • Tier 0(自动化):Playwright无头测试(无需浏览器,完全自动化)
  • Tier 1(手动):浏览器控制台dataLayer验证
  • Tier 2(手动):GTM预览模式标签触发验证
  • Tier 3(手动):GA4 DebugView端到端校验
如果用户询问「能否自动完成」或需要自动化测试,始终从Tier 0开始。仅在需要验证GTM容器和GA4配置(需要浏览器会话)时,才退回到手动层级。

Tier 0: Automated Playwright Testing (Preferred)

Tier 0:自动化Playwright测试(优先推荐)

Run this tier first. It requires no browser interaction from the user and can be run entirely by Claude.
首先运行此层级。无需用户进行浏览器交互,可由Claude完全自动执行。

Prerequisites Check

前置检查

bash
undefined
bash
undefined

Check if Playwright is installed

Check if Playwright is installed

npx playwright --version
npx playwright --version

If not installed as a project dependency:

If not installed as a project dependency:

npm install --save-dev playwright npx playwright install chromium
npm install --save-dev playwright npx playwright install chromium

Check if dev server is running

Check if dev server is running

curl -s -o /dev/null -w "%{http_code}" http://localhost:3000
curl -s -o /dev/null -w "%{http_code}" http://localhost:3000

If not running, start it:

If not running, start it:

npm run dev

npm run dev

undefined
undefined

Core Helper: captureDataLayerEvents

核心辅助函数:captureDataLayerEvents

This helper intercepts all
dataLayer.push()
calls during an action and returns the captured events. Use it in every test.
javascript
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 || []);
}
该辅助函数会拦截操作过程中所有
dataLayer.push()
调用,并返回捕获到的事件。所有测试中都应使用此函数。
javascript
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 || []);
}

Key Patterns for Common Element Types

常见元素类型的关键操作模式

Next.js Link components (navigation, course buttons): Do NOT use
page.click()
— it triggers navigation before the onClick handler fires. Use
dispatchEvent
instead:
javascript
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);
Outbound links (href to external domains): Block the navigation so the page stays loaded while the event fires:
javascript
await page.route('**github.com**', route => route.abort());
// Then use dispatchEvent as above
Regular buttons and internal actions: Standard click works fine:
javascript
await page.locator('#element-id').click({ force: true });
Next.js Link组件(导航、课程按钮): 请勿使用
page.click()
——它会在onClick处理器触发前触发导航。请改用
dispatchEvent
javascript
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): 阻止导航,以便在事件触发时页面保持加载状态:
javascript
await page.route('**github.com**', route => route.abort());
// Then use dispatchEvent as above
常规按钮与内部操作: 标准点击即可正常工作:
javascript
await page.locator('#element-id').click({ force: true });

Test Script Template

测试脚本模板

Create
scripts/test-tracking.js
in the project root:
javascript
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); });
在项目根目录创建
scripts/test-tracking.js
javascript
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); });

Finding Correct Element Selectors

查找正确的元素选择器

Before writing tests, always inspect what's actually rendered. Use this discovery script:
javascript
// 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));
在编写测试前,务必检查实际渲染的内容。使用以下发现脚本:
javascript
// 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));

Validating GTM Container Configuration via API

通过API验证GTM容器配置

Before running browser tests, verify the GTM container itself is correctly configured. This catches orphaned trigger references and missing measurement IDs.
javascript
// 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
Critical GTM API bug to watch for: The
gaawe
(GA4 Event) tag type uses
measurementIdOverride
and
eventSettingsTable
(not
measurementId
or
eventParameters
). The correct parameter structure is:
javascript
// 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}}' },
          ],
        },
      ],
    },
  ],
}
在运行浏览器测试前,先验证GTM容器本身是否配置正确。这可以捕获孤立的触发器引用和缺失的测量ID。
javascript
// 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关键bug:
gaawe
(GA4事件)标签类型使用
measurementIdOverride
eventSettingsTable
(而非
measurementId
eventParameters
)。正确的参数结构如下:
javascript
// 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}}' },
          ],
        },
      ],
    },
  ],
}

Running and Interpreting Results

运行与结果解读

bash
node scripts/test-tracking.js
Exit code
0
= all tests passed. Exit code
1
= failures exist.
Result types:
  • PASS
    - Event fired with correct parameters
  • FAIL
    - Event did not fire, or required element not found
  • WARN
    - Component has tracking code but is not rendered on any page yet (not a bug)
Common failure causes and fixes:
FailureCauseFix
dataLayer not found
GTM snippet missing from
<head>
Add GTM container snippet to layout
Event didn't fireElement uses wrong selector in testUse discovery script to find real ID/class
Event fired but page unloadedClicking a Next.js
<Link>
Use
dispatchEvent
not
page.click()
Outbound click not capturedPage navigated away before captureUse
page.route()
to block external navigation
No events on page loadGTM base tag has orphaned trigger referenceFix via GTM API or UI - re-assign to Page View trigger

bash
node scripts/test-tracking.js
退出码
0
= 所有测试通过。退出码
1
= 存在失败项。
结果类型:
  • PASS
    - 事件触发且参数正确
  • FAIL
    - 事件未触发,或未找到所需元素
  • WARN
    - 组件包含跟踪代码但尚未在任何页面上渲染(不属于bug)
常见失败原因与修复方案:
失败情况原因修复方案
dataLayer not found
<head>
中缺少GTM代码段
将GTM容器代码段添加到布局文件中
Event didn't fire测试中使用了错误的选择器使用发现脚本查找真实的ID/类名
Event fired but page unloaded点击Next.js
<Link>
使用
dispatchEvent
而非
page.click()
Outbound click not captured捕获前页面已导航离开使用
page.route()
阻止外部导航
No events on page loadGTM基础标签存在孤立的触发器引用通过GTM API或UI修复 - 重新分配到Page View触发器

Tier 1: Browser Console Testing (Manual)

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

Use when you want to manually verify events while interacting with the site.
当你想要在与站点交互时手动验证事件时使用此方法。

Step 1: Check dataLayer Exists

步骤1:检查dataLayer是否存在

javascript
window.dataLayer
// Expected: [...] array
// If undefined: GTM not installed
javascript
window.dataLayer
// Expected: [...] array
// If undefined: GTM not installed

Step 2: Monitor dataLayer in Real-Time

步骤2:实时监控dataLayer

javascript
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
javascript
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

Step 3: Test Each Event

步骤3:测试每个事件

Click elements one at a time and verify the console output matches expected:
Expected for cta_click:
{
  event: "cta_click",
  cta_location: "hero",
  cta_type: "primary",
  cta_text: "Start Course",
  cta_destination: "/claude-code"
}
逐个点击元素,验证控制台输出是否与预期一致:
Expected for cta_click:
{
  event: "cta_click",
  cta_location: "hero",
  cta_type: "primary",
  cta_text: "Start Course",
  cta_destination: "/claude-code"
}

Validation Checklist - Tier 1

验证清单 - Tier 1

  • window.dataLayer
    is an array
  • GTM bootstrap event (
    gtm.start
    ) present
  • Each event fires with correct
    event
    name
  • All required parameters present and non-empty
  • No duplicate events on single click
  • No JavaScript errors in console

  • window.dataLayer
    是一个数组
  • 存在GTM引导事件(
    gtm.start
  • 每个事件都以正确的
    event
    名称触发
  • 所有必填参数均存在且非空
  • 单次点击不会触发重复事件
  • 控制台中无JavaScript错误

Tier 2: GTM Preview Mode (Manual)

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

Confirms the GTM container receives events and fires tags. Requires GTM UI access.
确认GTM容器接收事件并触发标签。需要GTM UI访问权限。

Setup

设置步骤

  1. Go to tagmanager.google.com
  2. Select container
  3. Click Preview
  4. Enter site URL, click Connect
  5. A debug panel appears at the bottom of your site
  1. 访问tagmanager.google.com
  2. 选择容器
  3. 点击预览
  4. 输入站点URL,点击连接
  5. 站点底部会出现一个调试面板

What to Verify

验证内容

For each event, the Preview panel should show:
Event fired: "cta_click"
  Triggers: CE - CTA Click  [FIRED]
  Tags:      GA4 - CTA Click [FIRED]
Click a fired tag to verify:
  • measurementIdOverride
    has the correct GA4 ID
  • All event parameters are populated (not empty
    {{DL - ...}}
    strings)
对于每个事件,预览面板应显示:
Event fired: "cta_click"
  Triggers: CE - CTA Click  [FIRED]
  Tags:      GA4 - CTA Click [FIRED]
点击已触发的标签以验证:
  • measurementIdOverride
    包含正确的GA4 ID
  • 所有事件参数均已填充(非空的
    {{DL - ...}}
    字符串)

Validation Checklist - Tier 2

验证清单 - Tier 2

  • Preview mode connects successfully
  • GA4 Configuration tag fires on page load (not orphaned)
  • Each custom event appears in the event list
  • Correct trigger fires for each event
  • Correct tag fires for each trigger
  • Tag parameters show resolved values (not unresolved variable references)
  • No tags firing unexpectedly

  • 预览模式连接成功
  • GA4配置标签在页面加载时触发(非孤立状态)
  • 每个自定义事件都出现在事件列表中
  • 每个事件都触发了正确的触发器
  • 每个触发器都触发了正确的标签
  • 标签参数显示解析后的值(非未解析的变量引用)
  • 无意外触发的标签

Tier 3: GA4 DebugView (Manual)

Tier 3:GA4 DebugView(手动)

Confirms events reach GA4 with correct parameters. Requires GA4 property access.
确认事件已正确传递到GA4且参数正确。需要GA4属性访问权限。

Enable Debug Mode

启用调试模式

Option A - URL parameter: append
?debug_mode=true
to the page URL
Option B - Chrome extension: install Google Analytics Debugger, enable it
选项A - URL参数:在页面URL后追加
?debug_mode=true
选项B - Chrome扩展:安装Google Analytics Debugger并启用

Open DebugView

打开DebugView

GA4 > Admin > Property > DebugView
Events appear in real time as you interact with the site.
GA4 > 管理 > 属性 > DebugView
当你与站点交互时,事件会实时显示。

What to Verify

验证内容

  • Event name appears (e.g.,
    cta_click
    )
  • All parameters visible with correct values
  • page_view
    event fires on every page navigation
  • Event count increments on repeated actions
  • 事件名称显示(例如
    cta_click
  • 所有参数可见且值正确
  • 每次页面导航时
    page_view
    事件都会触发
  • 重复操作时事件计数递增

Validation Checklist - Tier 3

验证清单 - Tier 3

  • page_view
    events firing on all pages
  • Custom events appear within 1-3 seconds of firing
  • All event parameters visible and correctly valued
  • Events attributed to correct page paths
  • No unexpected events

  • page_view
    事件在所有页面上触发
  • 自定义事件在触发后1-3秒内显示
  • 所有事件参数可见且值正确
  • 事件被归因到正确的页面路径
  • 无意外事件

Common Issues Reference

常见问题参考

IssueTier FoundCauseFix
dataLayer
undefined
1GTM snippet missingAdd GTM snippet to
<head>
Event fires, trigger doesn't2Event name mismatch (case-sensitive)Confirm trigger uses
{{_event}}
equals exact event name
Trigger fires, tag doesn't2Orphaned trigger or misconfigured tagCheck tag has valid firing trigger assigned
Page View tag never fires2Orphaned trigger reference on base tagRe-assign base tag to a valid Page View trigger
Parameters show as
{{DL - X}}
2Data Layer Variable not createdCreate DLV with correct dataLayer key name
Events in Preview, not DebugView3Wrong GA4 property or debug mode offVerify Measurement ID matches, enable debug mode
Parameters missing in GA43Not mapped in tag's eventSettingsTableAdd parameter mapping in GTM tag config

问题发现层级原因修复方案
dataLayer
undefined
1缺少GTM代码段将GTM代码段添加到
<head>
Event fires, trigger doesn't2事件名称不匹配(区分大小写)确认触发器使用
{{_event}}
等于精确的事件名称
Trigger fires, tag doesn't2孤立的触发器或标签配置错误检查标签是否分配了有效的触发触发器
Page View tag never fires2基础标签存在孤立的触发器引用将基础标签重新分配到有效的Page View触发器
Parameters show as
{{DL - X}}
2未创建数据层变量使用正确的dataLayer键名创建DLV
Events in Preview, not DebugView3GA4属性错误或调试模式未开启验证测量ID匹配,启用调试模式
Parameters missing in GA43未在标签的eventSettingsTable中映射在GTM标签配置中添加参数映射

Full Workflow

完整工作流程

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

1. 运行Tier 0(自动化)
   PASS → 继续发布GTM
   FAIL → 修复代码或GTM配置,重新运行

2. 运行Tier 1(控制台)——可选的手动抽查
   PASS → 继续
   FAIL → 在Tier 2前修复

3. 运行Tier 2(GTM预览)
   PASS → 继续
   FAIL → 修复GTM标签/触发器/变量

4. 运行Tier 3(GA4 DebugView)
   PASS → 发布GTM容器
   FAIL → 修复GA4配置或参数映射

5. 发布GTM → GTM UI > 提交 > 发布版本
6. 在生产环境中禁用调试模式
7. 监控GA4报告 > 互动 > 事件

References

参考资料

  • references/debugging-guide.md
    - Extended issue diagnosis
  • references/test-checklist.md
    - Printable checklist template
  • examples/sample.md
    - Example test run output showing PASS/FAIL/WARN format and common failure fixes
  • Related skills:
    gtm-implementation
    ,
    gtm-analytics-audit
    ,
    gtm-reporting
  • references/debugging-guide.md
    - 扩展问题诊断
  • references/test-checklist.md
    - 可打印的清单模板
  • examples/sample.md
    - 示例测试运行输出,展示PASS/FAIL/WARN格式及常见失败修复方案
  • 相关技能:
    gtm-implementation
    ,
    gtm-analytics-audit
    ,
    gtm-reporting