feat: update GTM skills triad with field-tested improvements

gtm-audit (60):
- Added Mode D rule: check elements for IDs before designing CSS triggers

gtm-editor (61):
- Added "Tagging Workflow: dataLayer First" section — always suggest
  dataLayer push code for developers before creating GTM triggers
- Added multi-language snippets (JS, React, Vue, PHP)
- Added "Trigger Design: IDs First" section — prefer element IDs,
  ask user to add IDs before falling back to CSS selectors
- Added ID naming convention: [section]-[element]-[action]
- Added decision tree for trigger selection

gtm-validator (62):
- Flag CSS-based triggers as fragility risk during QA
- Recommend adding IDs instead of finding alternative CSS selectors

Based on field testing with ourdigital.org GTM-N9TPJW container.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-17 21:55:50 +09:00
parent f905ef6314
commit c287ca3340
3 changed files with 111 additions and 1 deletions

View File

@@ -34,6 +34,89 @@ Create, modify, and deploy GTM configurations via API. Generates ES5-compliant C
### Reporting (Notion MCP)
- Write implementation plans and tag configurations to Notion
## Tagging Workflow: dataLayer First (MANDATORY)
**Always push complexity into the dataLayer, not GTM triggers.**
### Step 1: Design the dataLayer push FIRST
Before creating any GTM configuration, design the `dataLayer.push()` that the website should implement. Present this to the user as a code snippet matching their tech stack:
**For vanilla JS / static HTML (ES5):**
```javascript
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
'event': 'generate_lead',
'lead_type': document.getElementById('requestType').value,
'form_id': 'contact-form'
});
```
**For React / Next.js / TypeScript:**
```typescript
declare global { interface Window { dataLayer: Record<string, any>[]; } }
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
event: 'generate_lead',
lead_type: selectedType,
form_id: 'contact-form',
});
```
**For Vue:**
```javascript
window.dataLayer?.push({
event: 'generate_lead',
lead_type: this.selectedType,
form_id: 'contact-form',
});
```
**For PHP / WordPress:**
```php
add_action('wp_footer', function() { ?>
<script>
document.getElementById('contact-form').addEventListener('submit', function() {
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
'event': 'generate_lead',
'lead_type': document.getElementById('requestType').value
});
});
</script>
<?php });
```
**ASK the user:** "Here's the dataLayer code for your developers. Can they add this to the page? What's your tech stack?"
### Step 2: Create simple GTM config
Once dataLayer push is agreed:
- **Trigger:** Custom Event `{{_event}}` equals `generate_lead` (simple, robust)
- **Variables:** DataLayer Variable for each parameter (e.g., `dlv - lead_type`)
- **Tag:** GA4 Event with `measurementIdOverride` + DLV parameters
### Step 3: cHTML fallback (LAST RESORT)
Only if user confirms they CANNOT modify the website code:
1. Create a Custom HTML tag that listens for DOM events
2. The cHTML pushes to dataLayer internally
3. A Custom Event trigger picks it up (same clean pattern)
**All cHTML must be ES5-compatible** (see ES5 section below).
### Decision Tree
```
Track user action?
├─ Can devs add dataLayer.push()? → YES → Simple CE trigger ✅
├─ Can't modify code, element has ID? → Use Click ID trigger ✅
├─ No ID? → Ask user to add one first
└─ Nothing possible? → cHTML + CE trigger (last resort)
```
---
## Core Capabilities
### 1. Tag Creation via GTM API
@@ -175,10 +258,35 @@ When creating tags that should trigger FB CAPI:
4. **Verify**: Hand off to gtm-validator for QA
5. **Document**: Write implementation details to Notion
## Trigger Design: IDs First (MANDATORY)
**Always prefer element `id` over CSS selectors.** IDs survive redesigns; CSS selectors break.
**Before creating ANY click/form trigger:**
1. Check if the target element has an `id` attribute via Chrome DevTools `evaluate_script`
2. **If it has an ID** → use `Click ID` or `Form ID` filter
3. **If it does NOT have an ID****ASK the user** before falling back to CSS:
> "This element doesn't have an ID. Can you add one to the website/app code?
> Suggested: `id="[section]-[element]-[action]"` e.g., `id="hero-btn-consult"`"
4. Only use CSS selectors when the user explicitly confirms they cannot modify the HTML
**Priority order:**
1. Element ID (`Click ID equals "hero-btn-consult"`)
2. Data attribute (`Click Element matches CSS [data-track="consult"]`)
3. Form ID (`Form ID equals "contact-form"`)
4. CSS selector (last resort — document which selectors are used)
**Suggested ID naming:** `[section]-[element]-[action]`
- Navigation: `nav-about`, `nav-services`, `nav-insights`
- CTAs: `hero-btn-consult`, `cta-btn-booking`
- Forms: `contact-form`, `newsletter-form`
- Footer: `footer-social-linkedin`, `footer-email`
## Rules
- Always use `dtm_status` first to verify auth and active container
- Always use `measurementIdOverride` for GA4 event tags (NOT `measurementId`)
- **Always prefer element IDs for triggers — ask user to add IDs before using CSS selectors**
- All Custom HTML must be ES5-compatible
- Use `--dry-run` conceptually — verify trigger selectors via Chrome DevTools before creating
- Rate limit: space API calls 1 second apart in batch operations