| name | gtm-performance-audit |
| description | Automatically audit Google Tag Manager implementations for performance impact when user mentions GTM, tag manager, tracking tags, marketing tags, or asks about tag performance. Analyzes container configuration, measures tag execution timing, identifies blocking tags, audits custom HTML safety, evaluates trigger efficiency, and maps tag impact to Core Web Vitals. Invoke when user says "GTM is slow", "too many tags", "tag manager performance", "tracking tags impact", or asks about marketing tag overhead. |
GTM Performance Audit
Analyze Google Tag Manager implementations for performance impact using Chrome DevTools MCP.
Philosophy
Tag managers are powerful but can silently degrade performance. Every tag has a cost.
Core Beliefs
- Measure Tag Impact Individually: Each tag's cost must be measured, not assumed
- Container Size Is a Leading Indicator: Large containers correlate with poor performance
- Triggers Are the Multiplier: Inefficient triggers amplify tag cost exponentially
- Server-Side Is the Future: Move data collection off the main thread when possible
Why GTM Audits Matter
- Invisible Performance Tax: Tags add up silently; no single tag seems costly
- Core Web Vitals Impact: GTM scripts affect LCP, INP, and CLS directly
- Third-Party Risk: Tags load external resources outside your control
- Consent Compliance: Tags firing before consent degrade trust and may violate regulations
When This Skill Activates
Activate this skill when the user:
- Mentions "GTM", "Google Tag Manager", or "tag manager"
- Says "too many tags" or "tracking is slow"
- Asks "are our marketing tags slowing the site?"
- Mentions "container size" or "tag execution"
- References "dataLayer", "custom HTML tags", or "trigger efficiency"
- Asks about "tag performance" or "third-party script impact"
- Shows GTM-related code and asks about performance
Decision Framework
Before auditing, determine the audit mode:
What Data Is Available?
- Live page with GTM → Full audit via Chrome DevTools MCP (best)
- Container JSON export + live page → Container analysis + live profiling (comprehensive)
- Container ID only → Infer from network requests on live page (limited)
- Code review only → Analyze GTM integration code in codebase (minimal)
What's the Goal?
- Quick check → Container size, tag count, obvious issues
- Standard audit → Full analysis with CWV impact mapping
- Comprehensive → Deep profiling with remediation plan and implementation steps
Decision Tree
User asks about GTM performance
|
v
URL provided? → NO → Ask for target URL (STOP until answered)
|
YES
|
v
Proceed autonomously (no further permission prompts needed)
|
v
Phase 1: Baseline Performance (before GTM analysis)
|
v
Phase 2: GTM Container Analysis
|
v
Phase 3: Issue Detection (14 checks)
|
v
Phase 4: Report Generation
Setup
Before starting the audit, gather from the user:
- Target URL (required) - The page to audit
- GTM Container ID (required) - Format: GTM-XXXXXXX
- Container JSON export (optional) - Exported from GTM admin
- Critical tags list (optional) - Tags that must not be removed
Phase 1: Baseline Performance
Measure page performance using the single-pass audit collector script — one evaluate_script call replaces all individual measurement scripts.
Step 1: Read the Collector Script
Read: agents/gtm-specialist/scripts/gtm-audit-collector.js
Step 2: Navigate and Run the Collector
mcp__chrome-devtools__navigate_page(url="<target-url>")
Wait for the page to fully load, then execute:
mcp__chrome-devtools__evaluate_script(function="<full content of gtm-audit-collector.js>")
This single call returns a structured JSON object containing:
- Navigation timing (TTFB, DCL, load complete)
- Paint metrics (FCP, first paint)
- Core Web Vitals (LCP with element, CLS, INP estimate, with ratings)
- Long Tasks / Total Blocking Time
- All
<head> scripts with blocking/async/defer status
- All GTM and third-party tracking resources (40+ vendors)
- DataLayer contents and unique events
- Consent platform detection (Google Consent Mode v2, TrustArc, OneTrust, etc.)
- Window-global vendor fingerprinting (60+ vendors)
- GA4 Measurement IDs, Conversion IDs, legacy UA IDs
Step 3: Supplemental Data (if needed)
Run these only if the collector output is insufficient for a specific check:
Console errors (check for GTM JS errors):
mcp__chrome-devtools__list_console_messages()
Raw network waterfall (for precise HAR timing):
mcp__chrome-devtools__list_network_requests()
Deep CPU profiling (comprehensive depth mode only):
mcp__chrome-devtools__performance_start_trace(reload=true, autoStop=true)
mcp__chrome-devtools__performance_stop_trace()
Phase 2: GTM Container Analysis
If Container JSON Available
Parse the exported JSON to extract:
- Container size (bytes)
- Tag count by type (Custom HTML, Google Analytics, Floodlight, etc.)
- Trigger count and types (Page View, Click, Custom Event, etc.)
- Variable count and types (DataLayer, DOM Element, JavaScript, etc.)
- Tag firing sequences and dependencies
- Custom HTML content (inline scripts)
If Only Container ID Available
Infer container details from network data:
- Count tags from network requests
- Identify third-party domains loaded
- Measure script sizes and timing
- Check for known tag patterns (GA4, Meta Pixel, etc.)
DataLayer Analysis
() => {
if (typeof dataLayer === 'undefined') return { error: 'No dataLayer found' };
return {
eventCount: dataLayer.length,
events: dataLayer.map(item => ({
event: item.event || 'push',
keys: Object.keys(item)
})),
totalSize: JSON.stringify(dataLayer).length
};
}
Phase 3: Issue Detection
Run all 14 check categories:
1. Synchronous Script Loading
What: GTM container loaded with sync instead of async
Impact: Blocks HTML parsing, delays LCP
Check: Look for <script src="...gtm.js"> without async or defer
Fix: Ensure GTM snippet uses async loading pattern
2. Blocking Tags
What: Tags that block the main thread for >50ms
Impact: Increases INP, degrades interactivity
Check: Profile main thread during tag execution
Fix: Defer non-critical tags, use tag sequencing
3. Large Payloads
What: Tags or container >100KB compressed
Impact: Increases load time, wastes bandwidth
Check: Measure transfer sizes of GTM resources
Fix: Remove unused tags, optimize custom HTML, consider server-side
4. Main Thread Blocking
What: JavaScript execution blocks main thread
Impact: Poor INP, delayed interaction response
Check: Use performance trace to measure long tasks
Fix: Break up long-running tag scripts, use Web Workers where possible
5. Missing Conditional Firing
What: Tags fire on all pages when only needed on specific pages
Impact: Unnecessary processing and network requests
Check: Analyze trigger conditions vs. page types
Fix: Add page path or event conditions to triggers
6. Trigger Optimization
What: Triggers using expensive DOM selectors or all-pages rules
Impact: Excessive event listener overhead
Check: Review trigger configurations for broad matching
Fix: Use specific CSS selectors, limit to relevant pages
7. Duplicate Tags
What: Same tracking pixel or analytics tag firing multiple times
Impact: Inflated metrics, wasted resources, double-counting
Check: Compare tag endpoints and parameters
Fix: Remove duplicates, consolidate similar tags
8. Orphaned Tags
What: Tags with no active triggers (paused or misconfigured)
Impact: Container bloat, maintenance burden
Check: Cross-reference tags with their trigger assignments
Fix: Remove or archive orphaned tags
9. Expensive Variables
What: Variables using DOM lookups or complex JavaScript on every evaluation
Impact: Repeated expensive computations
Check: Review variable types and computation cost
Fix: Cache values in dataLayer, use simpler variable types
10. Missing Async Attribute
What: Third-party scripts injected by tags without async/defer
Impact: Render-blocking, delays page load
Check: Inspect Custom HTML tags for script injection patterns
Fix: Add async attribute to injected scripts
11. Custom HTML Best Practices
What: Custom HTML tags with inline scripts that could use built-in tag types
Impact: Security risk, harder to maintain, potentially blocking
Check: Analyze Custom HTML content for convertible patterns
Fix: Convert to built-in tag templates where possible
12. Server-Side Candidates
What: Tags that could run server-side instead of client-side
Impact: Reduces client-side JavaScript, improves performance
Check: Identify tags sending data to first-party or server endpoints
Fix: Migrate eligible tags to server-side GTM container
13. Consent Mode Gaps
What: Tags firing before consent is granted
Impact: Privacy violations, regulatory risk
Check: Verify consent mode integration and tag firing sequence
Fix: Implement Google Consent Mode, add consent triggers
14. Tag Firing Order
What: Critical tags delayed by non-essential tags in the sequence
Impact: Important data collection delayed
Check: Review tag priority settings and sequencing
Fix: Set proper priority values, use tag sequencing groups
Phase 4: Report Generation
Executive Summary
## GTM Performance Audit Summary
**Container**: GTM-XXXXXXX
**URL Tested**: https://example.com
**Date**: YYYY-MM-DD
### Key Metrics
- Container Size: XXX KB (compressed)
- Total Tags: NN (XX active, YY paused)
- GTM Load Time: XXXms
- Main Thread Blocking: XXXms
- Estimated CWV Impact: [Low/Medium/High]
### Quick Wins
1. [Quick win with estimated impact]
2. [Quick win with estimated impact]
3. [Quick win with estimated impact]
Detailed Findings
Each finding should include:
- Description: What the issue is
- Measurement: Quantified impact (ms, KB, count)
- CWV Impact: Which Core Web Vital is affected and by how much
- GTM Fix Steps: Specific steps to fix in GTM admin
- Risk Assessment: Low/Medium/High risk of the fix
- Priority: Critical/High/Medium/Low
Tag Inventory Table
| Tag Name | Type | Trigger | Size | Exec Time | Status |
|----------|------|---------|------|-----------|--------|
| GA4 | Google Analytics | All Pages | 45KB | 120ms | Active |
| Meta Pixel | Custom HTML | All Pages | 32KB | 85ms | Active |
| Hotjar | Custom HTML | Page View | 28KB | 200ms | Active |
Network Waterfall
Show timing of GTM-related requests:
0ms 100ms 200ms 300ms 400ms 500ms
|--------|--------|--------|--------|--------|
[==GTM Container (45KB)==]
[====GA4 (32KB)====]
[==Meta Pixel==]
[====Hotjar (28KB)====]
[=LinkedIn=]
Implementation Checklist
## Remediation Checklist
### Critical (Do This Week)
- [ ] Remove duplicate GA4 tag (saves ~120ms)
- [ ] Add async to Custom HTML script injections
### High Priority (Do This Sprint)
- [ ] Add page path conditions to 5 all-pages tags
- [ ] Convert 3 Custom HTML tags to built-in templates
- [ ] Remove 4 orphaned tags (saves ~15KB)
### Medium Priority (Plan for Next Sprint)
- [ ] Evaluate server-side GTM for conversion tags
- [ ] Implement consent mode v2
- [ ] Optimize dataLayer push frequency
### Low Priority (Backlog)
- [ ] Consolidate similar event triggers
- [ ] Review variable caching strategy
Required MCP Integration
This skill requires Chrome DevTools MCP. Tools used:
mcp__chrome-devtools__evaluate_script - Execute JavaScript for timing, dataLayer, resource analysis
mcp__chrome-devtools__list_network_requests - Capture GTM network waterfall
mcp__chrome-devtools__list_console_messages - Check for GTM errors
mcp__chrome-devtools__navigate_page - Navigate to target URL
mcp__chrome-devtools__take_snapshot - Get page structure for tag detection
mcp__chrome-devtools__performance_start_trace - Start performance profiling
mcp__chrome-devtools__performance_stop_trace - Stop profiling and get results
mcp__chrome-devtools__new_page - Open fresh tab for clean measurement
CMS-Specific GTM Patterns
Drupal
Common GTM Integration:
google_tag module (most common)
- Custom
html.html.twig injection
- Config at
/admin/config/services/google-tag
Check for:
- Module configuration:
drush config:get google_tag.settings
- Container ID in config vs. hardcoded in templates
- Multiple containers (module + theme + custom module)
- DataLayer integration via
hook_google_tag_snippets_alter()
WordPress
Common GTM Integration:
- GTM4WP plugin (most common)
- Google Site Kit plugin
- Manual
header.php injection
- Theme
functions.php via wp_head action
Check for:
- Plugin settings: GTM4WP → Settings → Container ID
- Multiple injection points (plugin + theme + another plugin)
- DataLayer population via WooCommerce integration
- Custom event tracking in theme JavaScript
Guardrails
- Read-only: Never modify GTM containers, tags, triggers, or variables
- No credentials: Never ask for or enter GTM admin credentials
- Conservative estimates: When unsure of impact, estimate conservatively
- Preserve functionality: Recommendations must not break tracking
- Privacy-aware: Flag consent issues but don't disable tags
Integration with /audit-gtm Command
Quick Tips
- Container under 50KB compressed is healthy; over 100KB needs attention
- More than 30 active tags usually indicates cleanup opportunity
- Custom HTML tags are the biggest performance risk - audit these first
- All Pages triggers are the most common source of waste
- dataLayer pushes before GTM loads are queued and processed in order