Phase 2 refactoring of skills >500 lines and medium-sized skills: - paid-ads: 553 → 297 lines - Extract ad-copy-templates.md, audience-targeting.md, platform-setup-checklists.md - analytics-tracking: 541 → 292 lines - Extract ga4-implementation.md, gtm-implementation.md, event-library.md - ab-test-setup: 510 → 264 lines - Extract test-templates.md, sample-size-guide.md - copywriting: 458 → 248 lines - Extract copy-frameworks.md (headline formulas, section types) - page-cro: 336 → 180 lines - Extract experiments.md (experiment ideas by page type) - onboarding-cro: 435 → 218 lines - Extract experiments.md (onboarding experiment ideas) All skills now use progressive disclosure with references/ folders, keeping SKILL.md files focused on core workflow while detailed content is available when needed. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
7.1 KiB
Google Tag Manager Implementation Reference
Detailed guide for implementing tracking via Google Tag Manager.
Container Structure
Tags
Tags are code snippets that execute when triggered.
Common tag types:
- GA4 Configuration (base setup)
- GA4 Event (custom events)
- Google Ads Conversion
- Facebook Pixel
- LinkedIn Insight Tag
- Custom HTML (for other pixels)
Triggers
Triggers define when tags fire.
Built-in triggers:
- Page View: All Pages, DOM Ready, Window Loaded
- Click: All Elements, Just Links
- Form Submission
- Scroll Depth
- Timer
- Element Visibility
Custom triggers:
- Custom Event (from dataLayer)
- Trigger Groups (multiple conditions)
Variables
Variables capture dynamic values.
Built-in (enable as needed):
- Click Text, Click URL, Click ID, Click Classes
- Page Path, Page URL, Page Hostname
- Referrer
- Form Element, Form ID
User-defined:
- Data Layer variables
- JavaScript variables
- Lookup tables
- RegEx tables
- Constants
Naming Conventions
Recommended Format
[Type] - [Description] - [Detail]
Tags:
GA4 - Event - Signup Completed
GA4 - Config - Base Configuration
FB - Pixel - Page View
HTML - LiveChat Widget
Triggers:
Click - CTA Button
Submit - Contact Form
View - Pricing Page
Custom - signup_completed
Variables:
DL - user_id
JS - Current Timestamp
LT - Campaign Source Map
Data Layer Patterns
Basic Structure
// Initialize (in <head> before GTM)
window.dataLayer = window.dataLayer || [];
// Push event
dataLayer.push({
'event': 'event_name',
'property1': 'value1',
'property2': 'value2'
});
Page Load Data
// Set on page load (before GTM container)
window.dataLayer = window.dataLayer || [];
dataLayer.push({
'pageType': 'product',
'contentGroup': 'products',
'user': {
'loggedIn': true,
'userId': '12345',
'userType': 'premium'
}
});
Form Submission
document.querySelector('#contact-form').addEventListener('submit', function() {
dataLayer.push({
'event': 'form_submitted',
'formName': 'contact',
'formLocation': 'footer'
});
});
Button Click
document.querySelector('.cta-button').addEventListener('click', function() {
dataLayer.push({
'event': 'cta_clicked',
'ctaText': this.innerText,
'ctaLocation': 'hero'
});
});
E-commerce Events
// Product view
dataLayer.push({ ecommerce: null }); // Clear previous
dataLayer.push({
'event': 'view_item',
'ecommerce': {
'items': [{
'item_id': 'SKU123',
'item_name': 'Product Name',
'price': 99.99,
'item_category': 'Category',
'quantity': 1
}]
}
});
// Add to cart
dataLayer.push({ ecommerce: null });
dataLayer.push({
'event': 'add_to_cart',
'ecommerce': {
'items': [{
'item_id': 'SKU123',
'item_name': 'Product Name',
'price': 99.99,
'quantity': 1
}]
}
});
// Purchase
dataLayer.push({ ecommerce: null });
dataLayer.push({
'event': 'purchase',
'ecommerce': {
'transaction_id': 'T12345',
'value': 99.99,
'currency': 'USD',
'tax': 5.00,
'shipping': 10.00,
'items': [{
'item_id': 'SKU123',
'item_name': 'Product Name',
'price': 99.99,
'quantity': 1
}]
}
});
Common Tag Configurations
GA4 Configuration Tag
Tag Type: Google Analytics: GA4 Configuration
Settings:
- Measurement ID: G-XXXXXXXX
- Send page view: Checked (for pageviews)
- User Properties: Add any user-level dimensions
Trigger: All Pages
GA4 Event Tag
Tag Type: Google Analytics: GA4 Event
Settings:
- Configuration Tag: Select your config tag
- Event Name: {{DL - event_name}} or hardcode
- Event Parameters: Add parameters from dataLayer
Trigger: Custom Event with event name match
Facebook Pixel - Base
Tag Type: Custom HTML
<script>
!function(f,b,e,v,n,t,s)
{if(f.fbq)return;n=f.fbq=function(){n.callMethod?
n.callMethod.apply(n,arguments):n.queue.push(arguments)};
if(!f._fbq)f._fbq=n;n.push=n;n.loaded=!0;n.version='2.0';
n.queue=[];t=b.createElement(e);t.async=!0;
t.src=v;s=b.getElementsByTagName(e)[0];
s.parentNode.insertBefore(t,s)}(window, document,'script',
'https://connect.facebook.net/en_US/fbevents.js');
fbq('init', 'YOUR_PIXEL_ID');
fbq('track', 'PageView');
</script>
Trigger: All Pages
Facebook Pixel - Event
Tag Type: Custom HTML
<script>
fbq('track', 'Lead', {
content_name: '{{DL - form_name}}'
});
</script>
Trigger: Custom Event - form_submitted
Preview and Debug
Preview Mode
- Click "Preview" in GTM
- Enter site URL
- GTM debug panel opens at bottom
What to check:
- Tags fired on this event
- Tags not fired (and why)
- Variables and their values
- Data layer contents
Debug Tips
Tag not firing:
- Check trigger conditions
- Verify data layer push
- Check tag sequencing
Wrong variable value:
- Check data layer structure
- Verify variable path (nested objects)
- Check timing (data may not exist yet)
Multiple firings:
- Check trigger uniqueness
- Look for duplicate tags
- Check tag firing options
Workspaces and Versioning
Workspaces
Use workspaces for team collaboration:
- Default workspace for production
- Separate workspaces for large changes
- Merge when ready
Version Management
Best practices:
- Name every version descriptively
- Add notes explaining changes
- Review changes before publish
- Keep production version noted
Version notes example:
v15: Added purchase conversion tracking
- New tag: GA4 - Event - Purchase
- New trigger: Custom Event - purchase
- New variables: DL - transaction_id, DL - value
- Tested: Chrome, Safari, Mobile
Consent Management
Consent Mode Integration
// Default state (before consent)
gtag('consent', 'default', {
'analytics_storage': 'denied',
'ad_storage': 'denied'
});
// Update on consent
function grantConsent() {
gtag('consent', 'update', {
'analytics_storage': 'granted',
'ad_storage': 'granted'
});
}
GTM Consent Overview
- Enable Consent Overview in Admin
- Configure consent for each tag
- Tags respect consent state automatically
Advanced Patterns
Tag Sequencing
Setup tags to fire in order: Tag Configuration > Advanced Settings > Tag Sequencing
Use cases:
- Config tag before event tags
- Pixel initialization before tracking
- Cleanup after conversion
Exception Handling
Trigger exceptions - Prevent tag from firing:
- Exclude certain pages
- Exclude internal traffic
- Exclude during testing
Custom JavaScript Variables
// Get URL parameter
function() {
var params = new URLSearchParams(window.location.search);
return params.get('campaign') || '(not set)';
}
// Get cookie value
function() {
var match = document.cookie.match('(^|;) ?user_id=([^;]*)(;|$)');
return match ? match[2] : null;
}
// Get data from page
function() {
var el = document.querySelector('.product-price');
return el ? parseFloat(el.textContent.replace('$', '')) : 0;
}