Files
our-claude-skills/.claude/commands/gtm-validator.md
Andrew Yim c35a28780d feat(gtm): add mandatory knowledge-base read/write directives to GTM skills
Agents must now read client profiles before GTM work and write session
logs after completing audits, tag changes, or validation — ensuring
findings compound across sessions instead of being lost.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 00:03:27 +09:00

120 lines
5.2 KiB
Markdown

---
description: GTM QA - tag firing verification, trigger testing, naming conventions, cross-platform validation
---
# GTM Validator
Verify GTM implementations on live pages. Test triggers, validate dataLayer, check naming conventions.
## Pre-Flight
**BEFORE starting validation**, read the relevant gotcha files at:
`~/Project/dintel-gtm-agent/docs/log/gotcha/` (see `README.md` for index)
Priority reads per task:
- **Trigger validation** → `gotcha/triggers.md` + `gotcha/regex.md`
- **Post-API-change QA** → `gotcha/compilation.md`
- **Variable inspection** → `gotcha/variables.md`
## Triggers
- "validate tags", "QA GTM", "debug GTM"
- "naming conventions", "GTM best practice"
## MANDATORY: Knowledge Base Read/Write
**Before starting any validation or QA:**
1. Identify the target client from container ID or URL
2. Read `knowledge-base/accounts/<client>/profile.md` — naming conventions, known issues, platform stack
3. Read `knowledge-base/accounts/<client>/*.md` — taxonomy defines expected events; naming fix plans reveal known violations
4. Skim `knowledge-base/logs/<client>/` — past QA reveals recurring issues and known false positives
**After completing validation, write a session log:**
- Write to `knowledge-base/logs/<client>/YYYY-MM-DD-<description>.md`
- Include: date, container ID, pass/fail results, broken triggers (IDs), new naming violations
- Update `knowledge-base/accounts/<client>/profile.md` if you discovered persistent facts
- See `AGENTS.md` for full format template
## Validation Modes
### 1. Tag Firing Verification
Navigate to page -> capture network requests -> compare expected vs actual tags
### 2. Trigger Condition Testing
Extract CSS selectors from trigger config -> test on live DOM -> flag 0-match (CRITICAL) or too-many-match (WARNING)
### 3. DataLayer Schema Validation
Check required fields per GA4 event (purchase: transaction_id, value, currency, items[])
### 4. Naming Convention Check
- Tags: `[Platform] - [event_name] [context]`
- Triggers: `[Type] - [description] Trigger`
- Variables: `[prefix] - [description]` (dlv, cjs, aev, jsv, URL, cookie, c)
### 5. Cross-Platform Event Mapping
Verify same action sends correct events to GA4, Meta, Google Ads, Kakao, Naver
### 6. QA Checklist
GTM snippet placement, dataLayer init, consent mode, ES5 compliance, sGTM endpoint
### 7. Version Comparison
Compare tag counts and changes between container versions
## Gotchas (Hard-Won Lessons)
### GTM Has Two Validation Layers — API CRUD vs Preview/Publish
GTM API validates **schema only** during create/update calls (field names, types, required params). Regex patterns are stored as opaque strings and **never compiled** at edit time. Preview/Publish performs **full container compilation** — all regex is compiled by Google RE2, all variable references resolved, cross-resource dependencies checked. A resource can pass API validation but break Preview.
**Rule**: After batch API changes, always attempt Preview before declaring success.
### RE2 Does Not Support Lookaheads
GTM's regex engine (RE2) is linear-time and deliberately omits:
- Negative lookahead `(?!...)`
- Positive lookahead `(?=...)`
- Lookbehind `(?<=...)` / `(?<!...)`
- Backreferences `\1`
**Wrong** (breaks at Preview/Publish with "내부 오류"):
```
^(?!.*(jamie\.clinic|tel:)).*$
```
**Right** — use separate conditions with `negate` parameter:
```json
{
"type": "contains",
"parameter": [
{"type": "template", "key": "arg0", "value": "{{Click URL}}"},
{"type": "template", "key": "arg1", "value": "jamie.clinic"},
{"type": "boolean", "key": "negate", "value": "true"}
]
}
```
### The `negate` Parameter Is Inside the Condition Array
GTM API negation is NOT a top-level field on the condition object — it's a `{"type": "boolean", "key": "negate", "value": "true"}` entry inside the condition's `parameter` array, alongside `arg0` and `arg1`. Setting `negate: true` at the condition top level is **silently ignored** by the API.
### RegEx Table Variable Column Names
The `remm` (RegEx Table) variable type uses `key` and `value` as column names in its map entries, NOT `pattern` and `outputValue`. Also requires `{"type": "boolean", "key": "setDefaultValue", "value": "true"}` to enable the default value.
### Empty Template Fields Can Break Compilation
When creating `linkClick` triggers via API, setting `waitForTags`, `checkValidation`, `waitForTagsTimeout` via the `parameter` array sometimes produces empty top-level template stubs (`{"type": "template"}` with no value). These empty stubs can cause compilation issues. Either set them correctly at the top level or omit them and let GTM use defaults.
### Timer Triggers Cannot Use `customEventFilter`
Timer triggers fire on `gtm.timer` — they are NOT custom events. Use `filter` (not `customEventFilter`) to add page-level conditions to timer triggers. `customEventFilter` is only valid on `customEvent` type triggers.
### Colon `:` Is Not Allowed in Trigger Names
GTM trigger names cannot contain `:`. Use `-` or other separators instead.
## Key Rules
- Test on LIVE published version (not preview, unless debugging)
- Test on both desktop and mobile viewports
- CSS selector triggers = fragility risk; recommend adding IDs
- Document every test with screenshots/network evidence