Initial commit
This commit is contained in:
380
skills/ga4-gtm-integration/references/gtm-best-practices-ga4.md
Normal file
380
skills/ga4-gtm-integration/references/gtm-best-practices-ga4.md
Normal file
@@ -0,0 +1,380 @@
|
||||
# GTM Best Practices for GA4 Implementation
|
||||
|
||||
## Container Organization
|
||||
|
||||
### Naming Conventions
|
||||
|
||||
**Tags:**
|
||||
- `GA4 - Configuration` (base tag)
|
||||
- `GA4 - [Event Name] - [Description]`
|
||||
- Examples:
|
||||
- `GA4 - Button Click - Subscribe`
|
||||
- `GA4 - Form Submit - Contact`
|
||||
- `GA4 - Purchase`
|
||||
|
||||
**Triggers:**
|
||||
- `[Type] - [Description]`
|
||||
- Examples:
|
||||
- `All Pages`
|
||||
- `Click - Subscribe Button`
|
||||
- `Form - Contact Submit`
|
||||
- `Custom Event - add_to_cart`
|
||||
|
||||
**Variables:**
|
||||
- `DL - [Name]` for Data Layer Variables
|
||||
- `JS - [Name]` for JavaScript Variables
|
||||
- `Cookie - [Name]` for Cookies
|
||||
- Examples:
|
||||
- `DL - Product ID`
|
||||
- `JS - User Tier`
|
||||
- `Cookie - Session ID`
|
||||
|
||||
### Folder Structure
|
||||
|
||||
**Organize by Function:**
|
||||
```
|
||||
Folders:
|
||||
├── GA4 - Core (Configuration tag)
|
||||
├── GA4 - E-commerce (Purchase, add_to_cart, etc.)
|
||||
├── GA4 - Engagement (Scroll, clicks, video)
|
||||
├── GA4 - Forms
|
||||
└── Variables - Data Layer
|
||||
```
|
||||
|
||||
## Performance Optimization
|
||||
|
||||
### Rule 1: Use One GA4 Configuration Tag
|
||||
|
||||
**CORRECT:**
|
||||
- One GA4 Configuration tag
|
||||
- Fires on Initialization - All Pages
|
||||
- Multiple event tags reference same Measurement ID
|
||||
|
||||
**WRONG:**
|
||||
- Multiple GA4 Configuration tags
|
||||
- Different Measurement IDs in same container
|
||||
|
||||
### Rule 2: Minimize Data Layer Pushes
|
||||
|
||||
**CORRECT:**
|
||||
```javascript
|
||||
dataLayer.push({
|
||||
'event': 'add_to_cart',
|
||||
'product_id': 'SKU_123',
|
||||
'product_name': 'Blue T-Shirt',
|
||||
'price': 29.99
|
||||
});
|
||||
```
|
||||
|
||||
**WRONG:**
|
||||
```javascript
|
||||
dataLayer.push({'event': 'add_to_cart'});
|
||||
dataLayer.push({'product_id': 'SKU_123'});
|
||||
dataLayer.push({'product_name': 'Blue T-Shirt'});
|
||||
dataLayer.push({'price': 29.99});
|
||||
```
|
||||
|
||||
### Rule 3: Use Specific Triggers
|
||||
|
||||
**CORRECT:**
|
||||
```
|
||||
Trigger Type: Click - All Elements
|
||||
Fires on: Some Clicks
|
||||
Condition: Click ID equals subscribe-btn
|
||||
```
|
||||
|
||||
**WRONG:**
|
||||
```
|
||||
Trigger Type: Click - All Elements
|
||||
Fires on: All Clicks
|
||||
(Then filter in tag)
|
||||
```
|
||||
|
||||
### Rule 4: Batch Event Parameters
|
||||
|
||||
**CORRECT:**
|
||||
- Add all parameters in single event tag
|
||||
- Use data layer variables efficiently
|
||||
|
||||
**WRONG:**
|
||||
- Multiple tags for same event
|
||||
- Separate pushes for each parameter
|
||||
|
||||
## Data Quality
|
||||
|
||||
### Use Consistent Event Names
|
||||
|
||||
**Best Practice:**
|
||||
- Follow GA4 recommended event names
|
||||
- Use snake_case consistently
|
||||
- Document custom events
|
||||
|
||||
**Recommended Events:**
|
||||
- `purchase`, `add_to_cart`, `begin_checkout`
|
||||
- `sign_up`, `login`, `generate_lead`
|
||||
- `view_item`, `view_item_list`, `select_item`
|
||||
|
||||
**Custom Events:**
|
||||
- `button_click`, `form_submit`, `video_start`
|
||||
- Keep lowercase with underscores
|
||||
- Limit to 40 characters
|
||||
|
||||
### Validate Data Types
|
||||
|
||||
**Correct Types:**
|
||||
- **String:** Event names, IDs, categories
|
||||
- **Number:** Values, prices, quantities, revenue
|
||||
- **Boolean:** true/false (not "true"/"false")
|
||||
- **Array:** Items array for e-commerce
|
||||
|
||||
**Example:**
|
||||
```javascript
|
||||
dataLayer.push({
|
||||
'event': 'purchase',
|
||||
'transaction_id': 'T_12345', // String
|
||||
'value': 99.99, // Number
|
||||
'currency': 'USD', // String
|
||||
'items': [...] // Array
|
||||
});
|
||||
```
|
||||
|
||||
### Avoid PII (Personally Identifiable Information)
|
||||
|
||||
**DO NOT Track:**
|
||||
- Email addresses
|
||||
- Phone numbers
|
||||
- Full names
|
||||
- Street addresses
|
||||
- Social Security numbers
|
||||
|
||||
**Safe to Track:**
|
||||
- Email domain (`@gmail.com`, `@company.com`)
|
||||
- User IDs (hashed/anonymized)
|
||||
- City/region (not specific addresses)
|
||||
|
||||
## Testing and QA
|
||||
|
||||
### Pre-Publication Checklist
|
||||
|
||||
- [ ] All tags fire in Preview mode
|
||||
- [ ] Variables populate correctly
|
||||
- [ ] Event names follow naming conventions
|
||||
- [ ] Parameters have correct data types
|
||||
- [ ] No PII in parameters
|
||||
- [ ] Events appear in GA4 DebugView
|
||||
- [ ] No duplicate events
|
||||
- [ ] Data layer formatted correctly
|
||||
- [ ] Documentation updated
|
||||
- [ ] Version description written
|
||||
|
||||
### Version Control
|
||||
|
||||
**Every Publish:**
|
||||
1. **Version Name:** Descriptive (e.g., "GA4 E-commerce Tracking - Nov 2024")
|
||||
2. **Version Description:** Detailed list of changes
|
||||
3. **Workspace Name:** Feature/task description
|
||||
|
||||
**Example Version Description:**
|
||||
```
|
||||
Changes:
|
||||
- Added GA4 purchase event tracking
|
||||
- Created data layer variables for transaction data
|
||||
- Added form submission tracking for contact form
|
||||
- Fixed duplicate page_view issue
|
||||
|
||||
Tested:
|
||||
- Purchase flow (3 test transactions)
|
||||
- Contact form submission
|
||||
- All pages for duplicate events
|
||||
```
|
||||
|
||||
### Rollback Plan
|
||||
|
||||
**If Issues After Publishing:**
|
||||
1. Go to **Versions** tab
|
||||
2. Find previous working version
|
||||
3. Click **"•••"** → **Publish**
|
||||
4. Confirm rollback
|
||||
|
||||
**Prevention:**
|
||||
- Test thoroughly before publishing
|
||||
- Publish during low-traffic periods
|
||||
- Monitor for 30+ minutes after publishing
|
||||
|
||||
## Security and Privacy
|
||||
|
||||
### Use Appropriate Consent Mode
|
||||
|
||||
**Implementation:**
|
||||
```javascript
|
||||
// Set default consent state
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
|
||||
gtag('consent', 'default', {
|
||||
'ad_storage': 'denied',
|
||||
'analytics_storage': 'denied'
|
||||
});
|
||||
|
||||
// Update after user consent
|
||||
gtag('consent', 'update', {
|
||||
'ad_storage': 'granted',
|
||||
'analytics_storage': 'granted'
|
||||
});
|
||||
```
|
||||
|
||||
### IP Anonymization
|
||||
|
||||
**Not Needed for GA4:**
|
||||
- GA4 does not log or store IP addresses by default
|
||||
- No `anonymize_ip` parameter needed
|
||||
|
||||
### Data Retention Settings
|
||||
|
||||
**In GA4:**
|
||||
1. Admin → Data Settings → Data Retention
|
||||
2. Set event data retention (2 or 14 months)
|
||||
3. Enable/disable "Reset user data on new activity"
|
||||
|
||||
## Maintenance
|
||||
|
||||
### Regular Audits
|
||||
|
||||
**Monthly:**
|
||||
- Review Tags Not Fired section
|
||||
- Check for broken triggers
|
||||
- Verify variables still working
|
||||
- Test critical paths
|
||||
|
||||
**Quarterly:**
|
||||
- Full container audit
|
||||
- Remove unused tags/triggers/variables
|
||||
- Update documentation
|
||||
- Review naming conventions
|
||||
|
||||
**Annually:**
|
||||
- Major cleanup
|
||||
- Archive old tags
|
||||
- Update to latest GA4 features
|
||||
|
||||
### Documentation
|
||||
|
||||
**Maintain Documentation For:**
|
||||
- All custom events and parameters
|
||||
- Data layer structure
|
||||
- Trigger logic
|
||||
- Variable mappings
|
||||
- Change history
|
||||
|
||||
**Example Documentation:**
|
||||
```markdown
|
||||
# Custom Events
|
||||
|
||||
## add_to_cart
|
||||
Fires when: User clicks "Add to Cart" button
|
||||
Parameters:
|
||||
- product_id (string): SKU
|
||||
- product_name (string): Product name
|
||||
- price (number): Unit price
|
||||
- quantity (number): Quantity added
|
||||
Data Layer: dataLayer.push({event: 'add_to_cart', ...})
|
||||
GTM Tag: GA4 - Add to Cart
|
||||
Trigger: Custom Event - add_to_cart
|
||||
```
|
||||
|
||||
## Common Pitfalls to Avoid
|
||||
|
||||
### Pitfall 1: Multiple Measurement IDs
|
||||
|
||||
**Issue:** Using different Measurement IDs in event tags
|
||||
**Solution:** Use same Measurement ID across all GA4 tags
|
||||
|
||||
### Pitfall 2: Not Clearing ecommerce Object
|
||||
|
||||
**Issue:** Old ecommerce data persists across events
|
||||
**Solution:** Clear before each ecommerce push
|
||||
```javascript
|
||||
dataLayer.push({ ecommerce: null });
|
||||
dataLayer.push({ event: 'purchase', ecommerce: {...} });
|
||||
```
|
||||
|
||||
### Pitfall 3: Tracking PII
|
||||
|
||||
**Issue:** Accidentally sending email addresses or names
|
||||
**Solution:** Review all data layer pushes and parameters
|
||||
|
||||
### Pitfall 4: Inconsistent Event Names
|
||||
|
||||
**Issue:** `buttonClick`, `button_click`, `Button_Click`
|
||||
**Solution:** Use lowercase with underscores consistently
|
||||
|
||||
### Pitfall 5: Publishing Without Testing
|
||||
|
||||
**Issue:** Broken tags go live
|
||||
**Solution:** Always use Preview mode before publishing
|
||||
|
||||
### Pitfall 6: No Version Descriptions
|
||||
|
||||
**Issue:** Can't identify what changed in version history
|
||||
**Solution:** Write detailed version descriptions
|
||||
|
||||
### Pitfall 7: Overcomplicating Setup
|
||||
|
||||
**Issue:** Too many tags for simple tracking
|
||||
**Solution:** Start simple, add complexity as needed
|
||||
|
||||
## Migration from gtag.js to GTM
|
||||
|
||||
**Steps:**
|
||||
|
||||
1. **Remove gtag.js snippet** from website
|
||||
2. **Install GTM container** code
|
||||
3. **Create GA4 Configuration tag** in GTM
|
||||
4. **Migrate custom events** to GTM event tags
|
||||
5. **Test thoroughly** in Preview mode
|
||||
6. **Publish** GTM container
|
||||
|
||||
**Benefits:**
|
||||
- No code changes needed for new tracking
|
||||
- Easier testing with Preview mode
|
||||
- Centralized tag management
|
||||
- Better collaboration
|
||||
|
||||
## Collaboration Best Practices
|
||||
|
||||
### Workspaces
|
||||
|
||||
**Use Workspaces For:**
|
||||
- Feature development
|
||||
- Testing major changes
|
||||
- Team collaboration
|
||||
|
||||
**Best Practices:**
|
||||
- One workspace per feature/task
|
||||
- Descriptive workspace names
|
||||
- Merge/publish when complete
|
||||
|
||||
### User Permissions
|
||||
|
||||
**Roles:**
|
||||
- **No Access:** No access to container
|
||||
- **Read:** View-only access
|
||||
- **Edit:** Create/modify tags (can't publish)
|
||||
- **Approve:** Publish changes
|
||||
- **Publish:** Full control
|
||||
|
||||
**Best Practice:**
|
||||
- Limit Publish access
|
||||
- Most users: Edit access
|
||||
- Senior team: Approve/Publish
|
||||
|
||||
### Change Management
|
||||
|
||||
**Process:**
|
||||
1. Create workspace for change
|
||||
2. Implement and test
|
||||
3. Submit for review (if applicable)
|
||||
4. Peer review changes
|
||||
5. Final testing in Preview
|
||||
6. Publish with detailed description
|
||||
7. Monitor for 30+ minutes
|
||||
479
skills/ga4-gtm-integration/references/gtm-data-layer-ga4.md
Normal file
479
skills/ga4-gtm-integration/references/gtm-data-layer-ga4.md
Normal file
@@ -0,0 +1,479 @@
|
||||
# GTM Data Layer Implementation for GA4
|
||||
|
||||
## Data Layer Fundamentals
|
||||
|
||||
The **data layer** is a JavaScript object that acts as a bridge between your website and Google Tag Manager, holding structured data that GTM can access and send to GA4.
|
||||
|
||||
### Data Layer Structure
|
||||
|
||||
```javascript
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
```
|
||||
|
||||
**Key Concepts:**
|
||||
- Global JavaScript array
|
||||
- Holds events and data
|
||||
- GTM reads from this automatically
|
||||
- Must exist BEFORE GTM container code
|
||||
|
||||
### Basic Data Layer Push
|
||||
|
||||
```javascript
|
||||
dataLayer.push({
|
||||
'event': 'event_name',
|
||||
'parameter_key': 'parameter_value'
|
||||
});
|
||||
```
|
||||
|
||||
**Components:**
|
||||
- `event`: Trigger name for GTM Custom Event triggers
|
||||
- Additional keys: Data accessible via Data Layer Variables
|
||||
|
||||
## Event Tracking Patterns
|
||||
|
||||
### Pattern 1: Simple Event
|
||||
|
||||
**On Website:**
|
||||
|
||||
```javascript
|
||||
dataLayer.push({
|
||||
'event': 'button_click',
|
||||
'button_name': 'Subscribe Now',
|
||||
'button_location': 'header'
|
||||
});
|
||||
```
|
||||
|
||||
**In GTM:**
|
||||
|
||||
1. Create Trigger:
|
||||
- Type: Custom Event
|
||||
- Event name: `button_click`
|
||||
|
||||
2. Create Variables:
|
||||
- Name: "DL - Button Name"
|
||||
- Type: Data Layer Variable
|
||||
- Variable Name: `button_name`
|
||||
|
||||
3. Create GA4 Tag:
|
||||
- Event Name: `button_click`
|
||||
- Parameters: `button_name` → `{{DL - Button Name}}`
|
||||
|
||||
### Pattern 2: E-commerce Event
|
||||
|
||||
**On Website:**
|
||||
|
||||
```javascript
|
||||
dataLayer.push({
|
||||
'event': 'add_to_cart',
|
||||
'ecommerce': {
|
||||
'items': [
|
||||
{
|
||||
'item_id': 'SKU_123',
|
||||
'item_name': 'Blue T-Shirt',
|
||||
'price': 29.99,
|
||||
'quantity': 1,
|
||||
'item_category': 'Apparel'
|
||||
}
|
||||
],
|
||||
'value': 29.99,
|
||||
'currency': 'USD'
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
**In GTM:**
|
||||
|
||||
1. Create Variable for items:
|
||||
- Name: "DL - Ecommerce Items"
|
||||
- Type: Data Layer Variable
|
||||
- Variable Name: `ecommerce.items`
|
||||
|
||||
2. Create GA4 Event Tag:
|
||||
- Event Name: `add_to_cart`
|
||||
- Parameters:
|
||||
- `items` → `{{DL - Ecommerce Items}}`
|
||||
- `value` → `{{DL - Ecommerce Value}}`
|
||||
- `currency` → `{{DL - Ecommerce Currency}}`
|
||||
|
||||
### Pattern 3: Purchase Event (Complete)
|
||||
|
||||
**On Website:**
|
||||
|
||||
```javascript
|
||||
dataLayer.push({
|
||||
'event': 'purchase',
|
||||
'ecommerce': {
|
||||
'transaction_id': 'T_12345',
|
||||
'affiliation': 'Online Store',
|
||||
'value': 99.98,
|
||||
'currency': 'USD',
|
||||
'tax': 8.00,
|
||||
'shipping': 5.00,
|
||||
'coupon': 'SUMMER20',
|
||||
'items': [
|
||||
{
|
||||
'item_id': 'SKU_123',
|
||||
'item_name': 'Blue T-Shirt',
|
||||
'price': 29.99,
|
||||
'quantity': 2,
|
||||
'item_category': 'Apparel',
|
||||
'item_brand': 'MyBrand'
|
||||
},
|
||||
{
|
||||
'item_id': 'SKU_124',
|
||||
'item_name': 'Black Hat',
|
||||
'price': 20.00,
|
||||
'quantity': 2,
|
||||
'item_category': 'Accessories'
|
||||
}
|
||||
]
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
**In GTM:**
|
||||
|
||||
Create Data Layer Variables for:
|
||||
- `ecommerce.transaction_id`
|
||||
- `ecommerce.value`
|
||||
- `ecommerce.currency`
|
||||
- `ecommerce.tax`
|
||||
- `ecommerce.shipping`
|
||||
- `ecommerce.items`
|
||||
|
||||
Create GA4 Event Tag mapping all parameters.
|
||||
|
||||
### Pattern 4: Form Submission
|
||||
|
||||
**On Website:**
|
||||
|
||||
```javascript
|
||||
document.getElementById('contact-form').addEventListener('submit', function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
dataLayer.push({
|
||||
'event': 'form_submit',
|
||||
'form_name': 'Contact Form',
|
||||
'form_id': 'contact-form',
|
||||
'form_destination': '/thank-you',
|
||||
'user_email_domain': document.getElementById('email').value.split('@')[1]
|
||||
});
|
||||
|
||||
// Then submit form
|
||||
this.submit();
|
||||
});
|
||||
```
|
||||
|
||||
### Pattern 5: Video Tracking
|
||||
|
||||
**On Website:**
|
||||
|
||||
```javascript
|
||||
// When video starts
|
||||
dataLayer.push({
|
||||
'event': 'video_start',
|
||||
'video_title': 'Product Demo',
|
||||
'video_duration': 180,
|
||||
'video_id': 'demo_v1'
|
||||
});
|
||||
|
||||
// When video completes
|
||||
dataLayer.push({
|
||||
'event': 'video_complete',
|
||||
'video_title': 'Product Demo',
|
||||
'video_percent': 100,
|
||||
'video_id': 'demo_v1'
|
||||
});
|
||||
```
|
||||
|
||||
## Advanced Patterns
|
||||
|
||||
### Pattern 6: User Authentication
|
||||
|
||||
**On Login:**
|
||||
|
||||
```javascript
|
||||
dataLayer.push({
|
||||
'event': 'login',
|
||||
'method': 'email',
|
||||
'user_id': 'user_12345',
|
||||
'user_tier': 'premium',
|
||||
'years_customer': 3
|
||||
});
|
||||
```
|
||||
|
||||
**On Logout:**
|
||||
|
||||
```javascript
|
||||
dataLayer.push({
|
||||
'event': 'logout',
|
||||
'user_id': null // Clear user ID
|
||||
});
|
||||
```
|
||||
|
||||
### Pattern 7: Page Data (For SPAs)
|
||||
|
||||
**On Route Change (Single Page Apps):**
|
||||
|
||||
```javascript
|
||||
// React example
|
||||
useEffect(() => {
|
||||
dataLayer.push({
|
||||
'event': 'virtual_page_view',
|
||||
'page_path': window.location.pathname,
|
||||
'page_title': document.title,
|
||||
'page_category': 'products'
|
||||
});
|
||||
}, [location]);
|
||||
```
|
||||
|
||||
### Pattern 8: Search Tracking
|
||||
|
||||
**On Search:**
|
||||
|
||||
```javascript
|
||||
dataLayer.push({
|
||||
'event': 'search',
|
||||
'search_term': searchQuery,
|
||||
'search_results_count': resultsCount,
|
||||
'search_category': selectedCategory
|
||||
});
|
||||
```
|
||||
|
||||
## Data Layer Variable Types in GTM
|
||||
|
||||
### Type 1: Simple Data Layer Variable
|
||||
|
||||
**Configuration:**
|
||||
- **Variable Type:** Data Layer Variable
|
||||
- **Data Layer Variable Name:** `product_id`
|
||||
- **Data Layer Version:** Version 2
|
||||
|
||||
**Usage:** `{{DL - Product ID}}`
|
||||
|
||||
### Type 2: Nested Object Access
|
||||
|
||||
**For Nested Data:**
|
||||
|
||||
```javascript
|
||||
dataLayer.push({
|
||||
'ecommerce': {
|
||||
'value': 99.99,
|
||||
'items': [...]
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
**Variable Configuration:**
|
||||
- **Variable Name:** "DL - Ecommerce Value"
|
||||
- **Type:** Data Layer Variable
|
||||
- **Variable Name:** `ecommerce.value`
|
||||
|
||||
### Type 3: Array Access
|
||||
|
||||
**For Array Elements:**
|
||||
|
||||
```javascript
|
||||
dataLayer.push({
|
||||
'items': [
|
||||
{'item_id': 'SKU_123'},
|
||||
{'item_id': 'SKU_124'}
|
||||
]
|
||||
});
|
||||
```
|
||||
|
||||
**Variable for First Item:**
|
||||
- **Variable Name:** `items.0.item_id` (first array element)
|
||||
|
||||
**Better:** Pass entire `items` array to GA4 event parameter
|
||||
|
||||
## Timing and Order
|
||||
|
||||
### Rule 1: Data Layer BEFORE GTM Container
|
||||
|
||||
```html
|
||||
<script>
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
// Can push initial page data here
|
||||
dataLayer.push({
|
||||
'page_type': 'product',
|
||||
'user_tier': 'premium'
|
||||
});
|
||||
</script>
|
||||
|
||||
<!-- GTM Container Code -->
|
||||
<script>(function(w,d,s,l,i){...})(window,document,'script','dataLayer','GTM-XXXXXXX');</script>
|
||||
```
|
||||
|
||||
### Rule 2: Event Push AFTER User Action
|
||||
|
||||
```javascript
|
||||
// CORRECT
|
||||
button.addEventListener('click', function() {
|
||||
dataLayer.push({
|
||||
'event': 'button_click',
|
||||
'button_name': 'Subscribe'
|
||||
});
|
||||
});
|
||||
|
||||
// WRONG - Fires on page load before click
|
||||
dataLayer.push({
|
||||
'event': 'button_click',
|
||||
'button_name': 'Subscribe'
|
||||
});
|
||||
```
|
||||
|
||||
### Rule 3: Clear ecommerce Before Push
|
||||
|
||||
**For E-commerce Events:**
|
||||
|
||||
```javascript
|
||||
// Clear previous ecommerce data
|
||||
dataLayer.push({ ecommerce: null });
|
||||
|
||||
// Push new ecommerce data
|
||||
dataLayer.push({
|
||||
'event': 'add_to_cart',
|
||||
'ecommerce': {
|
||||
'items': [...]
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
**Why:** Prevents old ecommerce data from persisting
|
||||
|
||||
## SPA (Single Page Application) Patterns
|
||||
|
||||
### React Example
|
||||
|
||||
```javascript
|
||||
import { useEffect } from 'react';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
|
||||
function App() {
|
||||
const location = useLocation();
|
||||
|
||||
useEffect(() => {
|
||||
// Track virtual page view on route change
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
window.dataLayer.push({
|
||||
'event': 'virtual_page_view',
|
||||
'page_path': location.pathname,
|
||||
'page_title': document.title
|
||||
});
|
||||
}, [location]);
|
||||
|
||||
return <div>...</div>;
|
||||
}
|
||||
```
|
||||
|
||||
### Vue.js Example
|
||||
|
||||
```javascript
|
||||
// In router/index.js
|
||||
router.afterEach((to, from) => {
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
window.dataLayer.push({
|
||||
'event': 'virtual_page_view',
|
||||
'page_path': to.path,
|
||||
'page_title': to.meta.title || document.title
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
## Debugging Data Layer
|
||||
|
||||
### Console Debugging
|
||||
|
||||
```javascript
|
||||
// View entire data layer
|
||||
console.log(window.dataLayer);
|
||||
|
||||
// View last event pushed
|
||||
console.log(window.dataLayer[window.dataLayer.length - 1]);
|
||||
|
||||
// Listen for pushes
|
||||
var originalPush = window.dataLayer.push;
|
||||
window.dataLayer.push = function() {
|
||||
console.log('Data Layer Push:', arguments);
|
||||
return originalPush.apply(this, arguments);
|
||||
};
|
||||
```
|
||||
|
||||
### GTM Preview Mode
|
||||
|
||||
**Steps:**
|
||||
1. Click Preview in GTM
|
||||
2. Interact with website
|
||||
3. Tag Assistant shows:
|
||||
- **Data Layer** tab with all pushed events
|
||||
- Event details and parameters
|
||||
- Values of variables at time of event
|
||||
|
||||
## Common Mistakes
|
||||
|
||||
### Mistake 1: Pushing Empty Events
|
||||
|
||||
```javascript
|
||||
// BAD - No data
|
||||
dataLayer.push({
|
||||
'event': 'button_click'
|
||||
});
|
||||
|
||||
// GOOD - Include context
|
||||
dataLayer.push({
|
||||
'event': 'button_click',
|
||||
'button_name': 'Subscribe',
|
||||
'button_location': 'header'
|
||||
});
|
||||
```
|
||||
|
||||
### Mistake 2: Not Clearing ecommerce
|
||||
|
||||
```javascript
|
||||
// BAD - Old ecommerce data persists
|
||||
dataLayer.push({
|
||||
'event': 'add_to_cart',
|
||||
'ecommerce': {...}
|
||||
});
|
||||
|
||||
// GOOD
|
||||
dataLayer.push({ ecommerce: null });
|
||||
dataLayer.push({
|
||||
'event': 'add_to_cart',
|
||||
'ecommerce': {...}
|
||||
});
|
||||
```
|
||||
|
||||
### Mistake 3: Using Reserved Keys
|
||||
|
||||
**Avoid These Keys:**
|
||||
- `gtm` (reserved by GTM)
|
||||
- `google_tag_manager` (reserved)
|
||||
- `event` (only for trigger names)
|
||||
|
||||
### Mistake 4: Wrong Data Types
|
||||
|
||||
```javascript
|
||||
// BAD - String when should be number
|
||||
dataLayer.push({
|
||||
'event': 'purchase',
|
||||
'value': '99.99' // String
|
||||
});
|
||||
|
||||
// GOOD
|
||||
dataLayer.push({
|
||||
'event': 'purchase',
|
||||
'value': 99.99 // Number
|
||||
});
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Initialize Early:** Create `window.dataLayer` before GTM container
|
||||
2. **Consistent Naming:** Use snake_case for event and parameter names
|
||||
3. **Clear ecommerce:** Always clear before pushing new ecommerce data
|
||||
4. **Document Events:** Maintain documentation of all custom events
|
||||
5. **Test Thoroughly:** Use GTM Preview mode to verify data layer pushes
|
||||
6. **Avoid PII:** Don't push personal data (emails, names, addresses)
|
||||
7. **Use Structured Data:** Follow GA4 recommended event structures
|
||||
295
skills/ga4-gtm-integration/references/gtm-ga4-setup-complete.md
Normal file
295
skills/ga4-gtm-integration/references/gtm-ga4-setup-complete.md
Normal file
@@ -0,0 +1,295 @@
|
||||
# Complete GTM-GA4 Setup Guide
|
||||
|
||||
## Prerequisites
|
||||
|
||||
1. **GTM Container Installed** - GTM container code already on website
|
||||
2. **GA4 Property Created** - GA4 property with Measurement ID available
|
||||
3. **GTM Editor+ Access** - Required permissions to create/modify tags
|
||||
|
||||
## Step-by-Step Setup
|
||||
|
||||
### Step 1: Install GTM Container (If Not Already Installed)
|
||||
|
||||
**GTM Container Code Location:**
|
||||
|
||||
Place in `<head>` section (immediately after `<head>` tag):
|
||||
|
||||
```html
|
||||
<!-- Google Tag Manager -->
|
||||
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
|
||||
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
|
||||
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
|
||||
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
|
||||
})(window,document,'script','dataLayer','GTM-XXXXXXX');</script>
|
||||
<!-- End Google Tag Manager -->
|
||||
```
|
||||
|
||||
Place noscript fallback in `<body>` (immediately after `<body>` tag):
|
||||
|
||||
```html
|
||||
<!-- Google Tag Manager (noscript) -->
|
||||
<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-XXXXXXX"
|
||||
height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
|
||||
<!-- End Google Tag Manager (noscript) -->
|
||||
```
|
||||
|
||||
### Step 2: Create GA4 Configuration Tag
|
||||
|
||||
**In GTM Workspace:**
|
||||
|
||||
1. Navigate to **Tags → New**
|
||||
2. **Tag Name:** "GA4 - Configuration" (or "GA4 - Base Tag")
|
||||
|
||||
**Tag Configuration:**
|
||||
|
||||
3. Click **Tag Configuration** box
|
||||
4. Select **Google Tag** (tag type)
|
||||
5. **Tag ID:** Enter GA4 Measurement ID (format: `G-XXXXXXXXXX`)
|
||||
- Find in: GA4 Admin → Data Streams → Web Stream → Measurement ID
|
||||
|
||||
**Configuration Settings (Optional):**
|
||||
|
||||
6. Click **Configuration Settings** (expand if needed)
|
||||
7. Set optional parameters:
|
||||
- **send_page_view:** true (default - automatically sends page_view events)
|
||||
- **allow_google_signals:** true (for Demographics/Remarketing)
|
||||
- **allow_ad_personalization_signals:** true
|
||||
|
||||
**Shared Event Settings (Optional):**
|
||||
|
||||
8. Click **Shared Event Settings** to add parameters sent with ALL events:
|
||||
- Example: `user_tier`, `page_category`, etc.
|
||||
|
||||
**Triggering:**
|
||||
|
||||
9. Click **Triggering** box
|
||||
10. Select **Initialization - All Pages**
|
||||
- This fires BEFORE page_view
|
||||
- Ensures GA4 loads on every page
|
||||
|
||||
**Save:**
|
||||
|
||||
11. Click **Save**
|
||||
|
||||
**Result:** GA4 Configuration tag created and will fire on all pages
|
||||
|
||||
### Step 3: Test GA4 Configuration Tag
|
||||
|
||||
**Using GTM Preview Mode:**
|
||||
|
||||
1. Click **Preview** button (top-right of GTM)
|
||||
2. Enter your website URL
|
||||
3. Click **Connect**
|
||||
4. Tag Assistant opens in new window
|
||||
|
||||
**Verify in Tag Assistant:**
|
||||
|
||||
- **Summary** tab shows "Tag Fired: GA4 - Configuration"
|
||||
- **Tag** appears in "Tags Fired" section
|
||||
- Event: `gtm.js` (GTM initialization)
|
||||
- **Initialization** trigger activated
|
||||
|
||||
**Verify in GA4 DebugView:**
|
||||
|
||||
1. Open GA4 property
|
||||
2. Go to **Admin → DebugView**
|
||||
3. See events appearing in real-time:
|
||||
- `page_view` (automatic from GA4 Configuration tag)
|
||||
- `session_start`
|
||||
- `first_visit` (if first time)
|
||||
|
||||
### Step 4: Create GA4 Event Tags
|
||||
|
||||
**Example: Button Click Event**
|
||||
|
||||
**Create Tag:**
|
||||
|
||||
1. **Tags → New**
|
||||
2. **Name:** "GA4 - Button Click - Subscribe"
|
||||
3. **Tag Configuration → Google Tag**
|
||||
4. **Tag ID:** Same GA4 Measurement ID (G-XXXXXXXXXX)
|
||||
5. **Event Name:** `button_click`
|
||||
|
||||
**Event Parameters:**
|
||||
|
||||
6. Click **Add Parameter**
|
||||
7. Parameter entries:
|
||||
- **Parameter Name:** `button_name` → **Value:** `{{Button Text}}` (variable)
|
||||
- **Parameter Name:** `button_location` → **Value:** `header`
|
||||
- **Parameter Name:** `button_id` → **Value:** `{{Click ID}}`
|
||||
|
||||
**Triggering:**
|
||||
|
||||
8. Click **Triggering**
|
||||
9. Click **"+"** to create new trigger
|
||||
|
||||
**Create Trigger:**
|
||||
|
||||
10. **Trigger Name:** "Click - Subscribe Button"
|
||||
11. **Trigger Type:** Click - All Elements
|
||||
12. **This trigger fires on:** Some Clicks
|
||||
13. **Filter:**
|
||||
- **Click ID** → **equals** → `subscribe-btn`
|
||||
14. Click **Save**
|
||||
|
||||
**Save Event Tag:**
|
||||
|
||||
15. Click **Save**
|
||||
|
||||
### Step 5: Create Form Submission Event
|
||||
|
||||
**Create Tag:**
|
||||
|
||||
1. **Tags → New**
|
||||
2. **Name:** "GA4 - Form Submit - Contact"
|
||||
3. **Tag Configuration → Google Tag**
|
||||
4. **Tag ID:** G-XXXXXXXXXX
|
||||
5. **Event Name:** `form_submit`
|
||||
|
||||
**Event Parameters:**
|
||||
|
||||
6. Add Parameters:
|
||||
- `form_name` → `{{Form Name}}`
|
||||
- `form_id` → `{{Form ID}}`
|
||||
- `form_destination` → `/thank-you`
|
||||
|
||||
**Create Trigger:**
|
||||
|
||||
7. **Triggering → New Trigger**
|
||||
8. **Name:** "Form - Contact Form Submit"
|
||||
9. **Type:** Form Submission
|
||||
10. **Fire on:** Some Forms
|
||||
11. **Filter:** **Form ID** → **equals** → `contact-form`
|
||||
12. Save trigger and tag
|
||||
|
||||
### Step 6: Implement Custom Event with Data Layer
|
||||
|
||||
**On Website (in code):**
|
||||
|
||||
```javascript
|
||||
// When user adds item to cart
|
||||
document.querySelector('.add-to-cart-btn').addEventListener('click', function() {
|
||||
dataLayer.push({
|
||||
'event': 'add_to_cart',
|
||||
'product_id': 'SKU_123',
|
||||
'product_name': 'Blue T-Shirt',
|
||||
'price': 29.99,
|
||||
'quantity': 1
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
**In GTM:**
|
||||
|
||||
**Create Data Layer Variables:**
|
||||
|
||||
1. **Variables → New**
|
||||
2. **Name:** "DL - Product ID"
|
||||
3. **Type:** Data Layer Variable
|
||||
4. **Variable Name:** `product_id`
|
||||
5. Save
|
||||
|
||||
Repeat for `product_name`, `price`, `quantity`
|
||||
|
||||
**Create GA4 Event Tag:**
|
||||
|
||||
1. **Tags → New**
|
||||
2. **Name:** "GA4 - Add to Cart"
|
||||
3. **Tag Type:** Google Tag
|
||||
4. **Tag ID:** G-XXXXXXXXXX
|
||||
5. **Event Name:** `add_to_cart`
|
||||
6. **Parameters:**
|
||||
- `product_id` → `{{DL - Product ID}}`
|
||||
- `product_name` → `{{DL - Product Name}}`
|
||||
- `price` → `{{DL - Price}}`
|
||||
- `quantity` → `{{DL - Quantity}}`
|
||||
|
||||
**Create Trigger:**
|
||||
|
||||
7. **Triggering → New**
|
||||
8. **Name:** "Custom Event - Add to Cart"
|
||||
9. **Type:** Custom Event
|
||||
10. **Event name:** `add_to_cart`
|
||||
11. Save
|
||||
|
||||
### Step 7: Test All Tags with Preview Mode
|
||||
|
||||
**Preview Workflow:**
|
||||
|
||||
1. Click **Preview** in GTM
|
||||
2. Connect to website
|
||||
3. Navigate pages and interact with elements
|
||||
4. **Tag Assistant** shows:
|
||||
- Which tags fired
|
||||
- Which didn't fire (and why)
|
||||
- Variable values
|
||||
- Data layer state
|
||||
|
||||
**Check Each Event:**
|
||||
|
||||
- Click subscribe button → Verify "GA4 - Button Click" fires
|
||||
- Submit contact form → Verify "GA4 - Form Submit" fires
|
||||
- Add item to cart → Verify "GA4 - Add to Cart" fires
|
||||
|
||||
**Verify in GA4 DebugView:**
|
||||
|
||||
- All events appear with correct names
|
||||
- Parameters populate with expected values
|
||||
- No duplicate events
|
||||
|
||||
### Step 8: Publish GTM Container
|
||||
|
||||
**When Ready:**
|
||||
|
||||
1. Click **Submit** (top-right)
|
||||
2. **Version Name:** "GA4 Initial Setup - [Date]"
|
||||
3. **Version Description:**
|
||||
```
|
||||
- Added GA4 Configuration tag
|
||||
- Added button click tracking
|
||||
- Added form submission tracking
|
||||
- Added add_to_cart event via data layer
|
||||
```
|
||||
4. Click **Publish**
|
||||
5. **Result:** Changes live immediately on website
|
||||
|
||||
### Step 9: Verify Production
|
||||
|
||||
**After Publishing:**
|
||||
|
||||
1. Visit website (incognito/private mode)
|
||||
2. Enable **Google Analytics Debugger** Chrome extension
|
||||
3. Interact with tracked elements
|
||||
4. Check **GA4 DebugView** for events
|
||||
|
||||
**Wait 24-48 hours:**
|
||||
- Events appear in standard GA4 reports
|
||||
- Custom dimensions/metrics populate
|
||||
|
||||
## Common Setup Issues
|
||||
|
||||
| Issue | Cause | Solution |
|
||||
|-------|-------|----------|
|
||||
| **Tags not firing** | Wrong trigger conditions | Check trigger settings in Preview mode |
|
||||
| **GA4 Configuration not firing** | Wrong trigger selected | Must use "Initialization - All Pages" |
|
||||
| **Parameters empty** | Variables not created | Create Data Layer Variables first |
|
||||
| **Duplicate page_views** | Both gtag.js and GTM | Remove gtag.js snippet from website |
|
||||
| **Events delayed** | Normal processing | Events appear in DebugView immediately, reports in 24-48 hours |
|
||||
|
||||
## Best Practices
|
||||
|
||||
**Naming Conventions:**
|
||||
- Tags: "GA4 - [Event Name]"
|
||||
- Triggers: "[Type] - [Description]"
|
||||
- Variables: "DL - [Variable Name]" or "GTM - [Built-in Name]"
|
||||
|
||||
**Organization:**
|
||||
- Use folders for related tags/triggers/variables
|
||||
- Document changes in version descriptions
|
||||
- Test thoroughly before publishing
|
||||
- Keep GA4 Configuration tag separate from event tags
|
||||
|
||||
**Performance:**
|
||||
- Use specific triggers (not "All Elements" when possible)
|
||||
- Minimize data layer pushes
|
||||
- Batch related events when feasible
|
||||
317
skills/ga4-gtm-integration/references/gtm-preview-debugging.md
Normal file
317
skills/ga4-gtm-integration/references/gtm-preview-debugging.md
Normal file
@@ -0,0 +1,317 @@
|
||||
# GTM Preview Mode and Debugging Guide
|
||||
|
||||
## Enabling Preview Mode
|
||||
|
||||
**Steps:**
|
||||
1. Open GTM workspace
|
||||
2. Click **Preview** button (top-right)
|
||||
3. Enter website URL in popup
|
||||
4. Click **Connect**
|
||||
5. New browser tab opens with Tag Assistant
|
||||
|
||||
**Result:** Tag Assistant panel shows real-time tag activity
|
||||
|
||||
## Tag Assistant Interface
|
||||
|
||||
### Summary Tab
|
||||
|
||||
**Shows:**
|
||||
- Tags Fired count
|
||||
- Tags Not Fired count
|
||||
- Data Layer Messages
|
||||
- Event timeline
|
||||
|
||||
### Tags Tab
|
||||
|
||||
**Categories:**
|
||||
- **Tags Fired:** Successfully triggered tags
|
||||
- **Tags Not Fired:** Tags that didn't trigger
|
||||
- **Tag Firing Failed:** Tags with errors
|
||||
|
||||
**For Each Tag:**
|
||||
- Tag name
|
||||
- Trigger that fired it
|
||||
- Variables used
|
||||
- Parameters sent
|
||||
|
||||
### Variables Tab
|
||||
|
||||
**Shows All Variables:**
|
||||
- Name
|
||||
- Current value
|
||||
- Type
|
||||
- Last updated
|
||||
|
||||
### Data Layer Tab
|
||||
|
||||
**Shows:**
|
||||
- All dataLayer pushes
|
||||
- Event details
|
||||
- Parameters
|
||||
- Timestamp
|
||||
|
||||
### Errors Tab
|
||||
|
||||
**Shows:**
|
||||
- JavaScript errors
|
||||
- Tag firing errors
|
||||
- Configuration issues
|
||||
|
||||
## Debugging Workflow
|
||||
|
||||
### Step 1: Verify GA4 Configuration Tag
|
||||
|
||||
**In Tag Assistant:**
|
||||
1. Look for **"GA4 - Configuration"** in **Tags Fired**
|
||||
2. Check it fired on **Initialization - All Pages** trigger
|
||||
3. Verify Tag ID is correct (G-XXXXXXXXXX)
|
||||
|
||||
**Expected:** Fires on every page load
|
||||
|
||||
### Step 2: Test Event Tags
|
||||
|
||||
**Workflow:**
|
||||
1. Trigger expected action (click button, submit form)
|
||||
2. Check **Tags Fired** for corresponding GA4 event tag
|
||||
3. Expand tag to see:
|
||||
- **Event Name:** Correct event name
|
||||
- **Event Parameters:** Populated with expected values
|
||||
- **Trigger:** Correct trigger fired
|
||||
|
||||
**Example: Button Click**
|
||||
- Click "Subscribe" button
|
||||
- Verify "GA4 - Button Click - Subscribe" in Tags Fired
|
||||
- Check Event Parameters:
|
||||
- `button_name`: "Subscribe Now"
|
||||
- `button_location`: "header"
|
||||
|
||||
### Step 3: Verify Variables
|
||||
|
||||
**In Variables Tab:**
|
||||
1. Locate variable (e.g., "DL - Product ID")
|
||||
2. Check **Value** column
|
||||
3. Verify value matches expected data
|
||||
|
||||
**Common Variables to Check:**
|
||||
- Data Layer Variables
|
||||
- Click Variables (after clicking element)
|
||||
- Form Variables (after form interaction)
|
||||
- Page Variables (on page load)
|
||||
|
||||
### Step 4: Check Data Layer
|
||||
|
||||
**In Data Layer Tab:**
|
||||
1. See all `dataLayer.push()` calls
|
||||
2. Expand each message
|
||||
3. Verify structure and values
|
||||
|
||||
**Example:**
|
||||
```
|
||||
Message: {event: "add_to_cart", product_id: "SKU_123", ...}
|
||||
Event: add_to_cart
|
||||
Variables:
|
||||
- product_id: "SKU_123"
|
||||
- product_name: "Blue T-Shirt"
|
||||
- price: 29.99
|
||||
```
|
||||
|
||||
### Step 5: Verify in GA4 DebugView
|
||||
|
||||
**After Tags Fire in GTM:**
|
||||
1. Open GA4 property
|
||||
2. Go to **Admin → DebugView**
|
||||
3. Events appear in real-time
|
||||
4. Click event to see parameters
|
||||
|
||||
**Verify:**
|
||||
- Event name matches GTM event name
|
||||
- Parameters match GTM event parameters
|
||||
- Values are correct types (strings, numbers)
|
||||
|
||||
## Common Debugging Scenarios
|
||||
|
||||
### Scenario 1: Tag Not Firing
|
||||
|
||||
**Symptoms:**
|
||||
- Tag appears in **Tags Not Fired**
|
||||
- Expected action performed but tag doesn't fire
|
||||
|
||||
**Troubleshooting:**
|
||||
1. **Check Trigger Conditions:**
|
||||
- Expand tag in **Tags Not Fired**
|
||||
- See "Why didn't this tag fire?"
|
||||
- Review trigger conditions
|
||||
|
||||
2. **Verify Trigger Variables:**
|
||||
- Check variables used in trigger
|
||||
- Ensure they have expected values
|
||||
|
||||
3. **Check Trigger Type:**
|
||||
- Click trigger: Did you click the right element?
|
||||
- Form trigger: Did form actually submit?
|
||||
- Custom Event: Was event pushed to dataLayer?
|
||||
|
||||
4. **Check Exceptions:**
|
||||
- Tag may have exception preventing firing
|
||||
|
||||
**Example Fix:**
|
||||
- **Problem:** Click trigger for button ID "subscribe-btn" not firing
|
||||
- **Check:** Click ID variable value
|
||||
- **Find:** Actual button ID is "subscribe-button"
|
||||
- **Fix:** Update trigger condition
|
||||
|
||||
### Scenario 2: Wrong Variable Value
|
||||
|
||||
**Symptoms:**
|
||||
- Tag fires but parameter value is wrong/empty
|
||||
- Variable shows `undefined` or wrong data
|
||||
|
||||
**Troubleshooting:**
|
||||
1. **Check Variable Configuration:**
|
||||
- Data Layer Variable: Verify key name (case-sensitive)
|
||||
- JavaScript Variable: Check global variable exists
|
||||
- Click Variable: Ensure element has attribute
|
||||
|
||||
2. **Check Data Layer:**
|
||||
- Go to Data Layer tab
|
||||
- Find relevant dataLayer push
|
||||
- Verify key exists and has value
|
||||
|
||||
3. **Check Timing:**
|
||||
- Variable may not be set when tag fires
|
||||
- Ensure data layer push happens BEFORE tag fires
|
||||
|
||||
**Example Fix:**
|
||||
- **Problem:** `product_id` variable empty
|
||||
- **Check:** Data Layer tab
|
||||
- **Find:** Key is `productId` (camelCase), not `product_id`
|
||||
- **Fix:** Update variable name to `productId`
|
||||
|
||||
### Scenario 3: Duplicate Events
|
||||
|
||||
**Symptoms:**
|
||||
- Same event fires multiple times
|
||||
- Duplicate events in GA4
|
||||
|
||||
**Troubleshooting:**
|
||||
1. **Check for Multiple Triggers:**
|
||||
- Same event tag may have multiple triggers
|
||||
- Review tag's triggering section
|
||||
|
||||
2. **Check for Multiple Tags:**
|
||||
- Multiple tags for same event
|
||||
- Search for duplicate tag names
|
||||
|
||||
3. **Check for gtag.js + GTM:**
|
||||
- Website may have both gtag.js snippet AND GTM
|
||||
- Remove gtag.js if using GTM
|
||||
|
||||
**Example Fix:**
|
||||
- **Problem:** `page_view` firing twice
|
||||
- **Find:** Both gtag.js snippet in <head> and GTM GA4 Configuration tag
|
||||
- **Fix:** Remove gtag.js snippet
|
||||
|
||||
### Scenario 4: Missing Event Parameters
|
||||
|
||||
**Symptoms:**
|
||||
- Event fires but some parameters missing
|
||||
- GA4 DebugView shows event without expected parameters
|
||||
|
||||
**Troubleshooting:**
|
||||
1. **Check Tag Configuration:**
|
||||
- Expand tag in Preview
|
||||
- Verify all parameters added to tag
|
||||
|
||||
2. **Check Variable Values:**
|
||||
- Variables Tab: Check parameter variables have values
|
||||
- Empty variables won't send parameters
|
||||
|
||||
3. **Check Data Layer:**
|
||||
- Ensure data layer includes all expected keys
|
||||
- Verify spelling and case
|
||||
|
||||
**Example Fix:**
|
||||
- **Problem:** `item_category` parameter missing from `add_to_cart`
|
||||
- **Check:** Variables Tab
|
||||
- **Find:** `DL - Item Category` has value `undefined`
|
||||
- **Root Cause:** dataLayer push missing `item_category` key
|
||||
- **Fix:** Update dataLayer push to include `item_category`
|
||||
|
||||
## Advanced Debugging
|
||||
|
||||
### Debugging Data Layer
|
||||
|
||||
**View in Console:**
|
||||
```javascript
|
||||
// View entire data layer
|
||||
window.dataLayer
|
||||
|
||||
// View last message
|
||||
window.dataLayer[window.dataLayer.length - 1]
|
||||
|
||||
// Monitor pushes
|
||||
var _push = window.dataLayer.push;
|
||||
window.dataLayer.push = function() {
|
||||
console.log('dataLayer push:', arguments);
|
||||
return _push.apply(this, arguments);
|
||||
};
|
||||
```
|
||||
|
||||
### Debugging Triggers
|
||||
|
||||
**Test Trigger Manually:**
|
||||
1. Preview mode active
|
||||
2. Open Console
|
||||
3. Manually push event:
|
||||
```javascript
|
||||
dataLayer.push({'event': 'test_event'});
|
||||
```
|
||||
4. Check if trigger fires
|
||||
|
||||
### Debugging Variables
|
||||
|
||||
**Check Variable in Console:**
|
||||
```javascript
|
||||
// For built-in variables
|
||||
google_tag_manager['GTM-XXXXXXX'].dataLayer.get('variableName')
|
||||
|
||||
// For data layer
|
||||
window.dataLayer.find(item => item.product_id)
|
||||
```
|
||||
|
||||
## Testing Checklist
|
||||
|
||||
**Before Publishing:**
|
||||
|
||||
- [ ] GA4 Configuration tag fires on all pages
|
||||
- [ ] All event tags fire when expected
|
||||
- [ ] No tags in "Tags Not Fired" section
|
||||
- [ ] Variables populate with correct values
|
||||
- [ ] Event parameters sent to GA4
|
||||
- [ ] No duplicate events firing
|
||||
- [ ] Data Layer pushes correctly formatted
|
||||
- [ ] Events appear in GA4 DebugView
|
||||
- [ ] Parameters match expected values in DebugView
|
||||
- [ ] No JavaScript errors in Errors tab
|
||||
|
||||
## Best Practices
|
||||
|
||||
**During Development:**
|
||||
1. Test each tag immediately after creating
|
||||
2. Use Preview mode for every change
|
||||
3. Verify in both GTM and GA4 DebugView
|
||||
4. Document expected behavior
|
||||
5. Test on multiple pages/scenarios
|
||||
|
||||
**Before Publishing:**
|
||||
1. Complete testing checklist
|
||||
2. Test with team members
|
||||
3. Document all tags/triggers/variables
|
||||
4. Create version description
|
||||
5. Schedule publication during low-traffic period
|
||||
|
||||
**After Publishing:**
|
||||
1. Verify tags still working in production
|
||||
2. Monitor GA4 DebugView for 30 minutes
|
||||
3. Check standard GA4 reports next day
|
||||
4. Monitor for anomalies
|
||||
@@ -0,0 +1,429 @@
|
||||
# GTM Tags, Triggers, and Variables Reference for GA4
|
||||
|
||||
## Tag Types for GA4
|
||||
|
||||
### Google Tag (GA4 Configuration Tag)
|
||||
|
||||
**Purpose:** Initialize GA4 tracking on pages
|
||||
|
||||
**Configuration:**
|
||||
- **Tag ID:** GA4 Measurement ID (G-XXXXXXXXXX)
|
||||
- **Trigger:** Initialization - All Pages
|
||||
- **send_page_view:** true (automatic page_view events)
|
||||
|
||||
**When to Use:** One per GA4 property, fires on all pages
|
||||
|
||||
### Google Tag (GA4 Event Tag)
|
||||
|
||||
**Purpose:** Track specific events
|
||||
|
||||
**Configuration:**
|
||||
- **Tag ID:** Same GA4 Measurement ID
|
||||
- **Event Name:** Specific event (e.g., `button_click`, `purchase`)
|
||||
- **Event Parameters:** Additional data
|
||||
|
||||
**When to Use:** Each specific event you want to track
|
||||
|
||||
## Trigger Types
|
||||
|
||||
### Page View Triggers
|
||||
|
||||
**All Pages**
|
||||
- Fires on: Every page load
|
||||
- Use for: GA4 Configuration tag
|
||||
|
||||
**Some Pages**
|
||||
- Fires on: Pages matching conditions
|
||||
- Conditions: Page Path, Page URL, Page Hostname
|
||||
- Example: Page Path contains `/checkout`
|
||||
|
||||
**DOM Ready**
|
||||
- Fires when: DOM fully loaded
|
||||
- Use for: Tags requiring DOM elements
|
||||
|
||||
**Window Loaded**
|
||||
- Fires when: Page fully loaded (images, CSS, JS)
|
||||
- Use for: Tags after full page load
|
||||
|
||||
### Click Triggers
|
||||
|
||||
**All Elements**
|
||||
- Fires on: Any click
|
||||
- Filter by: Click ID, Class, URL, Text
|
||||
- Example: Click ID equals `subscribe-btn`
|
||||
|
||||
**Just Links**
|
||||
- Fires on: `<a>` tag clicks only
|
||||
- Filter by: Click URL contains, starts with, equals
|
||||
- Example: Outbound link tracking
|
||||
|
||||
### Form Triggers
|
||||
|
||||
**Form Submission**
|
||||
- Fires when: Form submitted
|
||||
- Filter by: Form ID, Class, URL, Text
|
||||
- Example: Form ID equals `contact-form`
|
||||
|
||||
**Form Start** (Built-in Variable)
|
||||
- Fires when: User interacts with form first time
|
||||
- Use for: Form abandonment tracking
|
||||
|
||||
### Custom Event Triggers
|
||||
|
||||
**Custom Event**
|
||||
- Fires when: `dataLayer.push({event: 'event_name'})`
|
||||
- Event name: Exact match to data layer event
|
||||
- Example: Event name = `add_to_cart`
|
||||
|
||||
### Scroll Depth Trigger
|
||||
|
||||
**Scroll Depth**
|
||||
- Fires on: Vertical scroll percentages
|
||||
- Thresholds: 25%, 50%, 75%, 90%
|
||||
- Use for: Content engagement tracking
|
||||
|
||||
### Element Visibility Trigger
|
||||
|
||||
**Element Visibility**
|
||||
- Fires when: Element visible on screen
|
||||
- Selection Method: ID, CSS Selector
|
||||
- Use for: Scroll-based element tracking
|
||||
|
||||
### Timer Trigger
|
||||
|
||||
**Timer**
|
||||
- Fires on: Time intervals
|
||||
- Interval: Milliseconds
|
||||
- Limit: Optional max fires
|
||||
- Use for: Engagement time tracking
|
||||
|
||||
## Variable Types
|
||||
|
||||
### Built-in Variables (Enable in Variables Section)
|
||||
|
||||
**Page Variables:**
|
||||
- Page URL (full URL)
|
||||
- Page Hostname (domain only)
|
||||
- Page Path (path only, no domain)
|
||||
- Referrer (previous page URL)
|
||||
|
||||
**Click Variables:**
|
||||
- Click Element (entire element)
|
||||
- Click Classes (CSS classes)
|
||||
- Click ID (element ID)
|
||||
- Click Target (link target)
|
||||
- Click Text (visible text)
|
||||
- Click URL (link href)
|
||||
|
||||
**Form Variables:**
|
||||
- Form Element (entire form)
|
||||
- Form Classes (CSS classes)
|
||||
- Form ID (form ID attribute)
|
||||
- Form Target (form target)
|
||||
- Form Text (visible text in form)
|
||||
- Form URL (form action URL)
|
||||
|
||||
**Utilities:**
|
||||
- Random Number
|
||||
- Debug Mode (true in Preview)
|
||||
- Container ID (GTM-XXXXXXX)
|
||||
- Container Version
|
||||
|
||||
### Custom Variables
|
||||
|
||||
**Data Layer Variable**
|
||||
- Type: Data Layer Variable
|
||||
- Variable Name: Key from `dataLayer` (e.g., `product_id`)
|
||||
- Use: Access data layer values
|
||||
|
||||
**JavaScript Variable**
|
||||
- Type: JavaScript Variable
|
||||
- Global Variable Name: JavaScript variable name
|
||||
- Example: `window.location.hostname`
|
||||
|
||||
**1st Party Cookie**
|
||||
- Type: 1st Party Cookie
|
||||
- Cookie Name: Name of cookie
|
||||
- Use: Read cookie values
|
||||
|
||||
**Custom JavaScript**
|
||||
- Type: Custom JavaScript
|
||||
- Returns: Value from custom function
|
||||
|
||||
**Example:**
|
||||
```javascript
|
||||
function() {
|
||||
return document.querySelector('.product-price').textContent;
|
||||
}
|
||||
```
|
||||
|
||||
**Lookup Table**
|
||||
- Type: Lookup Table
|
||||
- Input Variable: Variable to map
|
||||
- Mapping: Input value → Output value
|
||||
|
||||
**Example:**
|
||||
- Input: `{{Page Type}}`
|
||||
- `product` → `product_page`
|
||||
- `category` → `category_page`
|
||||
|
||||
**RegEx Table**
|
||||
- Type: RegEx Table
|
||||
- Pattern matching with regex
|
||||
- Use: Complex URL/path mapping
|
||||
|
||||
## Common Tag Configurations
|
||||
|
||||
### 1. GA4 Configuration Tag
|
||||
|
||||
```
|
||||
Tag Type: Google Tag
|
||||
Tag ID: G-XXXXXXXXXX
|
||||
Trigger: Initialization - All Pages
|
||||
Configuration Settings:
|
||||
- send_page_view: true
|
||||
- allow_google_signals: true
|
||||
```
|
||||
|
||||
### 2. Button Click Event Tag
|
||||
|
||||
```
|
||||
Tag Type: Google Tag
|
||||
Tag ID: G-XXXXXXXXXX
|
||||
Event Name: button_click
|
||||
Event Parameters:
|
||||
- button_name: {{Button Text}}
|
||||
- button_location: header
|
||||
Trigger: Click - Subscribe Button
|
||||
```
|
||||
|
||||
### 3. Form Submission Tag
|
||||
|
||||
```
|
||||
Tag Type: Google Tag
|
||||
Tag ID: G-XXXXXXXXXX
|
||||
Event Name: form_submit
|
||||
Event Parameters:
|
||||
- form_name: {{Form Name}}
|
||||
- form_id: {{Form ID}}
|
||||
- form_destination: /thank-you
|
||||
Trigger: Form - Contact Form Submit
|
||||
```
|
||||
|
||||
### 4. Add to Cart Tag (Data Layer)
|
||||
|
||||
```
|
||||
Tag Type: Google Tag
|
||||
Tag ID: G-XXXXXXXXXX
|
||||
Event Name: add_to_cart
|
||||
Event Parameters:
|
||||
- items: {{DL - Ecommerce Items}}
|
||||
- value: {{DL - Ecommerce Value}}
|
||||
- currency: {{DL - Ecommerce Currency}}
|
||||
Trigger: Custom Event - add_to_cart
|
||||
```
|
||||
|
||||
### 5. Purchase Tag (Data Layer)
|
||||
|
||||
```
|
||||
Tag Type: Google Tag
|
||||
Tag ID: G-XXXXXXXXXX
|
||||
Event Name: purchase
|
||||
Event Parameters:
|
||||
- transaction_id: {{DL - Transaction ID}}
|
||||
- value: {{DL - Ecommerce Value}}
|
||||
- currency: {{DL - Ecommerce Currency}}
|
||||
- tax: {{DL - Tax}}
|
||||
- shipping: {{DL - Shipping}}
|
||||
- items: {{DL - Ecommerce Items}}
|
||||
Trigger: Custom Event - purchase
|
||||
```
|
||||
|
||||
## Common Trigger Configurations
|
||||
|
||||
### 1. All Pages Trigger
|
||||
|
||||
```
|
||||
Trigger Type: Page View - All Pages
|
||||
Fires on: All page views
|
||||
Use: GA4 Configuration tag
|
||||
```
|
||||
|
||||
### 2. Specific Page Trigger
|
||||
|
||||
```
|
||||
Trigger Type: Page View - Some Pages
|
||||
Fires on: Some Pages
|
||||
Condition: Page Path contains /checkout
|
||||
Use: Checkout page tracking
|
||||
```
|
||||
|
||||
### 3. Click - Specific Button
|
||||
|
||||
```
|
||||
Trigger Type: Click - All Elements
|
||||
Fires on: Some Clicks
|
||||
Condition: Click ID equals subscribe-btn
|
||||
Use: Button click events
|
||||
```
|
||||
|
||||
### 4. Click - Outbound Links
|
||||
|
||||
```
|
||||
Trigger Type: Click - Just Links
|
||||
Fires on: Some Link Clicks
|
||||
Condition: Click URL does not contain {{Page Hostname}}
|
||||
Use: External link tracking
|
||||
```
|
||||
|
||||
### 5. Form - Specific Form
|
||||
|
||||
```
|
||||
Trigger Type: Form Submission
|
||||
Fires on: Some Forms
|
||||
Condition: Form ID equals contact-form
|
||||
Use: Form submission tracking
|
||||
```
|
||||
|
||||
### 6. Custom Event - Data Layer
|
||||
|
||||
```
|
||||
Trigger Type: Custom Event
|
||||
Event name: add_to_cart
|
||||
Use: Data layer event tracking
|
||||
```
|
||||
|
||||
### 7. Scroll Depth
|
||||
|
||||
```
|
||||
Trigger Type: Scroll Depth
|
||||
Vertical Scroll Depths: 25, 50, 75, 90
|
||||
Fires on: All Pages
|
||||
Use: Content engagement
|
||||
```
|
||||
|
||||
### 8. Element Visibility
|
||||
|
||||
```
|
||||
Trigger Type: Element Visibility
|
||||
Selection Method: ID
|
||||
Element Selector: video-player
|
||||
Fires on: Page View
|
||||
Minimum Percent Visible: 50%
|
||||
Use: Video player visibility
|
||||
```
|
||||
|
||||
## Advanced Configurations
|
||||
|
||||
### Trigger Groups (AND Logic)
|
||||
|
||||
**Some Clicks with Multiple Conditions:**
|
||||
|
||||
```
|
||||
Fires on: Some Clicks
|
||||
Conditions (ALL must match):
|
||||
- Click Classes contains cta-button
|
||||
- Click URL does not contain #
|
||||
- Page Path equals /pricing
|
||||
```
|
||||
|
||||
### Trigger Exceptions
|
||||
|
||||
**Fire Except on Certain Pages:**
|
||||
|
||||
```
|
||||
Tag: GA4 - Page View Enhanced
|
||||
Trigger: All Pages
|
||||
Exception: Admin Pages (Page Path contains /admin)
|
||||
```
|
||||
|
||||
### Variable Fallbacks
|
||||
|
||||
**Using Lookup Table with Default:**
|
||||
|
||||
```
|
||||
Input: {{Page Type}}
|
||||
Table:
|
||||
- product → product_page
|
||||
- category → category_page
|
||||
Default Value: other_page
|
||||
```
|
||||
|
||||
## Naming Conventions
|
||||
|
||||
**Tags:**
|
||||
- Format: `[Platform] - [Event/Type] - [Description]`
|
||||
- Examples:
|
||||
- `GA4 - Configuration`
|
||||
- `GA4 - Button Click - Subscribe`
|
||||
- `GA4 - Purchase`
|
||||
|
||||
**Triggers:**
|
||||
- Format: `[Type] - [Description]`
|
||||
- Examples:
|
||||
- `All Pages`
|
||||
- `Click - Subscribe Button`
|
||||
- `Form - Contact Form Submit`
|
||||
- `Custom Event - add_to_cart`
|
||||
|
||||
**Variables:**
|
||||
- Format: `[Source] - [Variable Name]`
|
||||
- Examples:
|
||||
- `DL - Product ID` (Data Layer)
|
||||
- `GTM - Page Path` (Built-in)
|
||||
- `JS - User Tier` (JavaScript)
|
||||
- `Cookie - Session ID` (1st Party Cookie)
|
||||
|
||||
## Testing Configurations
|
||||
|
||||
### Using Preview Mode
|
||||
|
||||
**Steps:**
|
||||
1. Set up tag/trigger/variable
|
||||
2. Click Preview
|
||||
3. Connect to site
|
||||
4. Trigger expected behavior
|
||||
5. Verify in Tag Assistant:
|
||||
- Tag fires
|
||||
- Variables populate correctly
|
||||
- Parameters sent to GA4
|
||||
|
||||
### Common Test Scenarios
|
||||
|
||||
**Test 1: Click Trigger**
|
||||
- Click element
|
||||
- Verify tag fires
|
||||
- Check Click Variables populate
|
||||
|
||||
**Test 2: Form Trigger**
|
||||
- Fill form
|
||||
- Submit
|
||||
- Verify tag fires after submission
|
||||
- Check Form Variables
|
||||
|
||||
**Test 3: Data Layer Event**
|
||||
- Trigger data layer push
|
||||
- Verify Custom Event trigger fires
|
||||
- Check Data Layer Variables
|
||||
|
||||
**Test 4: Page View**
|
||||
- Navigate to specific page
|
||||
- Verify trigger conditions met
|
||||
- Check Page Variables
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
**Tag Not Firing:**
|
||||
- Check trigger conditions in Preview
|
||||
- Verify variables have values
|
||||
- Check trigger exceptions
|
||||
|
||||
**Wrong Variable Value:**
|
||||
- Check variable type configuration
|
||||
- Verify data layer key name (case-sensitive)
|
||||
- Check variable persistence settings
|
||||
|
||||
**Duplicate Firing:**
|
||||
- Check for multiple matching triggers
|
||||
- Review trigger conditions for overlap
|
||||
- Check tag firing priorities
|
||||
Reference in New Issue
Block a user