Initial commit

This commit is contained in:
Zhongwei Li
2025-11-29 18:32:45 +08:00
commit c02dafae1d
41 changed files with 17283 additions and 0 deletions

0
skills/.gitkeep Normal file
View File

58
skills/README.md Normal file
View File

@@ -0,0 +1,58 @@
# GTM Suite - Skills
Add your GTM skills here. Each skill should be in its own directory with a SKILL.md file.
## Suggested Skills
```
skills/
├── event-tracking/
│ ├── SKILL.md
│ ├── scripts/
│ └── references/
├── container-management/
│ ├── SKILL.md
│ └── references/
├── variable-configuration/
│ ├── SKILL.md
│ └── references/
├── trigger-setup/
│ ├── SKILL.md
│ └── references/
├── tag-templates/
│ ├── SKILL.md
│ ├── assets/
│ └── references/
└── debugging-tools/
├── SKILL.md
├── scripts/
└── references/
```
## Skill Format
Each skill directory should contain:
- **SKILL.md** (required) - Main skill file with frontmatter
- **scripts/** (optional) - Executable scripts
- **references/** (optional) - Documentation to load as needed
- **assets/** (optional) - Templates and files for output
### SKILL.md Structure
```markdown
---
name: skill-name
description: When this skill should be used
---
# Skill Name
## Overview
What this skill does
## Workflow
How to use this skill
## Resources
Reference the bundled resources (scripts, references, assets)
```

181
skills/gtm-api/SKILL.md Normal file
View File

@@ -0,0 +1,181 @@
---
name: gtm-api
description: Expert guidance for Google Tag Manager REST API v2 including authentication, programmatic container management, automation scripts, bulk operations, and GTM configuration backup/export. Use when automating GTM operations, managing multiple containers, building GTM tools, syncing configurations, exporting GTM data programmatically, working with Python or Node.js GTM automation, or using service account JSON credentials. Requires google-api-python-client and google-auth packages for Python implementations.
---
# GTM API Automation
## Overview
This skill provides comprehensive expertise for the Google Tag Manager REST API v2, enabling programmatic management of GTM containers, tags, triggers, variables, and configurations.
## When to Use This Skill
Invoke this skill when:
- Automating GTM container management
- Building tools for GTM configuration backup/restore
- Syncing tags across multiple containers
- Bulk creating or updating tags, triggers, variables
- Exporting GTM configuration to JSON
- Migrating containers between accounts
- Programmatically publishing GTM versions
- Building custom GTM management dashboards
- Implementing GTM configuration as code
- Integrating GTM with CI/CD pipelines
## GTM API Basics
### Authentication
Use OAuth 2.0 with service accounts (recommended for automation):
```python
from google.oauth2 import service_account
from googleapiclient.discovery import build
SCOPES = ['https://www.googleapis.com/auth/tagmanager.edit.containers']
SERVICE_ACCOUNT_FILE = 'service-account-key.json'
credentials = service_account.Credentials.from_service_account_file(
SERVICE_ACCOUNT_FILE, scopes=SCOPES)
service = build('tagmanager', 'v2', credentials=credentials)
```
### API Resource Hierarchy
```
Account → Container → Workspace → Tags/Triggers/Variables
```
## Common Operations
**List Containers:**
```python
containers = service.accounts().containers().list(
parent='accounts/123456'
).execute()
```
**Create Tag:**
```python
tag_body = {
'name': 'GA4 Event',
'type': 'gaawe',
'parameter': [
{'key': 'eventName', 'value': 'click', 'type': 'template'}
],
'firingTriggerId': ['trigger_id']
}
service.accounts().containers().workspaces().tags().create(
parent=workspace_path, body=tag_body
).execute()
```
**Publish Version:**
```python
version = service.accounts().containers().workspaces().create_version(
path=workspace_path,
body={'name': 'API Version', 'description': 'Auto-deployed'}
).execute()
service.accounts().containers().versions().publish(
path=version['containerVersion']['path']
).execute()
```
## Automation Patterns
### Backup Container
```python
def backup_container(workspace_path, output_file):
tags = service.accounts().containers().workspaces().tags().list(
parent=workspace_path
).execute()
triggers = service.accounts().containers().workspaces().triggers().list(
parent=workspace_path
).execute()
variables = service.accounts().containers().workspaces().variables().list(
parent=workspace_path
).execute()
with open(output_file, 'w') as f:
json.dump({
'tags': tags.get('tag', []),
'triggers': triggers.get('trigger', []),
'variables': variables.get('variable', [])
}, f, indent=2)
```
### Bulk Operations
```python
def disable_all_tags(workspace_path):
tags = service.accounts().containers().workspaces().tags().list(
parent=workspace_path
).execute()
for tag in tags.get('tag', []):
tag['paused'] = True
service.accounts().containers().workspaces().tags().update(
path=tag['path'], body=tag
).execute()
```
## Error Handling
```python
from googleapiclient.errors import HttpError
try:
tag = service.accounts().containers().workspaces().tags().create(
parent=workspace_path, body=tag_body
).execute()
except HttpError as error:
if error.resp.status == 404:
print("Resource not found")
elif error.resp.status == 403:
print("Permission denied")
```
## Best Practices
- Use service accounts for automation
- Implement rate limiting
- Always backup before modifications
- Test in workspaces before publishing
- Log all operations
- Handle errors gracefully
- Version control your configs
## References
- **references/api-overview.md** - Complete API reference
## Integration with Other Skills
- **gtm-general** - Understanding GTM concepts and architecture
- **gtm-tags** - Understanding tag structure for API operations
- **gtm-triggers** - Understanding trigger structure for API operations
- **gtm-variables** - Understanding variable structure for API operations
- **gtm-datalayer** - Creating data layer variables via API
- **gtm-custom-templates** - Managing templates programmatically
- **gtm-setup** - Container setup concepts for API automation
## Quick Reference
**Install:** `pip install google-api-python-client google-auth-oauthlib`
**List:** `.list(parent=parent_path)`
**Get:** `.get(path=resource_path)`
**Create:** `.create(parent=parent_path, body=resource_body)`
**Update:** `.update(path=resource_path, body=resource_body)`
**Publish:** `.create_version()` then `.publish()`

View File

@@ -0,0 +1,470 @@
# GTM API Overview
**Sources**:
- https://developers.google.com/tag-platform/tag-manager/api/v2
- https://developers.google.com/tag-platform/tag-manager/api/v2/devguide
**Last Updated**: 2025-01-09
## Overview
The Google Tag Manager API provides programmatic access to Google Tag Manager configuration data for authorized users. With this API, you can automate common tag management tasks, including creating containers, managing tags, triggers, variables, and publishing container versions.
## Why Use the GTM API
**Benefits:**
- **Automation**: Automate repetitive tasks like creating similar tags across containers
- **Scalability**: Manage multiple containers programmatically
- **Integration**: Integrate GTM with your existing workflows and tools
- **Version Control**: Implement custom version control and deployment workflows
- **Bulk Operations**: Create, update, or delete resources in bulk
**Common Use Cases:**
- Deploying standard tag configurations across multiple containers
- Implementing custom approval workflows
- Syncing GTM configurations with external systems
- Creating automated testing for tag configurations
- Building custom GTM management interfaces
## API Capabilities
The GTM API allows you to manage:
- **Accounts**: Access and list GTM accounts
- **Containers**: Create, read, update containers
- **Workspaces**: Manage draft configurations
- **Tags**: Create and configure tags programmatically
- **Triggers**: Set up firing conditions
- **Variables**: Define data sources
- **Folders**: Organize container elements
- **Built-in Variables**: Enable/disable built-in variables
- **Versions**: Create, publish, and manage versions
- **Environments**: Configure staging environments
- **User Permissions**: Manage account and container access
## Authentication
The GTM API uses **OAuth 2.0** for authentication and authorization.
### OAuth 2.0 Scopes
Choose the appropriate scope based on your needs:
```
https://www.googleapis.com/auth/tagmanager.readonly
Read-only access to all GTM data
https://www.googleapis.com/auth/tagmanager.edit.containers
Edit access to container configurations
https://www.googleapis.com/auth/tagmanager.delete.containers
Permission to delete containers
https://www.googleapis.com/auth/tagmanager.edit.containerversions
Create and modify container versions
https://www.googleapis.com/auth/tagmanager.publish
Publish container versions
https://www.googleapis.com/auth/tagmanager.manage.users
Manage user permissions
https://www.googleapis.com/auth/tagmanager.manage.accounts
Full account access
```
### Setup Steps
1. **Create a Project** in Google Cloud Console
2. **Enable the GTM API** for your project
3. **Create OAuth 2.0 Credentials**:
- For web apps: OAuth 2.0 Client ID
- For server apps: Service Account
4. **Download credentials** JSON file
5. **Implement OAuth flow** in your application
### Python Example
```python
from google.oauth2.credentials import Credentials
from googleapiclient.discovery import build
# Define scopes
scopes = ['https://www.googleapis.com/auth/tagmanager.edit.containers']
# Create service
service = build('tagmanager', 'v2', credentials=credentials)
```
### JavaScript Example
```javascript
const CLIENT_ID = 'YOUR_CLIENT_ID';
const SCOPES = [
'https://www.googleapis.com/auth/tagmanager.edit.containers'
];
gapi.client.load('tagmanager', 'v2', () => {
// API loaded
});
```
## API Resources and Hierarchy
GTM API follows a hierarchical structure:
```
Account (accounts/123456)
└─ Container (accounts/123456/containers/7890)
└─ Workspace (accounts/123456/containers/7890/workspaces/1)
├─ Tags
├─ Triggers
├─ Variables
└─ Folders
└─ Versions
└─ Environments
```
## Common Operations
### List Containers
```python
# Python
account_path = 'accounts/123456'
containers = service.accounts().containers().list(
parent=account_path
).execute()
for container in containers.get('container', []):
print(f"Container: {container['name']} ({container['containerId']})")
```
```javascript
// JavaScript
const request = gapi.client.tagmanager.accounts.containers.list({
parent: 'accounts/123456'
});
request.execute((response) => {
response.container.forEach((container) => {
console.log(`Container: ${container.name} (${container.containerId})`);
});
});
```
### Create a Workspace
```python
# Python
container_path = 'accounts/123456/containers/7890'
workspace = service.accounts().containers().workspaces().create(
parent=container_path,
body={'name': 'API Workspace', 'description': 'Created via API'}
).execute()
```
### Create a Tag
```python
# Python
workspace_path = 'accounts/123456/containers/7890/workspaces/1'
ga4_tag = {
'name': 'GA4 Config Tag',
'type': 'gaawe', # GA4 Configuration tag type
'parameter': [
{'key': 'measurementId', 'type': 'template', 'value': 'G-XXXXXXXXXX'}
]
}
tag = service.accounts().containers().workspaces().tags().create(
parent=workspace_path,
body=ga4_tag
).execute()
```
### Create a Trigger
```python
# Python
pageview_trigger = {
'name': 'All Pages',
'type': 'PAGEVIEW'
}
trigger = service.accounts().containers().workspaces().triggers().create(
parent=workspace_path,
body=pageview_trigger
).execute()
```
### Link Tag to Trigger
```python
# Python
tag_path = 'accounts/123456/containers/7890/workspaces/1/tags/5'
# Get existing tag
tag = service.accounts().containers().workspaces().tags().get(
path=tag_path
).execute()
# Add trigger ID
tag['firingTriggerId'] = [trigger['triggerId']]
# Update tag
updated_tag = service.accounts().containers().workspaces().tags().update(
path=tag_path,
body=tag
).execute()
```
### Create and Publish Version
```python
# Python
workspace_path = 'accounts/123456/containers/7890/workspaces/1'
# Create version
version = service.accounts().containers().workspaces().create_version(
path=workspace_path,
body={'name': 'Version 1', 'notes': 'Initial setup'}
).execute()
# Publish version
published = service.accounts().containers().versions().publish(
path=version['containerVersion']['path']
).execute()
```
## API Patterns
### Pagination
Some list operations return paginated results:
```python
# Python
def list_all_tags(service, workspace_path):
tags = []
page_token = None
while True:
response = service.accounts().containers().workspaces().tags().list(
parent=workspace_path,
pageToken=page_token
).execute()
tags.extend(response.get('tag', []))
page_token = response.get('nextPageToken')
if not page_token:
break
return tags
```
### Error Handling
```python
# Python
from googleapiclient.errors import HttpError
try:
tag = service.accounts().containers().workspaces().tags().create(
parent=workspace_path,
body=tag_data
).execute()
except HttpError as error:
if error.resp.status == 409:
print("Tag already exists")
elif error.resp.status == 403:
print("Permission denied")
else:
print(f"An error occurred: {error}")
```
### Rate Limiting
The API has the following quotas (default):
- **Queries per day**: 1,000 (can be increased)
- **Queries per 100 seconds**: 100
Implement retry logic with exponential backoff:
```python
# Python
import time
from googleapiclient.errors import HttpError
def api_call_with_retry(func, max_retries=5):
for attempt in range(max_retries):
try:
return func()
except HttpError as error:
if error.resp.status == 429: # Rate limit exceeded
wait_time = 2 ** attempt # Exponential backoff
time.sleep(wait_time)
else:
raise
raise Exception("Max retries exceeded")
```
## Resource Paths
All API operations use resource paths:
```
Account: accounts/{account_id}
Container: accounts/{account_id}/containers/{container_id}
Workspace: accounts/{account_id}/containers/{container_id}/workspaces/{workspace_id}
Tag: accounts/{account_id}/containers/{container_id}/workspaces/{workspace_id}/tags/{tag_id}
```
Use paths from API responses rather than constructing them manually when possible.
## Best Practices
### 1. Use Workspaces
Always work within a workspace:
- Create a new workspace for API changes
- Make changes in the workspace
- Create and publish a version when ready
- Don't modify the default workspace
### 2. Test Before Production
```python
# Create test workspace
test_workspace = service.accounts().containers().workspaces().create(
parent=container_path,
body={'name': 'API Test', 'description': 'Testing API changes'}
).execute()
# Make changes
# Test thoroughly
# Create version if satisfied
# Delete workspace if not needed
```
### 3. Version Everything
Always create versions with meaningful notes:
```python
version = service.accounts().containers().workspaces().create_version(
path=workspace_path,
body={
'name': 'Release 2.3.0',
'notes': 'Added GA4 ecommerce tracking\n- Purchase event\n- Product views\n- Add to cart'
}
).execute()
```
### 4. Handle Permissions
Check user permissions before operations:
```python
try:
containers = service.accounts().containers().list(
parent='accounts/123456'
).execute()
except HttpError as error:
if error.resp.status == 403:
print("User lacks permission to access this account")
```
### 5. Use Batch Requests
For multiple operations, use batch requests:
```python
from googleapiclient.http import BatchHttpRequest
def callback(request_id, response, exception):
if exception:
print(f"Error: {exception}")
else:
print(f"Created: {response['name']}")
batch = service.new_batch_http_request(callback=callback)
for tag_data in tags_to_create:
batch.add(service.accounts().containers().workspaces().tags().create(
parent=workspace_path,
body=tag_data
))
batch.execute()
```
## Example: Complete Workflow
```python
# 1. List accounts
accounts = service.accounts().list().execute()
account_path = accounts['account'][0]['path']
# 2. Find container
containers = service.accounts().containers().list(parent=account_path).execute()
container = next(c for c in containers['container'] if c['name'] == 'My Site')
container_path = container['path']
# 3. Create workspace
workspace = service.accounts().containers().workspaces().create(
parent=container_path,
body={'name': 'API Changes', 'description': 'Automated setup'}
).execute()
workspace_path = workspace['path']
# 4. Create trigger
trigger = service.accounts().containers().workspaces().triggers().create(
parent=workspace_path,
body={'name': 'All Pages', 'type': 'PAGEVIEW'}
).execute()
# 5. Create tag
tag = service.accounts().containers().workspaces().tags().create(
parent=workspace_path,
body={
'name': 'GA4 Config',
'type': 'gaawe',
'parameter': [{'key': 'measurementId', 'type': 'template', 'value': 'G-XXXXXX'}],
'firingTriggerId': [trigger['triggerId']]
}
).execute()
# 6. Create and publish version
version = service.accounts().containers().workspaces().create_version(
path=workspace_path,
body={'name': 'API Setup', 'notes': 'Automated GA4 configuration'}
).execute()
published = service.accounts().containers().versions().publish(
path=version['containerVersion']['path']
).execute()
print(f"Published version: {published['containerVersion']['containerVersionId']}")
```
## Limitations
- **No direct data layer access**: API manages configuration, not runtime data
- **No real-time testing**: Use Preview mode in GTM UI for testing
- **Version publishing is final**: Cannot unpublish, only publish new versions
- **Rate limits apply**: Be mindful of quota limits
- **Some features unavailable**: Certain GTM features may not be available via API
## Resources
- [GTM API Reference](https://developers.google.com/tag-platform/tag-manager/api/v2/reference)
- [GTM API Developer Guide](https://developers.google.com/tag-platform/tag-manager/api/v2/devguide)
- [OAuth 2.0 Documentation](https://developers.google.com/identity/protocols/oauth2)
- [Python Client Library](https://github.com/googleapis/google-api-python-client)
- [JavaScript Client Library](https://github.com/google/google-api-javascript-client)
- [Tag Dictionary Reference](https://developers.google.com/tag-platform/tag-manager/api/v2/tag-dictionary-reference)
- [Variable Dictionary Reference](https://developers.google.com/tag-platform/tag-manager/api/v2/variable-dictionary-reference)

View File

@@ -0,0 +1,150 @@
---
name: gtm-best-practices
description: Expert guidance for Google Tag Manager best practices including naming conventions, performance optimization, security, privacy compliance, container organization, and deployment strategies. Use when optimizing GTM performance, implementing security best practices, setting up naming conventions, auditing GTM containers, or ensuring privacy compliance.
---
# GTM Best Practices
## Overview
This skill provides best practices for Google Tag Manager including naming conventions, performance optimization, security, privacy, and deployment strategies.
## When to Use This Skill
Invoke this skill when:
- Optimizing GTM container performance
- Implementing security best practices
- Setting up naming conventions
- Auditing GTM containers
- Ensuring privacy compliance
- Planning deployment strategies
- Reviewing GTM implementations
## Naming Conventions
### Tags
Format: `[Platform] - [Type] - [Description]`
Examples:
- `GA4 - Event - Form Submit`
- `Google Ads - Conversion - Purchase`
- `FB - Pixel - Page View`
### Triggers
Format: `[Event Type] - [Description]`
Examples:
- `Click - CTA Button`
- `Page View - Homepage`
- `Form Submit - Contact Form`
### Variables
Format: `[Type] - [Description]`
Examples:
- `DL - User ID`
- `CJS - Format Price`
- `Cookie - Session ID`
## Performance Optimization
### Minimize Tag Load Time
- Use native tag templates instead of custom HTML
- Minimize custom JavaScript
- Implement async loading
- Configure appropriate timeouts
- Remove unused elements
### Container Optimization
- Regular container audits
- Remove duplicate tags
- Consolidate similar tags
- Minimize trigger complexity
- Use tag sequencing wisely
### Page Performance
- Defer non-critical tags
- Use async snippet
- Minimize container size
- Optimize custom HTML
- Monitor loading time
## Security Best Practices
### Tag Security
- Vet all custom HTML tags
- Review third-party templates
- Use template permissions
- Restrict custom JavaScript
- Validate input data
### Data Privacy
- Avoid PII in data layer
- Implement consent mode
- Block tags based on consent
- Hash sensitive identifiers
- Review data collection policies
### Access Control
- Use appropriate permission levels
- Review user access regularly
- Limit container admin access
- Audit permission changes
- Use workspaces for isolation
## Deployment Strategies
### Environment Setup
- Development environment for testing
- Staging environment for validation
- Production environment for live traffic
- Use container versions properly
### Version Management
- Create versions with detailed notes
- Test thoroughly before publishing
- Maintain version history
- Document changes clearly
- Enable quick rollback capability
### Publishing Workflow
1. Make changes in workspace
2. Test in Preview mode
3. Validate in development environment
4. Create version with notes
5. Publish to production
6. Monitor for issues
7. Document deployment
## Container Organization
### Folder Structure
- Group related tags by platform or purpose
- Use folders for triggers by type
- Organize variables by category
- Keep structure logical and consistent
### Documentation
- Add notes to complex configurations
- Document custom JavaScript logic
- Maintain change log
- Share knowledge with team
## Audit Checklist
- [ ] Naming conventions followed
- [ ] No unused tags, triggers, or variables
- [ ] Performance optimized
- [ ] Security reviewed
- [ ] Privacy compliance verified
- [ ] Proper version management
- [ ] Documentation complete
## References
- **references/best-practices.md** - Naming conventions, organization, deployment strategies
## Integration with Other Skills
## Integration with Other Skills
- **gtm-general** - General GTM guidance and concepts
- **gtm-setup** - Proper container setup and installation
- **gtm-tags** - Efficient tag configuration practices
- **gtm-triggers** - Trigger optimization and best practices
- **gtm-variables** - Variable naming and structure best practices
- **gtm-debugging** - Testing and validation workflows
- **gtm-datalayer** - Data layer naming and structure best practices
- **gtm-custom-templates** - Template development best practices
- **gtm-api** - API automation best practices

View File

@@ -0,0 +1,597 @@
# Google Tag Manager - Best Practices
## Foundational Technical Constraints
### JavaScript in Google Tag Manager (ES5 Requirement)
**Critical:** Google Tag Manager primarily uses **ECMAScript 5 (ES5)** for JavaScript code, not modern ES6+.
#### Where ES5 is Required
1. **Custom JavaScript Variables** - Must use ES5 syntax only
2. **Custom HTML Tags** - Standard `<script>` tags must use ES5
3. **Trigger conditions using JavaScript** - ES5 only
#### ES6 Features NOT Supported in Standard GTM
```javascript
// ❌ WILL FAIL - ES6 syntax
const myVar = 'value';
let count = 0;
const arrow = () => console.log('test');
const template = `Hello ${name}`;
// ✅ CORRECT - ES5 syntax
var myVar = 'value';
var count = 0;
var regularFunc = function() { console.log('test'); };
var concatenated = 'Hello ' + name;
```
#### Custom Templates Exception
**Custom Templates** (Sandboxed JavaScript) support some ES6 features:
- `const` and `let` declarations
- Template literals
- Limited modern JavaScript features
Running in a controlled sandboxed environment based on ECMAScript 5.1 with selective ES6 support.
#### Workarounds for Modern JavaScript
**Option 1: Transpilation (Recommended)**
Use BabelJS to transpile ES6+ to ES5 before pasting into GTM:
```javascript
// Write in ES6
const getData = () => {
const data = dataLayer.filter(item => item.event === 'purchase');
return data;
};
// Transpile to ES5 with Babel, then paste into GTM
var getData = function() {
var data = dataLayer.filter(function(item) {
return item.event === 'purchase';
});
return data;
};
```
**Option 2: text/gtmscript Tag**
Bypass GTM's syntax checking (use with caution):
```html
<script type="text/gtmscript">
// Modern JavaScript here - no syntax validation in GTM UI
const myModernCode = () => {
// ...
};
</script>
```
**Caveats:**
- No syntax highlighting in GTM interface
- No error checking until runtime
- Harder to debug
- Only use when absolutely necessary
### Regular Expressions in Google Tag Manager (RE2 Format)
**Critical:** GTM uses **RE2 (GoLang regex)**, NOT standard JavaScript/PCRE regex.
#### Key Differences from Standard Regex
**NOT Supported in RE2:**
- ❌ Backreferences: `\1`, `\2`, `\g{name}`
- ❌ Lookahead assertions: `(?=...)`, `(?!...)`
- ❌ Lookbehind assertions: `(?<=...)`, `(?<!...)`
- ❌ Conditional expressions: `(?(condition)yes|no)`
- ❌ Possessive quantifiers: `*+`, `++`
**Supported in RE2:**
- ✅ Character classes: `[abc]`, `[^abc]`, `[a-z]`
- ✅ Quantifiers: `*`, `+`, `?`, `{n,m}`
- ✅ Anchors: `^`, `$`, `\A`, `\z`
- ✅ Perl character classes: `\d`, `\w`, `\s` (and negations)
- ✅ Groups: `(...)`, `(?:...)` (non-capturing)
- ✅ Named groups: `(?P<name>...)`
- ✅ Alternation: `|`
- ✅ Case-insensitive flag: `(?i)`
#### Common RE2 Patterns for GTM
**Match URLs:**
```regex
# Exact match
^https://example\.com/page$
# Contains path
/checkout/
# Query parameter present
\?utm_source=
# Multiple domains
^https://(www\.)?example\.(com|net)
```
**Match Page Paths:**
```regex
# Product pages
^/products/[^/]+$
# Category with ID
^/category/\d+
# Blog posts
^/blog/[\w-]+$
```
**Case-Insensitive Matching:**
```regex
# Case-insensitive flag at start
(?i)^/checkout
# Matches: /checkout, /Checkout, /CHECKOUT, etc.
```
**Character Classes:**
```regex
# Digits only
^\d+$
# Alphanumeric
^[\w-]+$
# Specific characters
^[A-Z]{2,3}$
```
#### Where Regex is Used in GTM
1. **Trigger Conditions** - Page URL, Click URL, etc.
2. **Variable Formatting** - Regex Table variables
3. **Filter Conditions** - Various matching rules
#### Full RE2 Syntax Reference
Complete RE2 regex syntax is available in:
`.claude/skills/gtm-core/gtm-core/references/google-rew-regular-expressions-syntax.txt`
## Naming Conventions
### Tag Naming
Use descriptive, consistent naming patterns:
```
[Platform] - [Type] - [Purpose] - [Trigger Condition]
```
**Examples:**
- `GA4 - Event - Purchase Complete - Thank You Page`
- `Google Ads - Conversion - Form Submit - Contact Form`
- `Facebook - Pixel - Page View - All Pages`
- `Custom - LinkedIn Insight - Page View - Career Pages`
**Benefits:**
- Easy to find tags in large containers
- Clear purpose at a glance
- Sortable and filterable
- Easier collaboration
### Trigger Naming
```
[Type] - [Condition] - [Description]
```
**Examples:**
- `Pageview - URL Contains - Checkout`
- `Click - Element ID - CTA Button`
- `Custom Event - purchase_complete`
- `Form Submit - Contact Form`
### Variable Naming
```
[Type] - [Purpose]
```
**Examples:**
- `DLV - User ID`
- `JS - Page Category`
- `Constant - GA4 Measurement ID`
- `Regex Table - Page Type Mapping`
**Prefixes:**
- `DLV` - Data Layer Variable
- `JS` - Custom JavaScript
- `Constant` - Constant value
- `1P Cookie` - First Party Cookie
- `URL` - URL variable
### Folder Organization
Group related items:
```
├── Analytics
│ ├── GA4 Tags
│ ├── GA4 Triggers
│ └── GA4 Variables
├── Advertising
│ ├── Google Ads
│ ├── Facebook
│ └── LinkedIn
├── Utilities
│ ├── Error Tracking
│ └── Performance Monitoring
└── Testing
└── Development Tags
```
## Container Organization
### Workspace Management
**Development Workflow:**
1. Create workspace for each feature/change
2. Name workspace descriptively: `Add GA4 Ecommerce Tracking`
3. Work in isolation
4. Test thoroughly in Preview mode
5. Submit for review
6. Merge and publish
**Workspace Best Practices:**
- One feature per workspace
- Regular cleanup of abandoned workspaces
- Clear workspace descriptions
- Resolve conflicts promptly
- Use descriptive workspace names
### Version Control
**Version Naming:**
```
v[Major].[Minor] - [Description]
```
**Examples:**
- `v1.0 - Initial GTM Setup`
- `v1.1 - Add GA4 Ecommerce`
- `v2.0 - Major Restructure`
- `v2.1 - Fix Checkout Tracking`
**Version Notes:**
Include detailed notes:
```
Changes:
- Added GA4 purchase event tracking
- Updated data layer structure for checkout
- Fixed duplicate page view issue
Testing:
- Verified in dev environment
- Tested all checkout flows
- Confirmed data in GA4 DebugView
Tags Added:
- GA4 - Event - Purchase Complete
Tags Modified:
- GA4 - Event - Add to Cart (updated parameters)
```
### Multi-User Collaboration
**Permissions:**
- **No Access** - External users
- **Read** - Stakeholders, analysts (view only)
- **Edit** - Developers, marketers
- **Approve** - Senior developers, managers
- **Publish** - Select trusted users only
**Collaboration Best Practices:**
- Communicate workspace usage
- Regular team syncs
- Document changes thoroughly
- Use workspace approval workflow
- Maintain change log
## Performance Optimization
### Tag Load Order
**Priority System:**
Use tag firing priority (higher numbers fire first):
```
100 - Critical tags (error tracking, consent)
50 - Analytics tags (GA4, Adobe)
25 - Marketing tags (ads pixels)
10 - Third-party tags
0 - Default
```
**Tag Sequencing:**
Set up tag firing order:
1. Tag that must fire first
2. Configure "Tag Sequencing" in advanced settings
3. Setup tag fires after cleanup tag completes
### Minimize Custom HTML
**Prefer:**
1. Built-in tags (GA4, Google Ads)
2. Community Gallery templates
3. Custom templates
4. Custom HTML (last resort)
**Why:**
- Built-in tags are optimized
- Less maintenance
- Better performance
- Reduced security risk
### Async vs Sync Loading
**Asynchronous Loading (Default - Recommended):**
```javascript
// GTM loads async by default
<script async src="https://www.googletagmanager.com/gtm.js?id=GTM-XXXXXX"></script>
```
**Benefits:**
- Non-blocking
- Better page performance
- Parallel loading
**Synchronous (Use Sparingly):**
Only when tag MUST execute before page renders.
### Tag Timeout
**Configure Timeout:**
Admin → Container Settings → Tag Settings
- Default: 2000ms (2 seconds)
- Recommended: 3000-5000ms for complex tags
**Prevent:**
- Tags blocking page indefinitely
- Poor user experience
- False abandonment metrics
## Security Best Practices
### Custom HTML Security
**Review All Custom HTML:**
```javascript
// ❌ DANGEROUS - Eval and dynamic script loading
eval(userInput);
document.write('<script src="' + untrustedURL + '"></script>');
// ✅ SAFE - Controlled execution
var allowedScripts = {
'analytics': 'https://analytics.trusted.com/script.js'
};
```
**Security Checklist:**
- [ ] No `eval()` with user input
- [ ] No `document.write()` with external sources
- [ ] Validate all external script sources
- [ ] Review third-party tag code
- [ ] Use CSP (Content Security Policy) headers
### Data Layer Security
**Never Push PII to Data Layer:**
```javascript
// ❌ NEVER DO THIS
dataLayer.push({
'email': 'user@example.com',
'phone': '+1234567890',
'ssn': '123-45-6789'
});
// ✅ HASH OR PSEUDONYMIZE
dataLayer.push({
'userIdHash': sha256('user@example.com'),
'hasPhone': true
});
```
### Template Permissions
**Custom Template Security:**
Review template permissions:
- Access to APIs
- Access to global variables
- Access to local storage
- Network requests
Grant minimum necessary permissions.
## Quality Assurance
### Testing Checklist
**Before Publishing:**
- [ ] Preview mode testing completed
- [ ] All triggers fire correctly
- [ ] Data layer variables populate
- [ ] Tags send expected data
- [ ] No console errors
- [ ] Cross-browser testing
- [ ] Mobile testing
- [ ] Edge case scenarios tested
### Debug Workflow
1. **Enable Preview Mode**
2. **Navigate to test page**
3. **Verify in Debug Panel:**
- Tags Fired
- Tags Not Fired
- Data Layer
- Variables
4. **Check receiving platform** (GA4, Google Ads, etc.)
5. **Test edge cases**
### Automated Testing
**Tag Manager API + Testing Framework:**
```python
# Pseudo-code
def test_purchase_tag():
trigger_purchase_event()
assert ga4_tag_fired()
assert correct_parameters_sent()
```
## Deployment Best Practices
### Publishing Workflow
1. **Development** → Test in development workspace
2. **Staging** → Test in staging environment
3. **Preview** → Final check in preview mode
4. **Publish** → Publish to live container
5. **Monitor** → Watch for errors/issues
### Emergency Rollback
**Quick Rollback:**
Versions → Previous Version → Actions → Publish
**Keep:**
- Last 3 working versions readily accessible
- Emergency contact list
- Rollback documentation
### Production Deployment Checklist
- [ ] Workspace approved by team lead
- [ ] All tests passing
- [ ] Change documented in version notes
- [ ] Stakeholders notified
- [ ] Monitoring in place
- [ ] Rollback plan ready
## Maintenance
### Regular Audits
**Quarterly Review:**
- Remove unused tags/triggers/variables
- Update deprecated features
- Review tag performance
- Check for duplicate tracking
- Verify naming consistency
### Performance Monitoring
**Monitor:**
- Page load time impact
- Tag load time
- Failed tags
- Timeout events
- Error rates
**Tools:**
- Google Tag Assistant
- Chrome DevTools
- GTM Debug Panel
- GA4 DebugView
### Version Cleanup
**Retention Policy:**
- Keep last 10-15 versions
- Archive old versions
- Document reason for major changes
- Maintain change history
## Documentation
### External Documentation
**Maintain:**
1. **GTM Implementation Guide**
- Container architecture
- Tag inventory
- Trigger mapping
- Variable dictionary
- Data layer specification
2. **Change Log**
- Date of change
- Description
- Who made the change
- Reason for change
3. **Troubleshooting Guide**
- Common issues
- Solutions
- Contact information
### Version Notes Template
```markdown
## Version X.X - [Description]
### Changes Made
- List of changes
### Tags Added
- Tag names and purposes
### Tags Modified
- What changed and why
### Tags Removed
- What was removed and why
### Testing Completed
- Test scenarios
- Results
### Known Issues
- Any limitations or issues
```
## Resources
- [GTM Developer Documentation](https://developers.google.com/tag-platform/tag-manager)
- [GTM Help Center](https://support.google.com/tagmanager)
- [GTM Community](https://support.google.com/tagmanager/community)
- [RE2 Regex Syntax Reference](.claude/skills/gtm-core/gtm-core/references/google-rew-regular-expressions-syntax.txt)

View File

@@ -0,0 +1,536 @@
---
name: gtm-custom-templates
description: Expert guidance for building Google Tag Manager custom templates using sandboxed JavaScript. Use when creating custom tag templates, custom variable templates, server-side client templates, converting regular JavaScript to sandboxed JS, debugging template code, writing template tests, publishing to the Community Template Gallery, working with .tpl template files, or using sandboxed JavaScript APIs like require(), sendPixel, injectScript, and other GTM template APIs.
---
# GTM Custom Templates Builder
## Overview
This skill provides comprehensive expertise for building Google Tag Manager custom templates using sandboxed JavaScript. Master template structure, sandboxed JavaScript APIs, permissions, testing, and publishing to the Community Template Gallery.
## When to Use This Skill
Invoke this skill when:
- Building a custom tag template for a third-party service
- Creating a custom variable template for complex data manipulation
- Developing server-side client templates
- Converting regular JavaScript to sandboxed JavaScript
- Debugging sandboxed JavaScript API errors
- Understanding template permissions and security
- Writing tests for custom templates
- Publishing templates to the Community Template Gallery
- Troubleshooting "undefined is not a function" errors in templates
- Implementing HTTP requests, pixel firing, or script injection in templates
## Sandboxed JavaScript Fundamentals
### What is Sandboxed JavaScript?
Sandboxed JavaScript is a restricted subset of JavaScript used in GTM custom templates. It provides security by limiting what code can execute while offering safe APIs for common operations.
**Key Differences from Regular JavaScript:**
- No direct DOM access
- No window/document object
- No eval() or Function()
- No arbitrary HTTP requests
- Must use require() to import APIs
- All operations require explicit permissions
### Basic Template Structure
```javascript
// Import required APIs
const sendPixel = require('sendPixel');
const logToConsole = require('logToConsole');
const encodeUriComponent = require('encodeUriComponent');
// Access template configuration
const endpoint = data.endpoint;
const eventName = data.eventName;
// Execute template logic
const url = endpoint + '?event=' + encodeUriComponent(eventName);
sendPixel(url, data.gtmOnSuccess, data.gtmOnFailure);
```
## Building Tag Templates
### Tag Template Workflow
1. **Define Template Info**
- Template type (TAG)
- Display name and description
- Categories and branding
- Container contexts (WEB, SERVER, etc.)
2. **Configure Template Parameters**
- Add fields for user configuration
- Set field types (TEXT, SELECT, CHECKBOX, etc.)
- Define validation rules
- Set default values
3. **Write Sandboxed JavaScript Code**
- Require necessary APIs
- Access data from template fields
- Implement tag logic
- Call gtmOnSuccess/gtmOnFailure
4. **Set Permissions**
- Configure required permissions
- Specify allowed URLs, cookies, etc.
- Minimize permission scope
5. **Write Tests**
- Test successful execution
- Test error handling
- Test edge cases
### Common Tag Template Patterns
**Simple Pixel Tag:**
```javascript
const sendPixel = require('sendPixel');
const encodeUriComponent = require('encodeUriComponent');
const pixelUrl = data.pixelUrl +
'?id=' + encodeUriComponent(data.pixelId) +
'&event=' + encodeUriComponent(data.eventName);
sendPixel(pixelUrl, data.gtmOnSuccess, data.gtmOnFailure);
```
**HTTP Request Tag:**
```javascript
const sendHttpRequest = require('sendHttpRequest');
const JSON = require('JSON');
const postBody = JSON.stringify({
event: data.eventName,
userId: data.userId
});
const options = {
headers: {'Content-Type': 'application/json'},
method: 'POST'
};
sendHttpRequest(data.endpoint, options, postBody)
.then(data.gtmOnSuccess)
.catch(data.gtmOnFailure);
```
**Script Injection Tag:**
```javascript
const injectScript = require('injectScript');
const queryPermission = require('queryPermission');
const url = 'https://example.com/script.js';
if (queryPermission('inject_script', url)) {
injectScript(url, data.gtmOnSuccess, data.gtmOnFailure);
} else {
data.gtmOnFailure();
}
```
## Building Variable Templates
### Variable Template Basics
Variable templates return a value that can be used in other GTM configurations.
**Cookie Variable:**
```javascript
const getCookieValues = require('getCookieValues');
const cookieName = data.cookieName;
const cookies = getCookieValues(cookieName);
if (cookies && cookies.length > 0) {
return cookies[0];
}
return data.defaultValue || '';
```
**LocalStorage Variable:**
```javascript
const localStorage = require('localStorage');
const key = data.storageKey;
const value = localStorage.getItem(key);
return value || data.defaultValue;
```
**Custom JavaScript Variable:**
```javascript
const makeTableMap = require('makeTableMap');
const makeNumber = require('makeNumber');
// Convert table to lookup map
const lookupTable = makeTableMap(data.table, 'key', 'value');
// Perform lookup
const inputValue = data.inputVariable;
return lookupTable[inputValue] || data.defaultValue;
```
## Sandboxed JavaScript API Reference
### Commonly Used APIs
**Data Type Conversion:**
```javascript
const makeInteger = require('makeInteger');
const makeNumber = require('makeNumber');
const makeString = require('makeString');
const num = makeNumber('123.45'); // 123.45
const int = makeInteger('123.45'); // 123
const str = makeString(123); // '123'
```
**Network APIs:**
```javascript
const sendPixel = require('sendPixel');
const sendHttpRequest = require('sendHttpRequest');
const injectScript = require('injectScript');
// Pixel
sendPixel(url, onSuccess, onFailure);
// HTTP Request
sendHttpRequest(url, options, body)
.then(onSuccess)
.catch(onFailure);
// Script injection
injectScript(url, onSuccess, onFailure);
```
**Storage APIs:**
```javascript
const getCookieValues = require('getCookieValues');
const setCookie = require('setCookie');
const localStorage = require('localStorage');
// Cookies
const cookies = getCookieValues('cookieName');
setCookie('name', 'value', {
domain: 'example.com',
path: '/',
'max-age': 3600
});
// LocalStorage
const value = localStorage.getItem('key');
localStorage.setItem('key', 'value');
```
**Utility APIs:**
```javascript
const encodeUri = require('encodeUri');
const encodeUriComponent = require('encodeUriComponent');
const decodeUri = require('decodeUri');
const decodeUriComponent = require('decodeUriComponent');
const JSON = require('JSON');
const Math = require('Math');
const Object = require('Object');
// URL encoding
const encoded = encodeUriComponent('hello world');
// JSON
const obj = JSON.parse('{"key":"value"}');
const str = JSON.stringify({key: 'value'});
// Math
const random = Math.random();
const rounded = Math.round(3.7);
```
**DOM APIs (Limited):**
```javascript
const callInWindow = require('callInWindow');
const copyFromWindow = require('copyFromWindow');
// Call window function
callInWindow('functionName', arg1, arg2);
// Copy from window
const gaData = copyFromWindow('ga');
```
## Permissions System
### Understanding Permissions
Every API requires explicit permission configuration. Permissions define what URLs, cookies, or data the template can access.
**sendPixel Permission:**
```json
{
"instance": {
"key": {"publicId": "send_pixel", "versionId": "1"},
"param": [{
"key": "allowedUrls",
"value": {"type": 1, "string": "specific"},
"list": [
{"type": 1, "string": "https://example.com/*"}
]
}]
}
}
```
**get_cookies Permission:**
```json
{
"instance": {
"key": {"publicId": "get_cookies", "versionId": "1"},
"param": [{
"key": "cookieAccess",
"value": {"type": 1, "string": "specific"},
"list": [
{"type": 1, "string": "session_id"},
{"type": 1, "string": "user_*"}
]
}]
}
}
```
**Best Practice:** Use the most restrictive permissions possible. Avoid "any" when you can specify exact URLs or cookie names.
## Template Testing
### Writing Tests
```javascript
// Test successful execution
scenarios:
- name: Tag fires successfully
code: |-
const mockData = {
endpoint: 'https://example.com/api',
eventName: 'test_event'
};
runCode(mockData);
assertApi('gtmOnSuccess').wasCalled();
assertApi('sendHttpRequest').wasCalledWith(
'https://example.com/api',
assertThat.objectContaining({method: 'POST'})
);
```
### Test Mocking
```javascript
// Mock API returns
mock('getCookieValues', (name) => {
if (name === 'session_id') {
return ['abc123'];
}
return [];
});
// Test with mock
const mockData = {cookieName: 'session_id'};
let result = runCode(mockData);
assertThat(result).isEqualTo('abc123');
```
## Common Patterns and Solutions
### Converting Regular JS to Sandboxed JS
**Regular JavaScript (won't work):**
```javascript
// Direct DOM access
document.getElementById('element');
// Direct window access
window.dataLayer.push({});
// XMLHttpRequest
const xhr = new XMLHttpRequest();
```
**Sandboxed JavaScript (will work):**
```javascript
// Use callInWindow
const callInWindow = require('callInWindow');
callInWindow('dataLayer.push', {event: 'custom'});
// Use sendHttpRequest
const sendHttpRequest = require('sendHttpRequest');
sendHttpRequest(url, {method: 'GET'})
.then(data.gtmOnSuccess)
.catch(data.gtmOnFailure);
```
### Error Handling
```javascript
const sendHttpRequest = require('sendHttpRequest');
const logToConsole = require('logToConsole');
sendHttpRequest(data.endpoint)
.then(response => {
logToConsole('Success:', response);
data.gtmOnSuccess();
})
.catch(error => {
logToConsole('Error:', error);
data.gtmOnFailure();
});
```
### Data Validation
```javascript
const makeNumber = require('makeNumber');
const getType = require('getType');
// Validate input
if (getType(data.value) === 'undefined') {
data.gtmOnFailure();
return;
}
// Convert and validate
const numValue = makeNumber(data.value);
if (numValue === undefined) {
logToConsole('Invalid number');
data.gtmOnFailure();
return;
}
// Continue with valid data
data.gtmOnSuccess();
```
## Template Field Configuration
### Common Field Types
```javascript
// Text input
{
"type": "TEXT",
"name": "apiKey",
"displayName": "API Key",
"simpleValueType": true,
"valueValidators": [
{"type": "NON_EMPTY"},
{"type": "REGEX", "args": ["^[a-zA-Z0-9]{32}$"]}
]
}
// Select dropdown
{
"type": "SELECT",
"name": "eventType",
"displayName": "Event Type",
"selectItems": [
{"value": "pageview", "displayValue": "Pageview"},
{"value": "event", "displayValue": "Event"}
],
"simpleValueType": true
}
// Checkbox
{
"type": "CHECKBOX",
"name": "enableDebug",
"checkboxText": "Enable Debug Logging",
"simpleValueType": true,
"defaultValue": false
}
// Group
{
"type": "GROUP",
"name": "advancedSettings",
"displayName": "Advanced Settings",
"groupStyle": "ZIPPY_CLOSED",
"subParams": [
// Nested fields here
]
}
```
## Publishing to Community Template Gallery
1. **Complete Template Info**
- Descriptive name and description
- Appropriate categories
- Brand information
- Thumbnail image (optional)
2. **Add Comprehensive Tests**
- Test all major code paths
- Test error handling
- Test edge cases
3. **Document Template**
- Clear field descriptions
- Help text for complex fields
- Notes section with usage instructions
4. **Submit for Review**
- Export template from GTM
- Submit to Community Template Gallery
- Address reviewer feedback
## Template Boilerplates
This skill includes ready-to-use template boilerplates:
- **assets/tag-template-boilerplate.tpl** - Complete tag template structure
- **assets/variable-template-boilerplate.tpl** - Complete variable template structure
Copy these files and customize for your specific use case.
## References
This skill includes comprehensive reference documentation:
- **references/sandboxed-javascript-api.md** - Complete API reference
- **references/custom-templates-guide.md** - Simo Ahava's comprehensive guide
- **references/template-testing.md** - Testing documentation and patterns
- **references/template-examples.md** - Real-world template examples
Search references for specific APIs:
```bash
grep -r "sendHttpRequest" references/
grep -r "permissions" references/
grep -r "testing" references/
```
## Integration with Other Skills
- **gtm-general** - Understanding GTM concepts and architecture
- **gtm-setup** - Testing templates in GTM containers
- **gtm-tags** - Understanding tag structure for tag templates
- **gtm-variables** - Understanding variable structure for variable templates
- **gtm-datalayer** - Templates that interact with data layer
- **gtm-debugging** - Testing and debugging custom templates
- **gtm-api** - Programmatic template management
## Quick Reference
**Import API:** `const apiName = require('apiName');`
**Success/Failure:** Always call `data.gtmOnSuccess()` or `data.gtmOnFailure()`
**Permissions:** Every API requires explicit permission configuration
**Testing:** Use `runCode(mockData)` and assertions
**Debugging:** Use `logToConsole()` with debug environment permission

View File

@@ -0,0 +1,24 @@
# Example Asset File
This placeholder represents where asset files would be stored.
Replace with actual asset files (templates, images, fonts, etc.) or delete if not needed.
Asset files are NOT intended to be loaded into context, but rather used within
the output Claude produces.
Example asset files from other skills:
- Brand guidelines: logo.png, slides_template.pptx
- Frontend builder: hello-world/ directory with HTML/React boilerplate
- Typography: custom-font.ttf, font-family.woff2
- Data: sample_data.csv, test_dataset.json
## Common Asset Types
- Templates: .pptx, .docx, boilerplate directories
- Images: .png, .jpg, .svg, .gif
- Fonts: .ttf, .otf, .woff, .woff2
- Boilerplate code: Project directories, starter files
- Icons: .ico, .svg
- Data files: .csv, .json, .xml, .yaml
Note: This is a text placeholder. Actual assets can be any file type.

View File

@@ -0,0 +1,168 @@
___INFO___
{
"type": "TAG",
"id": "cvt_temp_public_id",
"version": 1,
"securityGroups": [],
"displayName": "My Custom Tag",
"categories": ["ANALYTICS", "MARKETING"],
"brand": {
"id": "brand_id",
"displayName": "My Brand",
"thumbnail": ""
},
"description": "A custom tag template for...",
"containerContexts": [
"WEB"
]
}
___TEMPLATE_PARAMETERS___
[
{
"type": "TEXT",
"name": "endpoint",
"displayName": "API Endpoint",
"simpleValueType": true,
"help": "Enter the API endpoint URL",
"valueValidators": [
{
"type": "NON_EMPTY"
},
{
"type": "REGEX",
"args": ["^https?://.*"]
}
]
},
{
"type": "TEXT",
"name": "eventName",
"displayName": "Event Name",
"simpleValueType": true,
"defaultValue": "custom_event"
},
{
"type": "CHECKBOX",
"name": "debug",
"checkboxText": "Enable Debug Mode",
"simpleValueType": true,
"defaultValue": false
}
]
___SANDBOXED_JS_FOR_WEB_TEMPLATE___
// Require necessary APIs
const sendPixel = require('sendPixel');
const logToConsole = require('logToConsole');
const encodeUriComponent = require('encodeUriComponent');
// Access template data
const endpoint = data.endpoint;
const eventName = data.eventName;
const debug = data.debug;
// Debug logging
if (debug) {
logToConsole('Custom Tag Firing', {
endpoint: endpoint,
eventName: eventName
});
}
// Build pixel URL
const pixelUrl = endpoint + '?event=' + encodeUriComponent(eventName);
// Fire pixel
sendPixel(pixelUrl, data.gtmOnSuccess, data.gtmOnFailure);
___WEB_PERMISSIONS___
[
{
"instance": {
"key": {
"publicId": "logging",
"versionId": "1"
},
"param": [
{
"key": "environments",
"value": {
"type": 1,
"string": "debug"
}
}
]
},
"clientAnnotations": {
"isEditedByUser": true
},
"isRequired": true
},
{
"instance": {
"key": {
"publicId": "send_pixel",
"versionId": "1"
},
"param": [
{
"key": "allowedUrls",
"value": {
"type": 1,
"string": "any"
}
}
]
},
"clientAnnotations": {
"isEditedByUser": true
},
"isRequired": true
}
]
___TESTS___
scenarios:
- name: Tag fires successfully
code: |-
const mockData = {
endpoint: 'https://example.com/pixel',
eventName: 'test_event',
debug: false
};
// Call runCode to run the template's code.
runCode(mockData);
// Verify that the tag finished successfully.
assertApi('gtmOnSuccess').wasCalled();
- name: Debug mode logs to console
code: |-
const mockData = {
endpoint: 'https://example.com/pixel',
eventName: 'test_event',
debug: true
};
runCode(mockData);
// Verify logging occurred
assertApi('logToConsole').wasCalledWith('Custom Tag Firing', {
endpoint: 'https://example.com/pixel',
eventName: 'test_event'
});
___NOTES___
Created using Custom Template Boilerplate

View File

@@ -0,0 +1,133 @@
___INFO___
{
"type": "MACRO",
"id": "cvt_temp_public_id",
"version": 1,
"securityGroups": [],
"displayName": "My Custom Variable",
"categories": ["UTILITY"],
"brand": {
"id": "brand_id",
"displayName": "My Brand"
},
"description": "A custom variable template for...",
"containerContexts": [
"WEB"
]
}
___TEMPLATE_PARAMETERS___
[
{
"type": "TEXT",
"name": "cookieName",
"displayName": "Cookie Name",
"simpleValueType": true,
"help": "Name of the cookie to read",
"valueValidators": [
{
"type": "NON_EMPTY"
}
]
},
{
"type": "TEXT",
"name": "defaultValue",
"displayName": "Default Value",
"simpleValueType": true,
"help": "Value to return if cookie is not found"
}
]
___SANDBOXED_JS_FOR_WEB_TEMPLATE___
// Require necessary APIs
const getCookieValues = require('getCookieValues');
const logToConsole = require('logToConsole');
// Access template data
const cookieName = data.cookieName;
const defaultValue = data.defaultValue;
// Get cookie values
const cookies = getCookieValues(cookieName);
// Return first cookie value or default
if (cookies && cookies.length > 0) {
return cookies[0];
}
return defaultValue;
___WEB_PERMISSIONS___
[
{
"instance": {
"key": {
"publicId": "get_cookies",
"versionId": "1"
},
"param": [
{
"key": "cookieAccess",
"value": {
"type": 1,
"string": "any"
}
}
]
},
"clientAnnotations": {
"isEditedByUser": true
},
"isRequired": true
}
]
___TESTS___
scenarios:
- name: Returns cookie value when exists
code: |-
mock('getCookieValues', (name) => {
if (name === 'testCookie') {
return ['cookieValue'];
}
return [];
});
const mockData = {
cookieName: 'testCookie',
defaultValue: 'default'
};
let result = runCode(mockData);
assertThat(result).isEqualTo('cookieValue');
- name: Returns default value when cookie does not exist
code: |-
mock('getCookieValues', (name) => {
return [];
});
const mockData = {
cookieName: 'nonExistentCookie',
defaultValue: 'defaultValue'
};
let result = runCode(mockData);
assertThat(result).isEqualTo('defaultValue');
___NOTES___
Created using Custom Variable Template Boilerplate

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,357 @@
# Sandboxed JavaScript API Reference
This is the complete Sandboxed JavaScript API reference for Google Tag Manager custom templates. These APIs enable you to build powerful custom templates while maintaining security and performance standards.
Source: https://developers.google.com/tag-platform/tag-manager/templates/api
## API Categories
### Core APIs
These APIs work with sandboxed JavaScript to build custom templates in Google Tag Manager.
#### Consent Management
- **addConsentListener(consentType, listener)** → void
- Registers a listener function to execute when the state of the specified consent type changes.
- **isConsentGranted(consentType)** → boolean
- Returns true if the specified consent type is granted.
- **setDefaultConsentState(consentSettings)** → void
- Pushes a default consent update to the data layer.
- **updateConsentState(consentSettings)** → void
- Pushes a consent update to the data layer.
#### Event Handling
- **addEventCallback(callback)** → void
- Allows you to register a callback function that will be invoked at the end of an event.
- **callLater(function)** → void
- Schedules a call to a function to occur asynchronously.
#### Window and Global Object Access
- **aliasInWindow(toPath, fromPath)** → boolean
- Lets you create an alias (e.g. window.foo = window.bar).
- **callInWindow(pathToFunction, args)** → *
- Allows you to call functions from a path off the window object, in a policy-controlled way.
- **copyFromWindow(key)** → *
- Copies a variable from window object.
- **setInWindow(key, value, overrideExisting)** → boolean
- Sets the given value in window at the given key.
#### Queue and Array Creation
- **createArgumentsQueue(fnKey, arrayKey)** → function
- Creates a queue that is populated with argument objects, in support of tag solutions that require it.
- **createQueue(arrayKey)** → function
- Creates an array in window and returns a function that will push values onto that array.
#### URI and Encoding
- **decodeUri(encoded_uri)** → string
- Decodes any encoded characters in the provided URI.
- **decodeUriComponent(encoded_uri_component)** → string
- Decodes any encoded characters in the provided URI component.
- **encodeUri(uri)** → string
- Returns an encoded Uniform Resource Identifier (URI) by escaping special characters.
- **encodeUriComponent(str)** → string
- Returns an encoded Uniform Resource Identifier (URI) by escaping special characters.
- **fromBase64(base64EncodedString)** → string
- Lets you decode strings from their base64 representation.
- **toBase64(input)** → string
- Lets you encode a string into a base64 representation.
#### Utility Functions
- **generateRandom(min, max)** → number
- Returns a random number (integer) within the given range.
- **getContainerVersion()** → object
- Returns an object containing data about the current container.
- **getType(value)** → string
- Returns a string describing the given value's type.
- **logToConsole(obj1, obj2, ...)** → void
- Logs arguments to the browser console.
- **makeInteger(value)** → number
- Converts the given value to a number (integer).
- **makeNumber(value)** → number
- Converts the given value to a number.
- **makeString(value)** → string
- Returns the given value as a string.
- **makeTableMap(tableObj, keyColumnName, valueColumnName)** → object
- Converts a simple table object with two columns to a Map.
- **queryPermission(permission, functionArgs)** → boolean
- Query the allowed and narrowed permissions.
- **require(name)** → function
- Imports a built-in function by name.
#### Data Layer Access
- **copyFromDataLayer(key, dataLayerVersion)** → *
- Returns the value currently assigned to the given key in the data layer.
- **gtagSet(object)** → void
- Pushes a gtag set command to the data layer.
#### Cookie Management
- **getCookieValues(name, decode)** → array
- Returns the values of all cookies with the given name.
- **setCookie(name, value, options, encode)** → void
- Sets or deletes the cookie with the specified name, value, and options.
#### URL and Query Parameters
- **getQueryParameters(queryKey, retrieveAll)** → *
- Returns the first or all of the parameters for the current URL's queryKey.
- **getUrl(component)** → string
- Returns a string that represents all or a portion of the current URL.
- **parseUrl(url)** → object
- Returns an object that contains all of a given URL's component parts.
- **getReferrerUrl(component)** → string
- Reads the document object for the referrer and returns a string that represents a portion of the referrer.
- **getReferrerQueryParameters(queryKey, retrieveAll)** → *
- Acts the same way as getQueryParameters, except it acts on the referrer instead of the current URL.
#### Time Management
- **getTimestamp()** → number
- Returns a number that represents the current time in milliseconds since Unix epoch.
- **getTimestampMillis()** → number
- Returns a number that represents the current time in milliseconds since Unix epoch.
#### Network and Injection
- **injectHiddenIframe(url, onSuccess)** → void
- Adds an invisible iframe to the page.
- **injectScript(url, onSuccess, onFailure, cacheToken)** → void
- Adds a script tag to the page to load the given URL asynchronously.
- **sendPixel(url, onSuccess, onFailure)** → void
- Makes a GET request to a specified URL endpoint.
- **sha256(input, onSuccess, onFailure, options)** → void
- Calculates the SHA-256 digest of the input.
#### Document Reading
- **readCharacterSet()** → string
- Returns the value of document.characterSet.
- **readTitle()** → string
- Returns the value of document.title.
- **readAnalyticsStorage(cookieOptions)** → object
- Retrieves the data stored for analytics and returns an object with client_id and sessions.
#### Built-in Objects
- **JSON** → object
- Returns an object that provides JSON functions.
- **Math** → object
- An object providing Math functions.
- **Object** → object
- Returns an object that provides Object methods.
- **localStorage** → object
- Returns an object with methods for accessing local storage.
- **templateStorage** → object
- Returns an object with methods for accessing template storage.
---
### Test APIs
These APIs work with sandboxed JavaScript tests to build tests for custom templates in Google Tag Manager.
#### Assertions and Validation
- **assertApi(apiName)** → object
- Returns a matcher object that can be used to fluently make assertions about the given API.
- **assertThat(actual, opt_message)** → object
- Returns an object that can be used to fluently make assertions about a subject's value.
- **fail(opt_message)** → void
- Immediately fails the current test and prints the given message, if supplied.
#### Mocking
- **mock(apiName, returnValue)** → void
- Allows you to override the behavior of Sandboxed APIs.
- **mockObject(apiName, objectMock)** → void
- Lets you override the behavior of Sandboxed APIs that return an object.
#### Test Execution
- **runCode(data)** → *
- Runs the code for the template in the current test environment.
---
## API Summary
**Total Core APIs**: 49 functions across 13 categories
**Total Test APIs**: 6 functions across 3 categories
**Total APIs**: 55 functions
### Core API Categories
1. Consent Management (4 functions)
2. Event Handling (2 functions)
3. Window and Global Object Access (4 functions)
4. Queue and Array Creation (2 functions)
5. URI and Encoding (6 functions)
6. Utility Functions (8 functions)
7. Data Layer Access (2 functions)
8. Cookie Management (2 functions)
9. URL and Query Parameters (5 functions)
10. Time Management (2 functions)
11. Network and Injection (4 functions)
12. Document Reading (3 functions)
13. Built-in Objects (5 functions)
### Test API Categories
1. Assertions and Validation (3 functions)
2. Mocking (2 functions)
3. Test Execution (1 function)
---
## Usage Examples
### Working with the Data Layer
```javascript
// Get a value from the data layer
var userId = copyFromDataLayer('userId');
// Push a gtag set command
gtagSet({
'event': 'page_view',
'page_title': readTitle()
});
```
### Managing Cookies
```javascript
// Get cookie values
var cookieValues = getCookieValues('tracking_id', true);
// Set a cookie
setCookie('my_cookie', 'value123', {
'domain': 'example.com',
'path': '/',
'max-age': 86400
});
```
### Working with URLs
```javascript
// Get URL components
var hostname = getUrl('hostname');
var pathname = getUrl('pathname');
var queryString = getUrl('query');
// Parse a URL
var urlParts = parseUrl('https://example.com/page?param=value');
// Get query parameters
var userParam = getQueryParameters('user_id', false);
```
### Async Operations
```javascript
// Inject a script
injectScript('https://example.com/tracker.js', function() {
logToConsole('Script loaded successfully');
}, function() {
logToConsole('Script failed to load');
});
// Send a pixel
sendPixel('https://example.com/track?event=purchase', function() {
logToConsole('Pixel sent');
}, function() {
logToConsole('Pixel failed');
});
// Calculate SHA-256
sha256('input_string', function(result) {
logToConsole('SHA-256: ' + result);
}, function() {
logToConsole('Hash calculation failed');
});
```
### Consent Management
```javascript
// Check if consent is granted
if (isConsentGranted('analytics_storage')) {
// Proceed with analytics
}
// Add a consent listener
addConsentListener('analytics_storage', function() {
logToConsole('Consent state changed');
});
// Update consent
updateConsentState({
'analytics_storage': 'granted',
'ad_storage': 'denied'
});
```
### Testing Custom Templates
```javascript
// Mock an API
mock('sendPixel', undefined);
// Assert API behavior
assertApi('sendPixel').wasCalled();
// Run template code with test data
var result = runCode({
'event': 'test_event',
'user_id': '12345'
});
```
---
## Reference
- **Official Documentation**: https://developers.google.com/tag-platform/tag-manager/templates/api
- **Google Tag Manager**: https://tagmanager.google.com
- **GTM Custom Templates Guide**: https://developers.google.com/tag-platform/tag-manager/templates/guide

View File

@@ -0,0 +1,149 @@
# Custom Template Examples
<!-- To be populated with practical examples -->
## Tag Template Examples
### Simple Pixel Tag Template
```javascript
// Code section
const sendPixel = require('sendPixel');
const encodeUriComponent = require('encodeUriComponent');
const getUrl = require('getUrl');
const pixelUrl = 'https://example.com/pixel?'
+ 'page=' + encodeUriComponent(getUrl())
+ '&event=' + encodeUriComponent(data.eventName);
sendPixel(pixelUrl, data.gtmOnSuccess, data.gtmOnFailure);
```
### HTTP Request Tag Template
```javascript
// Code section
const sendHttpRequest = require('sendHttpRequest');
const JSON = require('JSON');
const postBody = JSON.stringify({
event: data.eventName,
userId: data.userId,
timestamp: Date.now()
});
const options = {
headers: {'Content-Type': 'application/json'},
method: 'POST',
};
sendHttpRequest(data.endpoint, options, postBody)
.then(data.gtmOnSuccess)
.catch(data.gtmOnFailure);
```
## Variable Template Examples
### Cookie Variable Template
```javascript
// Code section
const getCookieValues = require('getCookieValues');
const cookieName = data.cookieName;
const cookies = getCookieValues(cookieName);
if (cookies.length > 0) {
return cookies[0];
}
return data.defaultValue;
```
### LocalStorage Variable Template
```javascript
// Code section
const localStorage = require('localStorage');
const key = data.localStorageKey;
return localStorage.getItem(key) || data.defaultValue;
```
### Custom JavaScript Function Variable
```javascript
// Code section
const makeTableMap = require('makeTableMap');
const lookupTable = makeTableMap(data.tableInput, 'input', 'output');
const inputValue = data.inputVariable;
return lookupTable[inputValue] || data.defaultValue;
```
## Common Patterns
### Error Handling
```javascript
const sendHttpRequest = require('sendHttpRequest');
const logToConsole = require('logToConsole');
sendHttpRequest(url, options)
.then(response => {
logToConsole('Success:', response);
data.gtmOnSuccess();
})
.catch(error => {
logToConsole('Error:', error);
data.gtmOnFailure();
});
```
### Conditional Logic
```javascript
const getType = require('getType');
if (getType(data.value) === 'undefined') {
return data.defaultValue;
}
if (data.value > 0) {
return 'positive';
} else if (data.value < 0) {
return 'negative';
} else {
return 'zero';
}
```
### Data Validation
```javascript
const makeNumber = require('makeNumber');
const makeString = require('makeString');
// Validate and convert input
const numericValue = makeNumber(data.inputValue);
if (numericValue === undefined) {
logToConsole('Invalid numeric input');
data.gtmOnFailure();
return;
}
// Continue with validated value
const result = numericValue * 2;
data.gtmOnSuccess();
```
## Placeholder for Additional Examples
This file will be enhanced with:
- Server-side client template examples
- Complex permission configurations
- Field validation patterns
- Real-world use cases
- Community template patterns
**Status**: ⚠️ To be enhanced with documentation extraction

View File

@@ -0,0 +1,96 @@
# Tests
**Source**: https://developers.google.com/tag-platform/tag-manager/templates/tests
**Extracted**: 2025-01-09
## Overview
Unit tests for Google Tag Manager custom templates help you validate the functionality of your templates. You can create a set of tests for each template that can be run without needing to deploy your tag, which allows you to continuously test your template's behavior during development. Each test can provide sample input values, mock function calls, and assert code behavior.
## Limitations
- Unit tests do not check validation rules but you can manually check validation using the **Run Code** button.
- Permission checks do not happen on mocked APIs in unit tests.
## Step-by-Step Guide: Creating a Variable Template with Tests
This guide creates a variable template that takes an input string and returns the uppercase version of that string.
### Steps 1-3: Create Template and Add Field
1. Create a new variable template. Click **Templates** in the left navigation and click **New** under the **Variable Templates** section.
2. Click **Fields**.
3. Click **Add Field** and select **Text input**. Name the field \`text1\` and set the display name to _"Text 1"_.
### Step 4: Add Template Code
In the **Code** tab, replace the default code with this sandboxed JavaScript:
\`\`\`javascript
let input = data.text1;
return input.toUpperCase();
\`\`\`
### Steps 5-7: Create First Test
5. Click **Tests** to open the testing tab.
6. Click **Add Test** and change the test's name from _"Untitled test 1"_ to _"Handles strings"_.
7. Click on the expand icon to reveal the test's sandboxed JavaScript editor. Replace the code with:
\`\`\`javascript
// Call runCode to run the template's code with a lowercase string
let variableResult = runCode({text1: 'this is a test'});
// Validate that the result of runCode is an uppercase string.
assertThat(variableResult).isEqualTo('THIS IS A TEST');
\`\`\`
This test passes the string \`'this is a test'\` to the variable and verifies that the variable returns the expected value of \`'THIS IS A TEST'\`. The \`runCode\` API is used to run the template code in the **Code** tab. The argument to \`runCode\` is an object that is used as the data global. The \`assertThat\` API returns an object that can be used to fluently make assertions about a subject's value.
### Step 8: Run Tests
Click **▶ Run Tests** to run the test. The output of the test will appear in the Console.
The **▶ Run Tests** button runs all of the enabled tests in the template, in the order shown. To change the order, use the drag icon. A test can be temporarily enabled or disabled by clicking on the circle to the left of the test name. To run a single test, click the ▶ button that appears when you move the mouse over the test.
The console should print the total number of tests run and the number of tests that failed, if any. In this case, only one test was run and it should pass.
### Steps 9-11: Create Second Test for Edge Cases
9. Click **Add Test** again to add a second test. Change the test's name from _"Untitled test 2"_ to _"Handles undefined"_.
10. Click on the test to expand it and reveal the sandboxed JavaScript editor. Enter:
\`\`\`javascript
let variableResult = runCode({});
assertThat(variableResult).isEqualTo(undefined);
\`\`\`
11. Click **▶ Run Tests** to run all of the tests at once. The output of the test will appear in the console.
The _Handles undefined_ test should fail. Congratulations, you found a bug!
### Steps 12-14: Fix Code and Re-test
12. Click **Code** to go back and edit the template's sandboxed JavaScript code. Update the code as follows:
\`\`\`javascript
const getType = require('getType');
let input = data.text1;
if (getType(input) !== 'string') {
return input;
}
return input.toUpperCase();
\`\`\`
The updated code follows the best practice of validating the \`input\` variable before using it.
13. Click **Tests** to go back to the list of test cases.
14. Click **▶ Run Tests** to run all of the test cases again. This time the _Handles undefined_ test should pass.
15. Click **Save**, and close the Template Editor.
## Core APIs
### runCode
Executes the template's code with provided sample data object. Arguments are merged into the data global variable used in the template code.
### assertThat
Returns an object that can be used to fluently make assertions about a subject's value. Used for validation in tests.

View File

@@ -0,0 +1,474 @@
---
name: gtm-datalayer
description: Expert guidance for implementing the GTM data layer including structure, events, e-commerce tracking, SPA patterns, and best practices. Use when designing data layer architecture, implementing tracking events, setting up e-commerce data, debugging data layer issues, migrating to GA4 data layer patterns, working with dataLayer.push syntax, implementing data layers in React, Vue, Angular, or Next.js applications, or working with .js, .jsx, or .tsx files containing ecommerce objects.
---
# GTM Data Layer Expert
## Overview
This skill provides comprehensive expertise for implementing and managing the Google Tag Manager data layer, the foundational data structure that powers GTM implementations. Use this skill for data layer architecture, event tracking patterns, e-commerce implementation, single-page application (SPA) strategies, and data layer best practices.
## When to Use This Skill
Invoke this skill when:
- Designing data layer architecture for a website or app
- Implementing custom events and event tracking
- Setting up e-commerce tracking (GA4 or enhanced e-commerce)
- Building data layer for single-page applications (React, Vue, Angular)
- Debugging data layer issues or undefined variables
- Migrating from Universal Analytics to GA4 data layer schema
- Establishing data layer naming conventions and standards
- Creating data layer documentation
- Validating data layer implementation
- Troubleshooting timing or data quality issues
## Data Layer Fundamentals
### What is the Data Layer?
The data layer is a JavaScript object that temporarily stores data before passing it to GTM. It acts as a structured data repository that separates your website's data from your tag management implementation.
**Basic Structure:**
```javascript
window.dataLayer = window.dataLayer || [];
```
### Data Layer Initialization
Always initialize the data layer BEFORE the GTM container snippet:
```javascript
<!-- Data Layer -->
<script>
window.dataLayer = window.dataLayer || [];
dataLayer.push({
'page_type': 'homepage',
'user_logged_in': true,
'user_id': 'user123'
});
</script>
<!-- Google Tag Manager -->
<script>(function(w,d,s,l,i){...GTM snippet...})</script>
```
### Pushing to the Data Layer
Use `dataLayer.push()` to add data:
```javascript
// Basic push
dataLayer.push({
'event': 'custom_event',
'event_category': 'engagement',
'event_label': 'button_click'
});
// E-commerce push
dataLayer.push({
'event': 'purchase',
'ecommerce': {
'transaction_id': 'T12345',
'value': 99.99,
'currency': 'USD',
'items': [
{
'item_id': 'SKU123',
'item_name': 'Product Name',
'price': 99.99,
'quantity': 1
}
]
}
});
```
## Common Data Layer Patterns
### Page Metadata
```javascript
dataLayer.push({
'page_type': 'product',
'page_category': 'electronics',
'page_language': 'en',
'page_region': 'US'
});
```
### User Information
```javascript
dataLayer.push({
'user_id': 'hashed_user_id', // Never use PII!
'user_logged_in': true,
'user_type': 'premium',
'user_ltv_segment': 'high'
});
```
### Custom Events
```javascript
// Form submission
dataLayer.push({
'event': 'form_submission',
'form_id': 'contact_form',
'form_name': 'Contact Us'
});
// Video interaction
dataLayer.push({
'event': 'video_progress',
'video_title': 'Product Demo',
'video_percent': 50
});
// Search
dataLayer.push({
'event': 'search',
'search_term': 'running shoes',
'search_results': 42
});
```
### Error Tracking
```javascript
dataLayer.push({
'event': 'error',
'error_type': '404',
'error_message': 'Page not found',
'error_url': window.location.href
});
```
## E-commerce Data Layer
### GA4 E-commerce Events
**View Item List:**
```javascript
dataLayer.push({
'event': 'view_item_list',
'ecommerce': {
'items': [
{
'item_id': 'SKU123',
'item_name': 'Product Name',
'item_brand': 'Brand',
'item_category': 'Category',
'price': 29.99,
'quantity': 1
}
]
}
});
```
**Add to Cart:**
```javascript
dataLayer.push({
'event': 'add_to_cart',
'ecommerce': {
'currency': 'USD',
'value': 29.99,
'items': [
{
'item_id': 'SKU123',
'item_name': 'Product Name',
'price': 29.99,
'quantity': 1
}
]
}
});
```
**Purchase:**
```javascript
dataLayer.push({
'event': 'purchase',
'ecommerce': {
'transaction_id': 'T12345',
'value': 99.99,
'tax': 8.00,
'shipping': 5.00,
'currency': 'USD',
'items': [
{
'item_id': 'SKU123',
'item_name': 'Product Name',
'item_brand': 'Brand',
'item_category': 'Electronics',
'price': 29.99,
'quantity': 3
}
]
}
});
```
### E-commerce Implementation Workflow
1. **Product Listing Pages**: Push `view_item_list` with all visible products
2. **Product Clicks**: Push `select_item` when user clicks product
3. **Product Detail Pages**: Push `view_item` for the viewed product
4. **Add to Cart**: Push `add_to_cart` when item added
5. **Checkout Steps**: Push `begin_checkout`, `add_shipping_info`, `add_payment_info`
6. **Purchase**: Push `purchase` on order confirmation page
## Single-Page Application (SPA) Data Layer
### Virtual Pageview Pattern
```javascript
// On route change in React/Vue/Angular
function trackVirtualPageview(pageData) {
// Clear previous page data
dataLayer.push({
page_title: undefined,
page_type: undefined,
page_category: undefined
});
// Push new page data
dataLayer.push({
'event': 'virtual_pageview',
'page_title': pageData.title,
'page_location': pageData.url,
'page_type': pageData.type
});
}
```
### React Example
```javascript
import { useEffect } from 'react';
import { useLocation } from 'react-router-dom';
function usePageTracking() {
const location = useLocation();
useEffect(() => {
dataLayer.push({
'event': 'virtual_pageview',
'page_path': location.pathname,
'page_title': document.title
});
}, [location]);
}
```
### Next.js Example
```javascript
// pages/_app.js
import { useRouter } from 'next/router';
import { useEffect } from 'react';
export default function App({ Component, pageProps }) {
const router = useRouter();
useEffect(() => {
const handleRouteChange = (url) => {
dataLayer.push({
'event': 'virtual_pageview',
'page_path': url,
'page_title': document.title
});
};
router.events.on('routeChangeComplete', handleRouteChange);
return () => {
router.events.off('routeChangeComplete', handleRouteChange);
};
}, [router.events]);
return <Component {...pageProps} />;
}
```
## Data Layer Best Practices
### Naming Conventions
**Good:**
```javascript
dataLayer.push({
'event': 'form_submit',
'form_id': 'contact_form',
'user_logged_in': true
});
```
**Bad:**
```javascript
dataLayer.push({
'event': 'formSubmit', // Inconsistent casing
'FormID': 'contact_form', // PascalCase
'logged in': true // Spaces
});
```
**Conventions:**
- Use snake_case for consistency
- Use descriptive names
- Avoid abbreviations unless standard
- Be consistent across all properties
### Data Structure
**Flat structure for simple data:**
```javascript
dataLayer.push({
'event': 'custom_event',
'event_category': 'engagement',
'event_action': 'click',
'event_label': 'cta_button'
});
```
**Nested structure for complex data:**
```javascript
dataLayer.push({
'event': 'product_view',
'product': {
'id': 'SKU123',
'name': 'Product Name',
'price': 29.99,
'category': 'Electronics'
}
});
```
### Timing Considerations
1. Initialize data layer BEFORE GTM snippet
2. Push critical page data before GTM loads
3. Push event-specific data when events occur
4. For SPAs, handle route changes properly
5. Consider async data loading
### Security and Privacy
**❌ NEVER include PII in data layer:**
```javascript
// BAD - Do not do this!
dataLayer.push({
'user_email': 'user@example.com',
'user_name': 'John Doe',
'credit_card': '1234-5678-9012-3456'
});
```
**✅ Use hashed or anonymized IDs:**
```javascript
// GOOD
dataLayer.push({
'user_id': 'hashed_user_id_123abc',
'user_segment': 'premium'
});
```
### Data Quality
- Always validate required fields exist
- Use consistent data types (string, number, boolean)
- Provide default values when appropriate
- Handle null/undefined gracefully
- Test thoroughly across user journeys
## Debugging Data Layer
### Browser Console Inspection
```javascript
// View entire data layer
console.log(window.dataLayer);
// View specific push
dataLayer.push({
'event': 'test_event',
'test_data': 'value'
});
console.log(dataLayer[dataLayer.length - 1]);
// Watch for pushes
const originalPush = dataLayer.push;
dataLayer.push = function() {
console.log('DataLayer push:', arguments[0]);
return originalPush.apply(dataLayer, arguments);
};
```
### GTM Preview Mode
1. Enter Preview mode in GTM
2. Navigate to your site
3. Click on any event in Summary
4. View "Data Layer" tab
5. Inspect all pushed values
### Common Issues
**Undefined Variable:**
- Check data layer path (dot notation)
- Verify timing (pushed before tag fires?)
- Check for typos in variable names
**Data Not Persisting:**
- Data layer is event-based, not state-based
- Variables don't persist across pages (unless SPAs)
- Must re-push data on each page load
**Timing Issues:**
- Ensure data layer initialized before GTM
- Check async loading issues
- Verify event fires before tag needs data
## References
This skill includes comprehensive reference documentation:
- **references/datalayer-fundamentals.md** - Data layer basics, syntax, and implementation
- **references/ecommerce-datalayer.md** - Complete e-commerce event patterns
- **references/spa-datalayer.md** - Single-page application implementation
- **references/datalayer-best-practices.md** - Naming, structure, security, testing
Search reference files for specific patterns:
```bash
grep -r "purchase" references/
grep -r "React" references/
grep -r "consent" references/
```
## Integration with Other Skills
## Integration with Other Skills
- **gtm-general** - General GTM guidance and concepts
- **gtm-setup** - GTM container setup and installation
- **gtm-tags** - Configure tags that use data layer variables
- **gtm-triggers** - Set up custom event triggers from data layer
- **gtm-variables** - Create data layer variables to access values
- **gtm-debugging** - Debug data layer implementation issues
- **gtm-custom-templates** - Build custom templates that read data layer
- **gtm-api** - Programmatic data layer documentation export
- **gtm-best-practices** - Data layer naming and structure best practices
## Quick Reference
## Quick Reference
**Initialize:** `window.dataLayer = window.dataLayer || [];`
**Push Event:** `dataLayer.push({'event': 'event_name', 'key': 'value'});`
**Clear Variable:** `dataLayer.push({'variable_name': undefined});`
**E-commerce:** Always use GA4 schema with `ecommerce` object
**SPAs:** Clear previous data and push virtual pageviews
**Security:** Never push PII - use hashed IDs only

View File

@@ -0,0 +1,572 @@
# Data Layer Best Practices
## Overview
The data layer is a JavaScript object used by Google Tag Manager and gtag.js to pass information to tags. Events or variables can be passed via the data layer, and triggers can be set up based on the values of variables. This guide covers best practices for implementing and maintaining the data layer.
## Installation and Setup
### Proper Data Layer Initialization
The data layer must be established before the Tag Manager or Google tag snippet loads:
```html
<script>
window.dataLayer = window.dataLayer || [];
</script>
<!-- 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-XXXXXX');</script>
<!-- End Google Tag Manager -->
```
### Gtag.js Installation
For gtag.js implementations:
```html
<!-- Google tag (gtag.js) -->
<script async src="https://www.googletagmanager.com/gtag/js?id=TAG_ID"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments)};
gtag('js', new Date());
gtag('config', 'TAG_ID');
</script>
```
## How Data Layer Information is Processed
Tag Manager processes data layer messages on a first-in, first-out (FIFO) basis:
1. Each message is processed one at a time, in the order received
2. If a message is an event, any tags with trigger conditions that have been met will fire before Tag Manager moves to the next message
3. `gtag()` or `dataLayer.push()` calls queue messages for processing after all pending messages
4. Updated data layer values are not guaranteed to be available for the next event
### Event Handling Pattern
To ensure data availability, add an event name to messages and listen for that event with a Custom Event trigger:
```javascript
// Push data with a custom event
dataLayer.push({
'event': 'userData',
'userId': '12345',
'userType': 'premium'
});
```
## Best Practices
### 1. Never Overwrite the dataLayer Variable
**Bad:**
```javascript
// This overwrites existing values!
dataLayer = [{'item': 'value'}];
```
**Good:**
```javascript
// Initialize at the top of the page
window.dataLayer = window.dataLayer || [];
// Then use push() to add values
dataLayer.push({'item': 'value'});
```
### 2. Use Correct Casing
The `dataLayer` object name is case-sensitive:
**Bad:**
```javascript
datalayer.push({'pageTitle': 'Home'}); // lowercase 'l'
DataLayer.push({'pageTitle': 'Home'}); // capital 'D'
```
**Good:**
```javascript
dataLayer.push({'pageTitle': 'Home'}); // correct camelCase
```
### 3. Use Proper Quote Marks
All data layer variable names should be enclosed in quotes:
**Bad:**
```javascript
dataLayer.push({new-variable: 'value'}); // No quotes
dataLayer.push({newVariable: 'value'}); // No quotes (though valid JS)
```
**Good:**
```javascript
dataLayer.push({'new-variable': 'value'}); // Proper quotes
dataLayer.push({'newVariable': 'value'}); // Proper quotes
```
### 4. Keep Variable Names Consistent Across Pages
Use consistent naming conventions for the same concept across all pages:
**Bad:**
```javascript
// Homepage:
dataLayer.push({'visitorType': 'low-value'});
// Checkout Page:
dataLayer.push({'visitor_type': 'high-value'}); // Different naming!
```
**Good:**
```javascript
// Homepage:
dataLayer.push({'visitorType': 'low-value'});
// Checkout Page:
dataLayer.push({'visitorType': 'high-value'}); // Consistent naming
```
## Using the Data Layer with Event Handlers
### Sending Events
Use the `event` key to initiate sending events:
```javascript
dataLayer.push({'event': 'event_name'});
```
### Event with Button Click
```html
<button onclick="dataLayer.push({'event': 'login'});">Login</button>
```
### Dynamic Data Layer Variables
Push variables dynamically to capture information:
```javascript
dataLayer.push({'variable_name': 'variable_value'});
```
#### Example: Form Value Capture
```javascript
// Capture color selection
dataLayer.push({'color': 'red'});
```
## Advanced Patterns
### Pushing Multiple Variables and Events
You can push multiple variables and events simultaneously:
```javascript
dataLayer.push({
'color': 'red',
'conversionValue': 50,
'event': 'customize'
});
```
### Persisting Data Layer Variables Across Pages
To persist data layer variables between pages:
1. Call `dataLayer.push()` on each page load after data layer instantiation
2. Place the push above the GTM container code for immediate availability
```html
<script>
window.dataLayer = window.dataLayer || [];
dataLayer.push({
'event': 'Pageview',
'pagePath': 'https://www.example.com/products',
'pageTitle': 'Product Catalog',
'visitorType': 'customer'
});
</script>
<!-- Google Tag Manager -->
<script>(function(w,d,s,l,i){...})(window,document,'script','dataLayer','GTM-XXXXXX');</script>
<!-- End Google Tag Manager -->
```
**Important:** Variables persist only as long as the visitor remains on the current page. Variables relevant across pages must be declared in the data layer on each page.
## Custom Data Layer Methods
### The set() Method
Set values to retrieve later:
```javascript
window.dataLayer.push(function() {
this.set('time', new Date());
});
```
### The get() Method
Retrieve values that were set:
```javascript
window.dataLayer.push(function() {
const existingTime = this.get('time');
if (existingTime !== null) {
// Value exists, use it
} else {
// Value doesn't exist
}
});
```
### The reset() Method
Reset the data in the data layer (useful for single-page applications):
```javascript
window.dataLayer.push(function() {
this.reset();
});
```
## Renaming the Data Layer
### For gtag.js
Add a query parameter named "l" to set a new data layer name:
```html
<!-- Google tag (gtag.js) -->
<script async src="https://www.googletagmanager.com/gtag/js?id=TAG_ID&l=myNewName"></script>
<script>
window.myNewName = window.myNewName || [];
function gtag(){myNewName.push(arguments);}
gtag('js', new Date());
gtag('config', 'TAG_ID');
</script>
```
### For Tag Manager
Replace the data layer parameter value in the container snippet:
```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','myNewName','GTM-XXXXXX');</script>
<!-- End Google Tag Manager -->
```
Update all references to match the new name:
```javascript
<script>
myNewName = window.myNewName || [];
myNewName.push({'variable_name': 'variable_value'});
</script>
```
## Common Data Layer Patterns
### Page View Data
```javascript
dataLayer.push({
'event': 'pageview',
'page': {
'path': '/products/shoes',
'title': 'Shoes | My Store',
'category': 'Products'
},
'user': {
'id': 'USER123',
'status': 'logged_in',
'type': 'premium'
}
});
```
### User Interaction
```javascript
dataLayer.push({
'event': 'button_click',
'element': {
'id': 'cta-button',
'text': 'Get Started',
'destination': '/signup'
}
});
```
### Form Submission
```javascript
dataLayer.push({
'event': 'form_submission',
'form': {
'id': 'contact-form',
'name': 'Contact Us',
'fields': 5
}
});
```
### Video Tracking
```javascript
dataLayer.push({
'event': 'video_start',
'video': {
'title': 'Product Demo',
'duration': 120,
'provider': 'youtube',
'url': 'https://youtube.com/watch?v=xxx'
}
});
```
## Troubleshooting
### Common Errors
#### 1. Overwriting dataLayer
**Problem:** Using direct assignment instead of push
```javascript
// Wrong
dataLayer = [{'item': 'value'}];
```
**Solution:** Always use push after initialization
```javascript
// Correct
dataLayer.push({'item': 'value'});
```
#### 2. Case Sensitivity
**Problem:** Incorrect casing
```javascript
datalayer.push({'pageTitle': 'Home'}); // Wrong
```
**Solution:** Use correct camelCase
```javascript
dataLayer.push({'pageTitle': 'Home'}); // Correct
```
#### 3. Missing Quotes
**Problem:** Variable names without quotes
```javascript
dataLayer.push({pageTitle: 'Home'}); // Can cause issues
```
**Solution:** Always use quotes
```javascript
dataLayer.push({'pageTitle': 'Home'}); // Better
```
#### 4. Inconsistent Variable Names
**Problem:** Using different names for the same concept
```javascript
// Page 1
dataLayer.push({'user_type': 'premium'});
// Page 2
dataLayer.push({'userType': 'premium'});
```
**Solution:** Document and enforce naming conventions
```javascript
// All pages
dataLayer.push({'userType': 'premium'});
```
## Data Layer Structure Best Practices
### Use Nested Objects for Organization
```javascript
dataLayer.push({
'event': 'purchase',
'transaction': {
'id': 'T12345',
'revenue': 99.99,
'tax': 9.99,
'shipping': 5.00
},
'customer': {
'id': 'C67890',
'type': 'returning',
'lifetime_value': 1500.00
}
});
```
### Use Arrays for Multiple Similar Items
```javascript
dataLayer.push({
'event': 'product_impressions',
'products': [
{'id': 'P1', 'name': 'Blue Shoes', 'price': 49.99},
{'id': 'P2', 'name': 'Red Shoes', 'price': 59.99},
{'id': 'P3', 'name': 'Green Shoes', 'price': 54.99}
]
});
```
### Use Clear, Descriptive Names
**Bad:**
```javascript
dataLayer.push({
'e': 'clk',
'v': '100',
't': 'btn'
});
```
**Good:**
```javascript
dataLayer.push({
'event': 'button_click',
'value': '100',
'element_type': 'button'
});
```
## Testing and Validation
### 1. Use Debug Mode
Enable debug mode in Tag Manager to verify data layer pushes in real-time.
### 2. Console Logging
Check data layer contents in the browser console:
```javascript
console.log(window.dataLayer);
```
### 3. Data Layer Checker Extensions
Use browser extensions like:
- Google Tag Assistant
- dataLayer Checker
- Tag Manager/Analytics Debugger
### 4. Preview Mode
Always test changes in Tag Manager Preview mode before publishing.
## Performance Considerations
### 1. Push Data Before It's Needed
Push data layer variables before the tags that need them fire.
### 2. Avoid Excessive Pushes
Consolidate data into single pushes when possible:
**Bad:**
```javascript
dataLayer.push({'userId': '123'});
dataLayer.push({'userType': 'premium'});
dataLayer.push({'event': 'user_data'});
```
**Good:**
```javascript
dataLayer.push({
'userId': '123',
'userType': 'premium',
'event': 'user_data'
});
```
### 3. Don't Push Unnecessarily Large Data
Avoid pushing very large arrays or objects that won't be used.
### 4. Clear Data for SPAs
For single-page applications, reset the data layer between virtual page views:
```javascript
window.dataLayer.push(function() {
this.reset();
});
```
## Documentation
### Maintain a Data Layer Specification
Document all data layer variables:
- Variable name
- Data type
- When it's populated
- Example values
- Pages where it appears
- Tags/triggers that use it
### Example Documentation Format
```markdown
## userType
- **Type:** String
- **Values:** 'guest', 'registered', 'premium'
- **Populated:** On all pages after user identification
- **Example:** `{'userType': 'premium'}`
- **Used by:** User Segmentation Tags, Personalization Triggers
```
## Resources
- [Google Tag Manager Data Layer Documentation](https://developers.google.com/tag-platform/tag-manager/datalayer)
- [Data Layer Best Practices (Google Support)](https://support.google.com/tagmanager/answer/6164391)
- [GTM Help Center](https://support.google.com/tagmanager)

View File

@@ -0,0 +1,258 @@
# The Data Layer
**Source**: https://developers.google.com/tag-platform/tag-manager/datalayer
**Extracted**: 2025-01-09
The data layer is an object used by Google Tag Manager and gtag.js to pass information to tags. Events or variables can be passed via the data layer, and triggers can be set up based on the values of variables.
For example, if you fire a remarketing tag when the value of `purchase_total` is greater than $100, or based on the specific events, e.g. when a button is clicked, your data layer can be configured to make that data available to your tags. The data layer object is structured as JSON. For example:
```json
{
"event": "checkout_button",
"gtm": {
"uniqueEventId": 2,
"start": 1639524976560,
"scrollThreshold": 90,
"scrollUnits": "percent",
"scrollDirection": "vertical",
"triggers": "1_27"
},
"value": "120"
}
```
Google tags are designed to easily reference information that is added to the data layer in an organized and predictable way, rather than by parsing variables, transaction information, page categories, and other signals scattered throughout your page. A data layer implementation populated with variables and associated values will help to ensure that relevant data is available when your tags need them.
## Installation
For Tag Manager web page installations, you must create a data layer. The data layer is established before Tag Manager is loaded:
```javascript
<script>
window.dataLayer = window.dataLayer || [];
</script>
<!-- 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-XXXXXX');</script>
<!-- End Google Tag Manager -->
```
In standard gtag.js implementations where the tag has been copied from within the product and added to a web page, the code to establish the data layer is provided. In custom implementations of the Google tag, add the data layer code at the beginning of your script:
```javascript
<!-- Google tag (gtag.js) -->
<script async src="https://www.googletagmanager.com/gtag/js?id=TAG_ID"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments)};
gtag('js', new Date());
gtag('config', 'TAG_ID');
</script>
```
## How Data Layer Information is Processed
When a container is loaded, Tag Manager will begin to process all queued data layer push messages. Tag Manager processes messages on a first-in, first-out basis: Each message is processed one at a time, in the order it was received. If the message is an event, any tags with trigger conditions that have been met will fire before Tag Manager moves on to the next message.
If a `gtag()` or `dataLayer.push()` call is made by code on a page, in a Custom Template, or in a Custom HTML tag, the associated message is queued and processed after all other pending messages are evaluated. This means that any updated data layer values are not guaranteed to be available for the next event. To handle these cases, you should add an event name to a message as it is pushed to the data layer, and then listen for that event name with a Custom Event trigger.
## Use a Data Layer with Event Handlers
The `dataLayer` object uses an `event` command to initiate the sending of events.
The Google tag and Tag Manager use a special data layer variable called `event` that is used by JavaScript event listeners to fire tags when a user interacts with website elements. For example, you may want to fire a conversion tracking tag when a user clicks a purchase confirmation button. Events may be called whenever a user interacts with website elements such as links, buttons, scrolls, etc.
This functionality is accomplished by calling `dataLayer.push()` when an event occurs. The syntax for sending an event with `dataLayer.push()` is as follows:
```javascript
dataLayer.push({'event': 'event_name'});
```
Where `event_name` is a string that describes the event, such as `'login'`, `purchase`, or `search`.
Use `dataLayer.push()` to send event data when an action occurs that you'd like to measure. For example, to send an event when a user clicks a button, modify the button's `onclick` handler:
```html
<button onclick="dataLayer.push({'event': 'login'});">Button 1</button>
```
You can push data layer variables to the data layer dynamically to capture information such as values entered or selected in a form, metadata associated with a video that the visitor is playing, the color of a product (e.g. a car) customized by the visitor, the destination URLs of clicked links, etc.
The basic syntax for setting dynamic data layer variables is as follows:
```javascript
dataLayer.push({'variable_name': 'variable_value'});
```
Where `'variable_name'` is a string indicating the name of the data layer variable to be set, and `'variable_value'` is a string indicating the value of the data layer variable to be set or replaced.
For example, to set a data layer variable with a color preference when a visitor engages with a product customization tool:
```javascript
dataLayer.push({'color': 'red'});
```
## One Push, Multiple Variables
You can push multiple variables and events at once:
```javascript
dataLayer.push({
'color': 'red',
'conversionValue': 50,
'event': 'customize'
});
```
## Persist Data Layer Variables
To persist data layer variables between web pages, call `dataLayer.push()` after the data layer has been instantiated on each page load, and push the variables to the data layer. If you want these data layer variables to be available to Tag Manager when the container is loaded, add a `dataLayer.push()` call above the Tag Manager container code:
```javascript
<script>
window.dataLayer = window.dataLayer || [];
dataLayer.push({
'event': 'Pageview',
'pagePath': 'https://www.googleanalytics.dev/pancakes',
'pageTitle': 'Pancake Event Signup',
'visitorType': 'customer'
});
</script>
<!-- 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-XXXXXX');</script>
<!-- End Google Tag Manager -->
```
Each variable declared within the data layer object will persist only as long as the visitor remains on the current page. Data layer variables that are relevant across pages (e.g. `visitorType`) must be declared in the data layer on each page of your website. While you don't need to put the same set of variables in the data layer on every page, you should use a consistent naming convention. In other words: if you set the page category on the signup page using a variable called `pageCategory`, your product and purchase pages should use the `pageCategory` variable as well.
## Troubleshooting
Here are some data layer troubleshooting tips:
**Do not overwrite the `window.dataLayer` variable:** When you use the data layer directly (e.g. `dataLayer = [{'item': 'value'}]`), it will overwrite any existing values in the `dataLayer`. Tag Manager installations should instantiate the data layer as high up in the source code as possible, above the container snippet, using `window.dataLayer = window.dataLayer || [];`. After the `dataLayer` has been declared, use `dataLayer.push({'item': 'value'})` to add additional values to it, and if those values need to be available to Tag Manager when the page loads, then that `dataLayer.push()` call needs to be above the Tag Manager container code as well.
**The `dataLayer` object name is case-sensitive:** If you try to push a variable or event without the proper casing, the push will not work.
```javascript
datalayer.push({'pageTitle': 'Home'}); // Bad (datalayer in lowercase)
dataLayer.push({'pageTitle': 'Home'}); // Good (dataLayer in camel case)
```
`dataLayer.push` must be called with valid JavaScript objects. All data layer variable names should be enclosed in quotes.
```javascript
dataLayer.push({new-variable: 'value'}); // Bad - no quote marks
dataLayer.push({'new-variable': 'value'}); // Good - proper quote marks
```
**Keep variable names consistent across pages:** If you use different variable names for the same concept on different pages, your tags will be unable to consistently fire in all desired locations.
Bad:
```javascript
// Homepage:
dataLayer.push({'visitorType': 'low-value'});
// Checkout Page:
dataLayer.push({'visitor_type': 'high-value'});
```
Good:
```javascript
// Homepage:
dataLayer.push({'visitorType': 'low-value'});
// Checkout Page:
dataLayer.push({'visitorType': 'high-value'});
```
## Rename the Data Layer
The default name of the data layer object initiated by the Google tag or Tag Manager is `dataLayer`. If you'd prefer to use a different name for your data layer, you may do so by editing the data layer parameter value in your Google tag or Tag Manager container snippet with the name of your choice.
### For gtag.js
Add a query parameter named "l" to the URL to set the new data layer name, e.g. `l=myNewName`. Update all instances of `dataLayer` in the Google tag snippet to the new name:
```javascript
<!-- Google tag (gtag.js) -->
<script async src="https://www.googletagmanager.com/gtag/js?id=TAG_ID&l=myNewName"></script>
<script>
window.myNewName = window.myNewName || [];
function gtag(){myNewName.push(arguments);}
gtag('js', new Date());
gtag('config', 'TAG_ID');
</script>
```
### For Tag Manager
Replace the data layer parameter value in your container snippet with the name of your choice:
```javascript
<!-- 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','myNewName','GTM-XXXXXX');</script>
<!-- End Google Tag Manager -->
```
Once renamed, all references to your data layer (i.e. when declaring the data layer above the snippet, or when pushing events or dynamic data layer variables to the data layer with the `.push()` command) must be adjusted to reflect your custom data layer name:
```javascript
<script>
myNewName = window.dataLayer || [];
myNewName.push({'variable_name': 'variable_value'});
</script>
```
## Custom Data Layer Methods
If you push a function to the data layer, it will be invoked with this set to an abstract data model. This abstract data model can get and set values to a key value store, and also provides a way to reset the data layer.
### Set
The `set` function on the abstract data model lets you set values to retrieve through get:
```javascript
window.dataLayer.push(function() {
this.set('time', new Date());
});
```
### Get
The `get` function on the abstract data model lets you retrieve values that were set:
```javascript
window.dataLayer.push(function() {
const existingTime = this.get('time');
if (existingTime !== null) {
// Change behavior based on whether or not this value exists...
} else {
// ...
}
})
```
### Reset
The `reset` function on the abstract data model lets you reset the data in the data layer. This is most useful with a page that will remain open and the data layer size continues to grow over time:
```javascript
window.dataLayer.push(function() {
this.reset();
})
```

View File

@@ -0,0 +1,542 @@
# E-commerce Data Layer Patterns
## Overview
Ecommerce events in Google Analytics 4 (GA4) enable you to collect information about shopping behavior and quantify your most popular products, measure the influence of promotions and product placement on revenue.
## E-commerce Object Structure
### GA4 E-commerce Schema
All ecommerce events use an `items` array to represent products and services. The items array can include up to 200 elements and supports up to 27 custom parameters in addition to prescribed parameters.
#### Item Object Structure
```javascript
{
item_id: "SKU_12345", // Required
item_name: "Stan and Friends Tee", // Required
affiliation: "Google Merchandise Store",
coupon: "SUMMER_FUN",
discount: 2.22,
index: 0,
item_brand: "Google",
item_category: "Apparel",
item_category2: "Adult",
item_category3: "Shirts",
item_category4: "Crew",
item_category5: "Short sleeve",
item_list_id: "related_products",
item_list_name: "Related Products",
item_variant: "green",
location_id: "ChIJIQBpAG2ahYAR_6128GcTUEo",
price: 10.01,
quantity: 3
}
```
## E-commerce Events
### 1. View Item List
When a user is presented with a list of results (e.g., search results, category page), send a `view_item_list` event:
```javascript
gtag("event", "view_item_list", {
item_list_id: "related_products",
item_list_name: "Related products",
items: [
{
item_id: "SKU_12345",
item_name: "Stan and Friends Tee",
affiliation: "Google Merchandise Store",
coupon: "SUMMER_FUN",
discount: 2.22,
index: 0,
item_brand: "Google",
item_category: "Apparel",
item_category2: "Adult",
item_category3: "Shirts",
item_category4: "Crew",
item_category5: "Short sleeve",
item_list_id: "related_products",
item_list_name: "Related Products",
item_variant: "green",
location_id: "ChIJIQBpAG2ahYAR_6128GcTUEo",
price: 10.01,
quantity: 3
}
]
});
```
### 2. Select Item
When a user selects an item from the list:
```javascript
gtag("event", "select_item", {
item_list_id: "related_products",
item_list_name: "Related products",
items: [
{
item_id: "SKU_12345",
item_name: "Stan and Friends Tee",
// ... other item parameters
}
]
});
```
### 3. View Item Details
Measure how many times item details are viewed:
```javascript
gtag("event", "view_item", {
currency: "USD",
value: 30.03,
items: [
{
item_id: "SKU_12345",
item_name: "Stan and Friends Tee",
price: 10.01,
quantity: 3
// ... other item parameters
}
]
});
```
### 4. Add to Cart
Measure when an item is added to a shopping cart:
```javascript
gtag("event", "add_to_cart", {
currency: "USD",
value: 30.03,
items: [
{
item_id: "SKU_12345",
item_name: "Stan and Friends Tee",
price: 10.01,
quantity: 3
// ... other item parameters
}
]
});
```
### 5. Remove from Cart
Measure when a user removes an item from cart:
```javascript
gtag("event", "remove_from_cart", {
currency: "USD",
value: 30.03,
items: [
{
item_id: "SKU_12345",
item_name: "Stan and Friends Tee",
price: 10.01,
quantity: 3
// ... other item parameters
}
]
});
```
### 6. View Cart
When a user views the cart:
```javascript
gtag("event", "view_cart", {
currency: "USD",
value: 30.03,
items: [
{
item_id: "SKU_12345",
item_name: "Stan and Friends Tee",
price: 10.01,
quantity: 3
// ... other item parameters
}
]
});
```
### 7. Add to Wishlist
Measure when an item is added to a wishlist:
```javascript
gtag("event", "add_to_wishlist", {
currency: "USD",
value: 30.03,
items: [
{
item_id: "SKU_12345",
item_name: "Stan and Friends Tee",
price: 10.01,
quantity: 3
// ... other item parameters
}
]
});
```
### 8. Begin Checkout
Measure the first step in a checkout process:
```javascript
gtag("event", "begin_checkout", {
currency: "USD",
value: 30.03,
coupon: "SUMMER_FUN",
items: [
{
item_id: "SKU_12345",
item_name: "Stan and Friends Tee",
price: 10.01,
quantity: 3
// ... other item parameters
}
]
});
```
### 9. Add Shipping Info
When a user adds shipping information:
```javascript
gtag("event", "add_shipping_info", {
currency: "USD",
value: 30.03,
coupon: "SUMMER_FUN",
shipping_tier: "Ground",
items: [
{
item_id: "SKU_12345",
item_name: "Stan and Friends Tee",
price: 10.01,
quantity: 3
// ... other item parameters
}
]
});
```
### 10. Add Payment Info
When a user submits payment information:
```javascript
gtag("event", "add_payment_info", {
currency: "USD",
value: 30.03,
coupon: "SUMMER_FUN",
payment_type: "Credit Card",
items: [
{
item_id: "SKU_12345",
item_name: "Stan and Friends Tee",
price: 10.01,
quantity: 3
// ... other item parameters
}
]
});
```
### 11. Purchase
Measure a purchase:
```javascript
gtag("event", "purchase", {
transaction_id: "T_12345", // Required
value: 72.05, // Sum of (price * quantity) for all items
tax: 3.60,
shipping: 5.99,
currency: "USD",
coupon: "SUMMER_SALE",
customer_type: "new",
items: [
{
item_id: "SKU_12345",
item_name: "Stan and Friends Tee",
affiliation: "Google Merchandise Store",
coupon: "SUMMER_FUN",
discount: 2.22,
index: 0,
item_brand: "Google",
item_category: "Apparel",
item_category2: "Adult",
item_category3: "Shirts",
item_category4: "Crew",
item_category5: "Short sleeve",
item_list_id: "related_products",
item_list_name: "Related Products",
item_variant: "green",
location_id: "ChIJIQBpAG2ahYAR_6128GcTUEo",
price: 10.01,
quantity: 3
},
{
item_id: "SKU_12346",
item_name: "Google Grey Women's Tee",
affiliation: "Google Merchandise Store",
coupon: "SUMMER_FUN",
discount: 3.33,
index: 1,
item_brand: "Google",
item_category: "Apparel",
price: 21.01,
promotion_id: "P_12345",
promotion_name: "Summer Sale",
quantity: 2
}
]
});
```
### 12. Refund
Measure refunds with the relevant transaction ID:
```javascript
gtag("event", "refund", {
currency: "USD",
transaction_id: "T_12345", // Required
value: 30.03,
coupon: "SUMMER_FUN",
shipping: 3.33,
tax: 1.11,
items: [
{
item_id: "SKU_12345",
item_name: "Stan and Friends Tee",
price: 10.01,
quantity: 3
// ... other item parameters
}
]
});
```
## Promotions
### View Promotion
Measure promotion impressions:
```javascript
gtag("event", "view_promotion", {
creative_name: "Summer Banner",
creative_slot: "featured_app_1",
promotion_id: "P_12345",
promotion_name: "Summer Sale",
items: [
{
item_id: "SKU_12345",
item_name: "Stan and Friends Tee",
// ... other item parameters
}
]
});
```
### Select Promotion
Indicate a user clicked on a promotion:
```javascript
gtag("event", "select_promotion", {
creative_name: "Summer Banner",
creative_slot: "featured_app_1",
promotion_id: "P_12345",
promotion_name: "Summer Sale",
items: [
{
item_id: "SKU_12345",
item_name: "Stan and Friends Tee",
// ... other item parameters
}
]
});
```
## Best Practices
### 1. Currency Formatting
- Always set `currency` when sending `value` (revenue) data
- Ensures revenue metrics are calculated correctly
- Use standard 3-letter ISO 4217 currency codes (e.g., "USD", "EUR", "GBP")
### 2. Product IDs
- Use consistent product IDs across all events
- Ensure `item_id` matches your product catalog
- Include both `item_id` and `item_name` for better reporting
### 3. Item Array Structure
- Populate all available ecommerce parameters you have data for
- Even if a parameter is optional, include it when you have the data
- Helps maximize the utility of your ecommerce reporting
### 4. Event Timing
- Fire events at the appropriate time in the user journey
- Don't fire `purchase` events until transaction is confirmed
- Fire `view_item_list` when the list initially loads, not on interaction
### 5. Data Quality Validation
- Use [debug mode](https://support.google.com/analytics/answer/7201382) to verify events in realtime
- Check that parameters match expected values
- Verify currency and value calculations are correct
- Test the complete funnel from browsing to purchase
### 6. Custom Dimensions and Metrics
- Review [custom dimension and metric limits](https://support.google.com/analytics/answer/10075209#limits)
- Plan your custom parameters within these limits
- Document your custom parameter usage
### 7. Sample E-commerce Website
- Use [the Google sample ecommerce website](https://enhancedecommerce.appspot.com/) as a reference
- See practical examples of proper tagging
- Test your implementation against working examples
## Implementation Tips
### Setting Currency at Event Level
When setting the items array outside of the ecommerce object, set the `currency` parameter at the event level:
```javascript
gtag("event", "purchase", {
transaction_id: "T_12345",
currency: "USD", // Event-level currency
value: 72.05,
items: [
// items array
]
});
```
### Consistent Naming Conventions
Maintain consistent naming across your implementation:
- Use snake_case for event names (following GA4 conventions)
- Keep parameter names consistent with GA4 recommended events
- Document any custom parameters you add
## Common Patterns
### Product Listing Pages
```javascript
// On page load
gtag("event", "view_item_list", {
item_list_id: "category_shirts",
item_list_name: "Shirts",
items: [/* all visible products */]
});
// On product click
gtag("event", "select_item", {
item_list_id: "category_shirts",
item_list_name: "Shirts",
items: [/* clicked product */]
});
```
### Product Detail Pages
```javascript
// On page load
gtag("event", "view_item", {
currency: "USD",
value: 29.99,
items: [/* product details */]
});
// On add to cart button click
gtag("event", "add_to_cart", {
currency: "USD",
value: 29.99,
items: [/* product with quantity */]
});
```
### Shopping Cart
```javascript
// When viewing cart
gtag("event", "view_cart", {
currency: "USD",
value: 150.00,
items: [/* all cart items */]
});
// When removing item
gtag("event", "remove_from_cart", {
currency: "USD",
value: 29.99,
items: [/* removed item */]
});
```
### Checkout Flow
```javascript
// Step 1: Begin checkout
gtag("event", "begin_checkout", {
currency: "USD",
value: 150.00,
items: [/* all cart items */]
});
// Step 2: Add shipping
gtag("event", "add_shipping_info", {
currency: "USD",
value: 150.00,
shipping_tier: "Ground",
items: [/* all cart items */]
});
// Step 3: Add payment
gtag("event", "add_payment_info", {
currency: "USD",
value: 150.00,
payment_type: "Credit Card",
items: [/* all cart items */]
});
// Step 4: Complete purchase
gtag("event", "purchase", {
transaction_id: "T_12345",
value: 155.99,
tax: 10.00,
shipping: 5.99,
currency: "USD",
items: [/* all purchased items */]
});
```
## Resources
- [GA4 E-commerce Documentation](https://developers.google.com/analytics/devguides/collection/ga4/ecommerce)
- [GA4 Recommended Events Reference](https://developers.google.com/analytics/devguides/collection/ga4/reference/events)
- [Set up a Purchase Event Guide](https://developers.google.com/analytics/devguides/collection/ga4/set-up-ecommerce)
- [Sample E-commerce Website](https://enhancedecommerce.appspot.com/)

View File

@@ -0,0 +1,472 @@
# Data Layer for Single-Page Applications (SPAs)
**Source**: https://developers.google.com/analytics/devguides/collection/ga4/single-page-applications
**Last Updated**: 2025-01-09
## Overview
Single-Page Applications (SPAs) are websites that load an HTML document once and fetch additional content using JavaScript APIs. Unlike traditional multi-page applications, SPAs require special handling for tracking page views and user interactions because the browser doesn't reload the page when users navigate between different screens.
The key challenge with SPAs is that traditional page view tracking relies on full page loads, but in SPAs, navigation happens dynamically without triggering a new page load event.
## Why SPAs Require Special Treatment
### Traditional vs SPA Page Loads
**Traditional Website:**
- User clicks a link
- Browser requests a new HTML document
- Page fully reloads
- Analytics tags fire automatically on load
**Single-Page Application:**
- User clicks a link
- JavaScript updates the DOM
- URL may change (via History API)
- No page reload occurs
- Analytics tags don't automatically fire
### Key Measurement Goals
To accurately track SPAs, you need to:
1. **Count page views for each screen** a user interacts with
2. **Track the page referrer correctly** to trace the user journey
3. **Maintain proper event sequencing** as users navigate
4. **Clear previous page data** to avoid data carryover
5. **Update page-specific parameters** for each virtual page view
## Implementation Methods
### Method 1: Browser History Changes (Recommended)
Use this method if your SPA uses the [History API](https://developer.mozilla.org/en-US/docs/Web/API/History), specifically the `pushState()` and `replaceState()` methods to update screens.
#### How It Works
GTM's **History Change trigger** listens for:
- Changes to the URL fragment (hash)
- Calls to `history.pushState()`
- Calls to `history.replaceState()`
- Browser back/forward button clicks (`popstate` event)
#### GTM Setup
1. **Enable Built-in History Variables** in GTM:
- History Old URL Fragment
- History New URL Fragment
- History Old State
- History New State
- History Source (pushState, replaceState, popstate, or hashchange)
2. **Create a History Change Trigger:**
- Go to Triggers > New
- Choose "History Change" as trigger type
- Configure any additional filters if needed
- This trigger fires whenever the URL changes without a page reload
3. **Create a Virtual Page View Tag:**
- Create a GA4 Event tag
- Event Name: `page_view`
- Set to fire on the History Change trigger
- Configure page parameters (page_location, page_title, etc.)
#### Example Implementation
```javascript
// Your SPA framework (e.g., React Router) handles navigation
// It uses pushState internally:
history.pushState({ page: 'products' }, 'Products', '/products');
// GTM's History Change trigger automatically detects this
// and fires your configured tags
```
#### Data Layer Push Pattern
When using History Change triggers, push updated page data to the data layer:
```javascript
// Clear previous page data and push new page data
window.dataLayer.push({
event: 'virtual_pageview',
page_path: '/new-page',
page_title: 'New Page Title',
page_location: window.location.href,
// Clear previous page-scoped variables
previous_page_data: undefined,
transaction_id: undefined // Clear transaction-specific data
});
```
### Method 2: Custom Events
Use this method if your website uses the [`DocumentFragment`](https://developer.mozilla.org/en-US/docs/Web/API/DocumentFragment) object to render different screens, or if you need more control over when virtual page views fire.
#### How It Works
You manually push custom events to the data layer when screen changes occur, rather than relying on automatic History API detection.
#### Implementation
```javascript
// In your SPA's route change handler
function onRouteChange(newRoute) {
// Update the DOM with new content
updateContent(newRoute);
// Push virtual pageview to data layer
window.dataLayer.push({
event: 'virtual_pageview',
page_path: newRoute.path,
page_title: newRoute.title,
page_location: window.location.href
});
}
```
#### GTM Setup
1. **Create a Custom Event Trigger:**
- Go to Triggers > New
- Choose "Custom Event" as trigger type
- Event name: `virtual_pageview`
2. **Create Variables for Page Data:**
- Data Layer Variable for `page_path`
- Data Layer Variable for `page_title`
- Data Layer Variable for `page_location`
3. **Create a GA4 Event Tag:**
- Event Name: `page_view`
- Add event parameters using the variables created above
- Set to fire on the Custom Event trigger
## Data Layer Clearing Best Practices
### Why Clear Data
In SPAs, data persists in the data layer until explicitly cleared. This can cause:
- Transaction data appearing on non-transaction pages
- User data from one session bleeding into another
- Incorrect attribution of events to pages
### What to Clear
**Page-Scoped Data** (clear on every virtual pageview):
- `page_title`
- `page_path`
- `page_category`
- Custom page dimensions
**Event-Scoped Data** (clear after the event fires):
- `transaction_id`
- `ecommerce` objects
- Form submission data
- Click data
**Persistent Data** (keep across page views):
- `user_id`
- `user_type`
- Session-level dimensions
### Clearing Pattern
```javascript
// Pattern 1: Clear and set in separate pushes
dataLayer.push(function() {
this.reset(); // Clear all data layer state
});
dataLayer.push({
event: 'virtual_pageview',
page_title: 'New Page',
page_path: '/new-page'
});
// Pattern 2: Clear and set in one push (set to undefined)
dataLayer.push({
event: 'virtual_pageview',
// Clear previous values
transaction_id: undefined,
ecommerce: undefined,
form_id: undefined,
// Set new values
page_title: 'New Page',
page_path: '/new-page'
});
```
## Framework-Specific Implementation
### React with React Router
```javascript
import { useEffect } from 'react';
import { useLocation } from 'react-router-dom';
function Analytics() {
const location = useLocation();
useEffect(() => {
// Clear previous page data
window.dataLayer.push({
event: 'virtual_pageview',
page_path: location.pathname,
page_title: document.title,
page_location: window.location.href,
// Clear event-scoped data
transaction_id: undefined,
ecommerce: undefined
});
}, [location]);
return null;
}
export default Analytics;
```
### Vue.js with Vue Router
```javascript
// In your main.js or router configuration
import router from './router';
router.afterEach((to, from) => {
window.dataLayer.push({
event: 'virtual_pageview',
page_path: to.path,
page_title: to.meta.title || document.title,
page_location: window.location.href,
// Clear event-scoped data
transaction_id: undefined,
ecommerce: undefined
});
});
```
### Angular with Angular Router
```typescript
import { Router, NavigationEnd } from '@angular/router';
import { filter } from 'rxjs/operators';
export class AppComponent {
constructor(private router: Router) {
this.router.events.pipe(
filter(event => event instanceof NavigationEnd)
).subscribe((event: NavigationEnd) => {
window.dataLayer.push({
event: 'virtual_pageview',
page_path: event.urlAfterRedirects,
page_title: document.title,
page_location: window.location.href,
// Clear event-scoped data
transaction_id: undefined,
ecommerce: undefined
});
});
}
}
```
### Next.js
```javascript
// In pages/_app.js
import { useEffect } from 'react';
import { useRouter } from 'next/router';
function MyApp({ Component, pageProps }) {
const router = useRouter();
useEffect(() => {
const handleRouteChange = (url) => {
window.dataLayer.push({
event: 'virtual_pageview',
page_path: url,
page_title: document.title,
page_location: window.location.href,
// Clear event-scoped data
transaction_id: undefined,
ecommerce: undefined
});
};
router.events.on('routeChangeComplete', handleRouteChange);
return () => {
router.events.off('routeChangeComplete', handleRouteChange);
};
}, [router.events]);
return <Component {...pageProps} />;
}
export default MyApp;
```
## Testing and Debugging SPAs
### Preview Mode in GTM
1. **Enable Preview Mode** in your GTM container
2. Navigate through your SPA
3. Watch for:
- History Change events firing
- Custom Event triggers activating
- Data layer state changes
- Tag firing sequence
### Debug Console Checklist
For each virtual page view, verify:
- [ ] `page_view` event fires
- [ ] `page_location` updates correctly
- [ ] `page_title` reflects the new screen
- [ ] Previous page's `page_location` becomes current `page_referrer`
- [ ] Event-scoped data is cleared
- [ ] User/session data persists
### DebugView in GA4
1. **Enable Debug Mode** in GTM tags:
```javascript
// Add to your data layer push
window.dataLayer.push({
event: 'virtual_pageview',
debug_mode: true,
// ... other parameters
});
```
2. **Navigate through your SPA**
3. **Check in GA4 DebugView:**
- Each screen change should create a new `page_view` event
- Event parameters should update correctly
- Event sequence should match user journey
### Common SPA Pitfalls
#### 1. Data Carryover
**Problem:** Transaction data appears on non-checkout pages
**Solution:**
```javascript
// Always clear ecommerce data after it's sent
dataLayer.push({
event: 'purchase',
ecommerce: { /* purchase data */ }
});
// On next page view, clear it
dataLayer.push({
event: 'virtual_pageview',
ecommerce: undefined, // Explicitly clear
transaction_id: undefined
});
```
#### 2. Missing Virtual Pageviews
**Problem:** Some navigation doesn't trigger page views
**Solution:** Ensure all route changes push to data layer, including:
- Back/forward button navigation
- Hash changes
- Modal/dialog state changes (if tracking as pages)
#### 3. Duplicate Page Views
**Problem:** Both real and virtual page views fire
**Solution:**
```javascript
// Block the initial page_view from GA4 Config tag
// Use a Pageview trigger with "Fire on DOM Ready" exception
// Or configure GA4 tag to not send page_view on initial load
```
#### 4. Incorrect Referrer
**Problem:** `page_referrer` doesn't reflect previous virtual page
**Solution:** GTM automatically handles this when using History Change triggers. For custom events, ensure you're not manually setting `page_referrer`.
## Advanced Patterns
### Conditional Virtual Pageviews
Only track certain route changes:
```javascript
function shouldTrackPageview(newRoute) {
// Don't track hash-only changes
if (newRoute.startsWith('#')) return false;
// Don't track query parameter-only changes
if (isSamePath(currentRoute, newRoute)) return false;
return true;
}
if (shouldTrackPageview(newRoute)) {
dataLayer.push({
event: 'virtual_pageview',
page_path: newRoute
});
}
```
### Enhanced Virtual Pageview Data
Include additional context with virtual pageviews:
```javascript
dataLayer.push({
event: 'virtual_pageview',
page_path: '/products/category/shoes',
page_title: 'Shoes - Products',
page_location: window.location.href,
// Additional context
page_category: 'Products',
page_subcategory: 'Shoes',
content_group: 'Product Listing',
user_journey_step: 'Browse',
spa_route_type: 'category_page'
});
```
## Verification Checklist
Before deploying your SPA tracking:
- [ ] History Change trigger configured (if using History API)
- [ ] Custom Event trigger configured (if using custom events)
- [ ] Data Layer Variables created for page parameters
- [ ] GA4 Event tag configured with `page_view` event
- [ ] Initial page load tracked correctly
- [ ] All navigation types trigger virtual pageviews:
- [ ] Forward navigation
- [ ] Back button
- [ ] Direct URL changes
- [ ] Hash changes (if applicable)
- [ ] Data clearing implemented for:
- [ ] Transaction data
- [ ] Event-scoped variables
- [ ] Page-scoped variables
- [ ] Tested in Preview Mode
- [ ] Verified in GA4 DebugView
- [ ] Event sequence matches user journey
- [ ] Page referrer updates correctly
## Resources
- [Google Analytics: Measure Single-Page Applications](https://developers.google.com/analytics/devguides/collection/ga4/single-page-applications)
- [GTM History Change Trigger](https://support.google.com/tagmanager/answer/7679322)
- [GTM Built-in Variables for Web](https://support.google.com/tagmanager/answer/7182738)
- [History API Documentation (MDN)](https://developer.mozilla.org/en-US/docs/Web/API/History)
- [Single-Page Applications (MDN)](https://developer.mozilla.org/en-US/docs/Glossary/SPA)

View File

@@ -0,0 +1,113 @@
---
name: gtm-debugging
description: Expert guidance for debugging and testing Google Tag Manager implementations using Preview mode, Tag Assistant, debug console, and troubleshooting common issues like tags not firing, undefined variables, or timing problems. Use when debugging GTM, troubleshooting why tags aren't firing, testing GTM configurations, or analyzing GTM issues.
---
# GTM Debugging & Testing
## Overview
This skill provides expertise for debugging and testing Google Tag Manager implementations using Preview mode, Tag Assistant, and systematic troubleshooting approaches.
## When to Use This Skill
Invoke this skill when:
- Debugging why tags aren't firing
- Testing GTM implementations
- Troubleshooting undefined variables
- Investigating timing or sequencing issues
- Using GTM Preview mode
- Working with Tag Assistant
- Validating GTM configurations
- Comparing GTM versions
## Preview Mode & Debug Console
### Enable Preview Mode
1. Open GTM container
2. Click "Preview" button
3. Enter your website URL
4. Debug window opens
### Debug Console Sections
- **Summary** - All events fired on page
- **Tags** - Tags fired and not fired
- **Variables** - All variable values
- **Data Layer** - Data layer state at each event
- **Errors** - JavaScript errors and issues
## Common Debugging Workflows
### Debug Tag Not Firing
1. Enter Preview Mode
2. Trigger the event
3. Check "Tags Not Fired" section
4. Review trigger conditions in Variables tab
5. Inspect Data Layer
6. Fix conditions and retest
### Debug Undefined Variable
1. Find the event where variable is needed
2. Check Variables tab for the variable
3. Verify data layer contains the value
4. Check variable configuration (path, type)
5. Verify timing (is data available when tag fires?)
### Debug Data Layer Issues
1. Open Data Layer tab in debug console
2. Find the event where data should be pushed
3. Verify data structure matches expectations
4. Check for typos in variable names
5. Validate data types (string, number, object)
## Common Issues & Solutions
### Tag Fires on Wrong Pages
- Check trigger conditions
- Verify Page URL or Page Path filters
- Review trigger exceptions
- Test with different URL patterns
### Variable Returns Undefined
- Check data layer path (dot notation)
- Verify timing (pushed before tag fires?)
- Check for typos in variable names
- Validate data layer structure
### Tag Fires Multiple Times
- Check for duplicate triggers
- Review History Change triggers on SPAs
- Verify event deduplication
- Check tag sequencing
### Performance Issues
- Review number of tags firing
- Check custom HTML execution time
- Audit unnecessary triggers
- See gtm-best-practices skill for optimization
## Tag Assistant
- Chrome extension for GTM debugging
- Real-time tag validation
- HTTP request inspection
- GA4 event validation
## Testing Checklist
- [ ] Tags fire on correct pages/events
- [ ] Variables populate with correct values
- [ ] No JavaScript errors in console
- [ ] Data layer pushes correctly
- [ ] Triggers activate as expected
- [ ] No duplicate tag fires
- [ ] Performance is acceptable
## References
- **references/debugging-testing.md** - Debug console, preview mode, testing workflows
## Integration with Other Skills
## Integration with Other Skills
- **gtm-general** - General GTM guidance and concepts
- **gtm-tags** - Understand tag configuration
- **gtm-triggers** - Understand trigger setup
- **gtm-variables** - Understand variable configuration
- **gtm-datalayer** - Debug data layer implementation
- **gtm-setup** - Verify container installation
- **gtm-best-practices** - Testing and optimization best practices

View File

@@ -0,0 +1,642 @@
# Google Tag Manager - Debugging and Testing
**Sources**:
- https://support.google.com/tagmanager/answer/6107056
- https://developers.google.com/tag-platform/tag-manager/server-side/debug
**Last Updated**: 2025-01-09
## Overview
Testing and debugging are critical components of any Google Tag Manager implementation. GTM provides comprehensive tools to help you verify that tags fire correctly, triggers activate as expected, and data flows accurately to your analytics platforms.
## Preview Mode
Preview mode (formerly called Debug mode) allows you to test your GTM container configuration before publishing it to production. When enabled, you can browse your website with the unpublished container draft and see exactly how tags behave.
### Enabling Preview Mode
1. **Navigate to GTM** at https://tagmanager.google.com
2. **Open your container** workspace
3. **Click "Preview"** in the top right corner
4. **Tag Assistant launches** in a new tab
5. **Enter your website URL**
6. **Optional**: Uncheck "Include debug signal in the URL" if it breaks your site
7. **Click "Connect"**
8. **Your website opens** in a new window with "Connected" indicator
9. **Return to Tag Assistant** and click "Continue"
The debug interface appears, showing detailed information about tag firing, triggers, variables, and the data layer.
### Tag Assistant Companion
Installing the [Tag Assistant Companion Chrome extension](https://chrome.google.com/webstore/detail/tag-assistant-companion/jmekfmbnaedfebfnmakmokmlfpblbfdm) improves the preview experience by opening your website in a new tab instead of a popup window.
### Previewing Older Versions
To test a previously published version:
1. Go to **Versions** in your workspace navigation
2. Find the version to preview
3. Click **More Actions** (three dots)
4. Select **Preview**
## Using the Debug Interface
### Interface Overview
The debug interface consists of several key areas:
- **Summary Panel**: Overview of the current event and tag firing status
- **Tags Panel**: Lists which tags fired and which didn't
- **Data Layer Panel**: Shows the data layer state and events
- **Variables Panel**: Displays variable values for the current event
- **Errors Panel**: Lists JavaScript errors and tag failures
### Summary View
Shows a timeline of events as you interact with your website:
```
Container Loaded
Page View
DOM Ready
Window Loaded
Click (Button)
Custom Event (form_submit)
```
Click any event to see:
- Which tags fired
- Which triggers activated
- Current data layer state
- Variable values at that moment
### Tags View
**Tags Fired:**
- Green indicators show successfully fired tags
- Red indicators show failed tags
- Number shows how many times the tag fired
- Click a tag to see:
- Tag configuration
- Triggering conditions
- Blocking triggers
- Execution order
**Tags Not Fired:**
- Shows tags that didn't fire for this event
- Click to see why (trigger conditions not met, blocking triggers, etc.)
### Data Layer View
Displays the data layer's state:
```javascript
{
"gtm.start": 1704844800000,
"event": "gtm.js",
"gtm.uniqueEventId": 1
}
```
Shows:
- All pushes to the data layer
- Current state of the data layer
- Event sequence
- Custom data layer variables
### Variables View
Lists all variables and their current values:
| Variable Name | Value | Type |
|--------------|-------|------|
| Page URL | https://example.com/products | Built-in |
| Page Path | /products | Built-in |
| Product Name | Blue Widget | Data Layer Variable |
| User ID | 12345 | Data Layer Variable |
Helps verify:
- Variables resolve to expected values
- Data layer variables capture correct data
- Custom JavaScript variables execute properly
### Errors View
Shows JavaScript errors and tag execution failures:
```
Tag: GA4 Event - Purchase
Error: sendBeacon failed - network error
Tag: Facebook Pixel
Error: fbq is not defined
```
Critical for identifying:
- Missing vendor libraries
- JavaScript syntax errors
- Network failures
- Configuration issues
## Sharing Preview Mode
### Share with Colleagues
To let others view your debug session:
1. **In Tag Assistant**, click **More Actions** (three dots)
2. **Select "Share"**
3. **Enter your website domain**
4. **Copy the preview URL**
5. **Send to colleagues**
The recipient can:
- Connect to your site in preview mode
- View the Tag Assistant debug interface
- See the same container draft you're testing
**Note**: The preview URL is temporary and expires after the debug session ends.
### Share Specific Versions
From the Versions tab:
1. Click **More Actions** on any version
2. Select **Share Preview**
3. Enter target website domain
4. Copy and share the preview URL
## Debugging Common Scenarios
### Tag Not Firing
**Checklist:**
1. **Check the trigger**
- Is the trigger configured correctly?
- Are the trigger conditions being met?
- Check trigger variables resolve correctly
2. **Check for blocking triggers**
- Does the tag have any exception/blocking triggers?
- Are those triggers inadvertently activating?
3. **Check tag priority/sequencing**
- Does another tag need to fire first?
- Is tag sequencing configured correctly?
4. **Check the data layer**
- Is required data present when trigger evaluates?
- Are data layer variables returning expected values?
### Trigger Not Activating
**Debugging Steps:**
1. **Verify trigger conditions**
```
Example: Click trigger on CSS selector
- Check selector syntax
- Verify element exists on page
- Test with simpler selector
```
2. **Check built-in variables**
- Are required built-in variables enabled?
- Click Variables > Configure
- Enable missing variables
3. **Test variable values**
- Check Variables panel
- Verify trigger conditions match actual values
- Look for type mismatches (string vs number)
### Variable Returning Undefined
**Common Causes:**
1. **Data layer variable not found**
```javascript
// Data layer:
{ "product_name": "Widget" }
// Variable configured as:
productName // Wrong - case sensitive!
// Should be:
product_name // Correct
```
2. **Timing issue**
- Data pushed after tag fires
- Use Custom Event trigger to wait for data
3. **Incorrect data layer version**
- Check Data Layer Version setting
- Version 2 vs Version 1 syntax differs
### Data Layer Issues
**Debug Pattern:**
```javascript
// In browser console, inspect data layer
console.log(window.dataLayer);
// Check for specific event
window.dataLayer.filter(item => item.event === 'purchase');
// Watch for new pushes
var originalPush = window.dataLayer.push;
window.dataLayer.push = function() {
console.log('DataLayer push:', arguments[0]);
return originalPush.apply(this, arguments);
};
```
### JavaScript Errors
**Investigation Steps:**
1. **Check browser console** (F12 > Console)
2. **Look for errors** before tag execution
3. **Verify vendor scripts** load correctly
4. **Check for conflicts** between tags
5. **Test with tags disabled** one at a time
## Server-Side Debugging
For server-side GTM containers, the debug interface differs:
### Server Preview Layout
**Left Panel**: Incoming HTTP requests
```
collect?v=2&tid=G-XXXXXX&en=page_view...
└─ page_view
└─ scroll
└─ add_to_cart
```
**Right Panel Tabs**:
- Request
- Tags
- Variables
- Event Data
- Console
### Request Tab
**Client Box**: Shows which client claimed the request
**Incoming HTTP Request**: Full request details
- Headers
- Query parameters
- Request body
- Should match what's in Chrome Network tab
**Outgoing HTTP Requests**: Requests sent to vendors
- Tag that generated the request
- Request details (URL, headers, body)
- HTTP response from vendor
- Status code and response body
### Debugging Server Tags
**Tags Fired**:
- Success/failure status
- Number of times fired
- Click to see:
- Tag properties
- Outgoing HTTP requests
- Firing triggers
**Tags Not Fired**:
- Available tags that didn't fire
- Reason they didn't fire
### Server Variables
Shows:
- Variable type
- Return type
- Current value
Example:
```
var_screen_resolution: "1536x864"
var_user_agent: "Mozilla/5.0..."
var_client_id: "123456.789012"
```
### Event Data Tab
Full event data object:
```json
{
"event_name": "purchase",
"value": 129.99,
"currency": "USD",
"transaction_id": "T_12345",
"items": [...]
}
```
This data populates variable values.
### Server Console
Shows errors from fired tags:
```
Tag: GA4 Server Tag
Error: Invalid endpoint URL
Tag: Facebook Conversions API
Error: HTTP 401 - Invalid access token
```
## Testing Workflows
### Pre-Publishing Checklist
Before publishing any container version:
- [ ] Enable preview mode
- [ ] Test on all key pages:
- [ ] Homepage
- [ ] Product pages
- [ ] Category pages
- [ ] Cart/checkout
- [ ] Confirmation page
- [ ] Verify all critical tags fire
- [ ] Check data layer on each page
- [ ] Test all conversion events
- [ ] Verify cross-domain tracking
- [ ] Test with ad blockers disabled and enabled
- [ ] Check mobile experience (responsive design mode)
- [ ] Verify no JavaScript errors
- [ ] Confirm data in vendor platforms (GA4, Ads, etc.)
### Testing Different Environments
Use GTM Environments for staged testing:
1. **Development Environment**
- Test unstable/experimental changes
- Break things without consequence
- Rapid iteration
2. **Staging Environment**
- Test on staging server
- QA team validation
- Stakeholder review
3. **Production Environment**
- Live site
- Real user data
- Careful change management
### Cross-Domain Testing
When testing cross-domain tracking:
1. **Enable preview** on primary domain
2. **Navigate to secondary** domain
3. **Verify preview mode** persists
4. **Check data layer** for linker parameters
5. **Confirm client IDs** match across domains
### Version Comparison
Compare container versions:
1. Go to **Versions**
2. Select two versions
3. Click **Compare**
4. Review differences:
- Tags added/removed/modified
- Trigger changes
- Variable updates
## Browser Developer Tools
### Network Tab
Monitor tag requests:
1. **Open DevTools** (F12)
2. **Go to Network tab**
3. **Filter**: "analytics", "gtm", "google-analytics"
4. **Trigger events** on your site
5. **Inspect requests**:
- Check parameters sent
- Verify timing
- Look for errors (red status codes)
### Console Tab
Monitor JavaScript execution:
```javascript
// Check GTM loaded
console.log(google_tag_manager);
// Check dataLayer
console.log(dataLayer);
// Monitor events
dataLayer.push = new Proxy(dataLayer.push, {
apply: function(target, thisArg, args) {
console.log('DataLayer event:', args[0]);
return target.apply(thisArg, args);
}
});
```
### Application Tab
Inspect cookies:
1. **Open Application tab**
2. **Go to Cookies**
3. **Select your domain**
4. **Check for**:
- `_ga` (GA client ID)
- `_gid` (GA session ID)
- Custom cookies
## GA4 DebugView
For GA4-specific debugging:
1. **Enable debug mode** in GTM:
```javascript
// Add to data layer
window.dataLayer.push({
'debug_mode': true
});
```
2. **Or use Chrome extension**: Google Analytics Debugger
3. **Open GA4 DebugView**:
- Go to GA4 property
- Navigate to Configure > DebugView
- See real-time events from your debug session
4. **Verify in DebugView**:
- Events appear immediately
- Parameters are correct
- Event sequence matches expectations
## Common Debugging Patterns
### Test Ecommerce Flow
```javascript
// 1. View item list
dataLayer.push({
event: 'view_item_list',
ecommerce: { items: [...] }
});
// 2. Add to cart
dataLayer.push({
event: 'add_to_cart',
ecommerce: { items: [...] }
});
// 3. Purchase
dataLayer.push({
event: 'purchase',
ecommerce: {
transaction_id: 'T_12345',
value: 129.99,
items: [...]
}
});
// Verify each step in Preview Mode
```
### Test Conditional Logic
```javascript
// Test trigger with conditions
if ({{Page Path}} contains '/products/') {
// Should fire: Product View tag
// Should not fire: Homepage tag
}
// Verify in Variables panel
```
### Test Tag Sequencing
```javascript
// Tag A must fire before Tag B
// Tag A: Setup Tag
// - No sequencing
// Tag B: Cleanup Tag
// - Setup Tag: Tag A
// - Firing: After Tag A
// Verify firing order in Summary panel
```
## Troubleshooting Tips
### Clear Browser Cache
Sometimes old container versions cache:
```
1. Hard refresh: Ctrl+Shift+R (Windows) / Cmd+Shift+R (Mac)
2. Clear cache completely
3. Close and reopen preview mode
```
### Check Container Version
Verify correct container loads:
```javascript
// In console:
google_tag_manager['GTM-XXXXX'].dataLayer.get('gtm.version')
```
### Verify Container ID
Ensure correct container on page:
```html
<!-- Check page source for -->
<script>
(function(w,d,s,l,i){...})(window,document,'script','dataLayer','GTM-XXXXX');
</script>
```
### Multiple Containers
If multiple containers exist:
- Each fires independently
- Check all containers in preview
- Avoid duplicate tags across containers
## Best Practices
### Testing Best Practices
1. **Test before publishing** - Always use preview mode
2. **Test on real pages** - Not just homepage
3. **Test user journeys** - Complete flows, not just individual pages
4. **Document your tests** - Use version notes
5. **Get peer review** - Have colleagues review in preview mode
6. **Test with real data** - Use production-like scenarios
### Debugging Best Practices
1. **Start simple** - Test one thing at a time
2. **Check the basics first** - Is GTM loading? Is the tag enabled?
3. **Use the data layer** - Don't rely on page scraping
4. **Log everything** - Use version notes to document changes
5. **Keep containers clean** - Remove unused tags/triggers/variables
### Documentation
When testing, document:
```
Version: 123
Changes:
- Added GA4 purchase event
- Modified product click trigger
- Updated checkout flow
Tests Performed:
- ✅ Purchase event fires on confirmation page
- ✅ Product clicks tracked correctly
- ✅ Checkout funnel complete
- ❌ Cross-domain tracking issue on subdomain (to fix)
Tested By: Henrik
Date: 2025-01-09
```
## Exit Preview Mode
To stop debugging:
1. **Click X** in Tag Assistant debug interface
2. **Click "Stop debugging"** on Tag Assistant page
3. **Close preview window**
Preview mode only affects your browser - regular visitors don't see the debug interface.
## Resources
- [GTM Preview and Debug Containers](https://support.google.com/tagmanager/answer/6107056)
- [Preview and Debug Server Containers](https://developers.google.com/tag-platform/tag-manager/server-side/debug)
- [Tag Assistant](https://support.google.com/tagassistant/answer/10039345)
- [GA4 DebugView](https://support.google.com/analytics/answer/7201382)
- [GTM Troubleshooting](https://support.google.com/tagmanager/topic/9002003)

334
skills/gtm-general/SKILL.md Normal file
View File

@@ -0,0 +1,334 @@
---
name: gtm-general
description: General guidance and overview for Google Tag Manager (GTM), including what GTM is, how it works, GTM architecture, account structure, workspace concepts, version control, publishing workflows, when to use GTM, GTM vs hardcoded tags, container types (web, mobile, server-side), GTM terminology, common use cases, and routing to specialized GTM skills. Use when asking general questions about GTM, learning about GTM fundamentals, understanding GTM concepts, planning GTM implementation strategy, comparing GTM approaches, getting started with GTM, or when unsure which specific GTM skill to use.
---
# Google Tag Manager - General Guidance
## Overview
General guidance for Google Tag Manager (GTM) covering fundamentals, concepts, architecture, and routing to specialized skills for specific GTM tasks.
## When to Use This Skill
Invoke this skill when:
- Asking general questions about Google Tag Manager
- Learning GTM fundamentals and core concepts
- Understanding how GTM works and its architecture
- Planning GTM implementation strategy
- Deciding whether to use GTM vs other approaches
- Understanding GTM terminology and concepts
- Getting oriented with GTM capabilities
- Unsure which specific GTM skill applies to your question
- Comparing GTM container types or approaches
- Understanding GTM account structure and organization
## What is Google Tag Manager?
Google Tag Manager (GTM) is a free tag management system that allows you to deploy and manage marketing tags (tracking codes, analytics snippets, pixels) on your website or mobile app without modifying code directly.
**Key Benefits:**
- **No code deployments** - Add/modify tags without developer assistance
- **Faster implementation** - Deploy tags in minutes instead of weeks
- **Version control** - Track changes, test, and rollback if needed
- **Centralized management** - Manage all tags in one place
- **Built-in templates** - Pre-built tags for GA4, Google Ads, Facebook, etc.
- **Preview & debug** - Test before publishing to production
- **Performance** - Async loading, conditional firing
## GTM Architecture & Concepts
### Container Structure
**Account** (Organization level)
└── **Container** (Website/App level)
├── **Workspace** (Development environment)
│ ├── Tags (What to fire)
│ ├── Triggers (When to fire)
│ └── Variables (Data to capture)
└── **Versions** (Snapshots of container state)
### Core Components
**Tags** - Code snippets to fire (GA4, Google Ads, pixels, custom HTML)
- See **gtm-tags** skill for tag configuration
**Triggers** - Rules for when tags should fire (page views, clicks, events)
- See **gtm-triggers** skill for trigger configuration
**Variables** - Dynamic values used in tags and triggers (URLs, data layer values, cookies)
- See **gtm-variables** skill for variable configuration
**Data Layer** - JavaScript object for passing data to GTM
- See **gtm-datalayer** skill for data layer implementation
### Container Types
**Web Container** - For websites
- Most common container type
- Uses GTM snippet in HTML
- Supports page view, click, form, scroll tracking
- See **gtm-setup** skill for installation
**Mobile Container** - For iOS/Android apps
- Integrates with Firebase
- Different trigger types (screen view, app events)
**Server-Side Container** - For server-side tagging
- Runs on server infrastructure (Google Cloud, Cloudflare Workers, etc.)
- First-party data collection
- Enhanced privacy and control
- Better performance (offload client-side tags)
- See **gtm-api** skill for programmatic management
### Workspace & Version Control
**Workspaces** - Isolated development environments
- Multiple team members can work simultaneously
- Changes don't affect live container until published
- Merge changes when ready
**Versions** - Snapshots of container configuration
- Create version when ready to publish
- Version history maintained
- Rollback to previous version if needed
- Document changes in version notes
**Environments** - Different deployment targets
- **Live/Production** - Published container serving real traffic
- **Latest** - Most recent version (for testing)
- **Custom environments** - Development, staging, QA
## Common Use Cases
### Analytics Tracking
- Google Analytics 4 (GA4) implementation
- Page view tracking
- Event tracking (clicks, form submits, downloads)
- E-commerce tracking
- User behavior analysis
- See **gtm-tags** and **gtm-datalayer** skills
### Marketing & Advertising
- Google Ads conversion tracking
- Google Ads remarketing
- Facebook Pixel / Meta Pixel
- LinkedIn Insight Tag
- TikTok Pixel, Twitter/X Pixel
- See **gtm-tags** skill
### Custom Implementations
- A/B testing tools (Optimizely, VWO, Google Optimize)
- Chat widgets (Intercom, Drift)
- Heatmap tools (Hotjar, Crazy Egg)
- Custom tracking scripts
- See **gtm-tags** skill for custom HTML
### Consent Management
- Cookie consent implementation
- Consent Mode v2 (Google)
- Tag blocking based on consent
- See **gtm-best-practices** skill
## GTM vs Other Approaches
### GTM vs Hardcoded Tags
**Hardcoded Tags** (Traditional Approach):
- Tags embedded directly in HTML/JavaScript
- Requires developer for every change
- No version control
- Difficult to debug
- Slow to implement changes
**GTM** (Tag Management):
- Tags managed in GTM interface
- No code changes for tag updates
- Built-in version control and rollback
- Preview & debug mode
- Fast implementation (minutes vs weeks)
**When to use hardcoded**: Very simple sites, critical tags that must never change, single tag with no management needs
**When to use GTM**: Most websites, multiple tags, frequent tag changes, marketing/analytics tags
### GTM vs Google Analytics 4 Direct
- GTM provides flexibility to add/modify GA4 without code changes
- GTM allows multiple marketing tags beyond just GA4
- GA4 can be implemented without GTM (direct script), but less flexible
- Recommendation: Use GTM for GA4 unless extremely simple use case
## Getting Started with GTM
### 1. Create GTM Account & Container
- Sign up at tagmanager.google.com
- Create account (organization level)
- Create container (website/app level)
- See **gtm-setup** skill for detailed setup
### 2. Install GTM Container
- Copy GTM snippet
- Add to `<head>` and `<body>` of all pages
- Verify installation with Preview mode
- See **gtm-setup** skill for installation
### 3. Set Up Basic Tags
- Enable built-in variables
- Create GA4 configuration tag
- Create page view triggers
- Test in Preview mode
- See **gtm-tags** and **gtm-triggers** skills
### 4. Implement Data Layer (if needed)
- Plan data layer structure
- Implement dataLayer.push() calls
- Create data layer variables
- See **gtm-datalayer** skill
### 5. Test & Publish
- Use Preview mode to test
- Verify tags fire correctly
- Check data in analytics platforms
- Create version and publish
- See **gtm-debugging** skill
## GTM Terminology
**Auto-Event Variables** - Built-in variables for click, form, scroll events
**Built-in Variables** - Pre-configured variables (Page URL, Referrer, etc.)
**Community Template Gallery** - Shared tag/variable templates
**Container ID** - Unique ID for your GTM container (GTM-XXXXXX)
**Debug Mode** - GTM Preview mode for testing
**Firing Trigger** - Trigger that causes tag to fire
**Lookup Table** - Variable that maps inputs to outputs
**Preview Mode** - Testing mode to debug GTM before publishing
**Tag Sequencing** - Control order of tag firing
**User-Defined Variable** - Custom variable you create
**Workspace** - Development environment for making changes
## Routing to Specialized Skills
Based on your specific GTM need, use these specialized skills:
**Container Setup & Installation**
→ Use **gtm-setup** skill
- Creating containers
- Installing GTM snippet
- Workspace management
- Environment configuration
**Tag Configuration**
→ Use **gtm-tags** skill
- Creating GA4, Google Ads, marketing tags
- Custom HTML tags
- Tag settings and firing priority
**Trigger Setup**
→ Use **gtm-triggers** skill
- Page view, click, form triggers
- Custom event triggers
- Trigger conditions and RegEx
**Variable Configuration**
→ Use **gtm-variables** skill
- Data layer variables
- Custom JavaScript variables
- Built-in variables
**Data Layer Implementation**
→ Use **gtm-datalayer** skill
- Data layer structure
- E-commerce tracking
- Custom events
- SPA patterns
**Debugging & Testing**
→ Use **gtm-debugging** skill
- Preview mode
- Tag Assistant
- Troubleshooting tags not firing
**Best Practices & Optimization**
→ Use **gtm-best-practices** skill
- Naming conventions
- Performance optimization
- Security practices
- Privacy compliance
**Custom Template Development**
→ Use **gtm-custom-templates** skill
- Building custom tag templates
- Sandboxed JavaScript
- Template publishing
**API & Automation**
→ Use **gtm-api** skill
- GTM API v2
- Programmatic container management
- Automation scripts
## Common Questions
**Q: Do I need GTM if I only use Google Analytics?**
A: GTM is recommended even for GA-only setups because it provides flexibility to modify tracking without code changes, easier debugging, and future-proofing for additional tags.
**Q: Does GTM slow down my website?**
A: GTM loads asynchronously and typically has minimal impact. Proper implementation with optimized tags can actually improve performance vs hardcoded tags.
**Q: Can I use GTM on a single-page application (SPA)?**
A: Yes! Use History Change triggers for route changes and implement data layer pushes for virtual page views. See **gtm-datalayer** and **gtm-triggers** skills.
**Q: How do I test GTM without affecting production data?**
A: Use Preview mode to test before publishing, use development environments, configure filters in analytics platforms to exclude test traffic.
**Q: Can multiple people work on GTM at once?**
A: Yes, use Workspaces to allow simultaneous development. Each person works in their own workspace and merges changes when ready.
**Q: What's the difference between GTM web and server-side containers?**
A: Web containers run in the browser (client-side), server-side containers run on your server infrastructure for enhanced privacy, first-party data, and performance.
## References
- **references/gtm-overview.md** - Detailed GTM fundamentals and architecture
## Integration with Other Skills
All GTM skills work together for comprehensive GTM implementation:
- **gtm-setup** - Initial container setup
- **gtm-tags** - Tag configuration
- **gtm-triggers** - Trigger configuration
- **gtm-variables** - Variable configuration
- **gtm-datalayer** - Data layer implementation
- **gtm-debugging** - Testing and troubleshooting
- **gtm-best-practices** - Optimization and standards
- **gtm-custom-templates** - Template development
- **gtm-api** - Automation and programmatic access
## Quick Decision Tree
**"I want to..."**
- Install GTM → **gtm-setup**
- Add a tracking tag → **gtm-tags**
- Track clicks or forms → **gtm-triggers**
- Capture dynamic data → **gtm-variables**
- Send custom data → **gtm-datalayer**
- Fix tags not firing → **gtm-debugging**
- Optimize performance → **gtm-best-practices**
- Build custom template → **gtm-custom-templates**
- Automate GTM management → **gtm-api**
- General GTM questions → **gtm-general** (this skill)
## Best Practices
### Planning Your Implementation
1. **Define tracking requirements** - What data do you need?
2. **Plan data layer structure** - How will data be passed?
3. **Choose container type** - Web, mobile, or server-side?
4. **Set up environments** - Development, staging, production
5. **Establish naming conventions** - Consistent tag/trigger/variable names
6. **Document your setup** - Version notes, workspace purposes
7. **Train your team** - Ensure everyone understands GTM workflows
### Ongoing Management
- Test all changes in Preview mode before publishing
- Use descriptive version notes when publishing
- Regular container audits to remove unused elements
- Monitor tag performance and page load impact
- Keep security and privacy top of mind
- Stay updated on GTM new features and best practices
See **gtm-best-practices** skill for detailed guidance.

View File

@@ -0,0 +1,59 @@
# About Google Tag Manager
**Source**: https://developers.google.com/tag-platform/tag-manager
**Extracted**: 2025-01-09
Google Tag Manager is a tag management system that lets you configure and deploy tags on your website or mobile app, from an easy-to-use web interface. You can use Tag Manager to optimize your tag deployment, troubleshoot configuration errors, and modify tags that are already deployed.
## Why Use Google Tag Manager
Here are some reasons to use Tag Manager:
- Support for tag organization.
- Version control.
- Support for multiple tag types, including the Google tag.
- Community-developed tag templates.
- Enterprise collaboration.
- Security features.
## Deploy for Web Pages
Use Tag Manager to manage tags (such as measurement and marketing optimization JavaScript tags) on your site. Without editing your site code, use Tag Manager to add and update Google Ads, Google Analytics, Floodlight, and third-party tags.
**Related:** [Get started for websites](https://developers.google.com/tag-platform/tag-manager/web)
## Deploy for Mobile Apps
Use Google Tag Manager to manage analytics and advertising tools in your apps without having to rebuild and resubmit the applications' binaries to app marketplaces.
**Related:**
- [Get started for Android](https://developers.google.com/tag-platform/tag-manager/android/v5)
- [Get started for iOS](https://developers.google.com/tag-platform/tag-manager/ios/v5)
## Server-Side Tagging
Server-Side Tagging allows you to move tag code off of your website or app and into the Cloud. Server-Side Tagging can help you improve the performance and security of your website or mobile app while serving all dependent assets from your own domain.
**Related:** [Get started with Server-Side Tagging](https://developers.google.com/tag-platform/tag-manager/server-side)
## Create Custom Templates
Build your own tag and variable templates in Tag Manager. Submit templates to the Community Template Gallery and make them available worldwide.
**Related:**
- [Quick start guide](https://developers.google.com/tag-platform/tag-manager/templates)
- [Submit templates to the Community Template Gallery](https://developers.google.com/tag-platform/tag-manager/templates/gallery)
## Automate Configuration with the REST API
The Google Tag Manager API provides access to Tag Manager configuration data for an authorized user. Use the API to manage accounts, containers and container versions, tags, rules, triggers, variables, and user permissions.
**Related:** [Get started with the REST API](https://developers.google.com/tag-platform/tag-manager/api/v2/devguide)
## Additional Resources
For more information about Tag Manager features and benefits, visit the following resources:
- [Product site](https://marketingplatform.google.com/about/tag-manager/)
- [Help center](https://support.google.com/tagmanager/)
- [Help community](https://support.google.com/tagmanager/community)

64
skills/gtm-setup/SKILL.md Normal file
View File

@@ -0,0 +1,64 @@
---
name: gtm-setup
description: Expert guidance for Google Tag Manager container setup, installation, account management, workspaces, environments, and version publishing. Use when setting up new GTM containers, installing GTM snippets, managing workspaces, configuring environments, or publishing GTM versions.
---
# GTM Container Setup & Management
## Overview
This skill provides expertise for setting up and managing Google Tag Manager containers, including installation, workspace management, and deployment workflows.
## When to Use This Skill
Invoke this skill when:
- Setting up a new GTM container (web, mobile, server-side)
- Installing GTM snippet code
- Managing workspaces for different projects
- Configuring environments (Development, Staging, Production)
- Publishing GTM versions
- Managing container permissions and user access
- Setting up multiple containers on one site
## Container Types
### Web Containers
- Install GTM snippet in `<head>` and `<body>`
- Configure container for single-page applications (SPAs)
- Set up multiple containers on one site
- Manage container permissions and user access
### Server-Side Containers
- Deploy to Cloudflare Workers, Google Cloud, or other platforms
- Configure server-side clients and tags
- Set up custom tag templates for server endpoints
- Implement first-party data collection
### Mobile Containers
- Configure Firebase integration
- Set up mobile-specific triggers and variables
## Workspace Management
- Use workspaces for different projects
- Create versions with detailed notes
- Compare versions and test in different environments
- Maintain version history and rollback capability
## Publishing Workflow
1. Create changes in workspace
2. Test in Preview mode
3. Create version with detailed notes
4. Publish to appropriate environment
5. Verify deployment
## References
- **references/gtm-overview.md** - GTM fundamentals, architecture, account structure
## Integration with Other Skills
- **gtm-general** - General GTM guidance and concepts
- **gtm-tags** - Configure tags for tracking
- **gtm-triggers** - Set up triggers for tags
- **gtm-variables** - Create variables for dynamic data
- **gtm-debugging** - Debug and test your GTM setup
- **gtm-best-practices** - Follow GTM implementation best practices
- **gtm-datalayer** - Implement data layer for tracking
- **gtm-custom-templates** - Build custom templates
- **gtm-api** - Programmatic container management

View File

@@ -0,0 +1,59 @@
# About Google Tag Manager
**Source**: https://developers.google.com/tag-platform/tag-manager
**Extracted**: 2025-01-09
Google Tag Manager is a tag management system that lets you configure and deploy tags on your website or mobile app, from an easy-to-use web interface. You can use Tag Manager to optimize your tag deployment, troubleshoot configuration errors, and modify tags that are already deployed.
## Why Use Google Tag Manager
Here are some reasons to use Tag Manager:
- Support for tag organization.
- Version control.
- Support for multiple tag types, including the Google tag.
- Community-developed tag templates.
- Enterprise collaboration.
- Security features.
## Deploy for Web Pages
Use Tag Manager to manage tags (such as measurement and marketing optimization JavaScript tags) on your site. Without editing your site code, use Tag Manager to add and update Google Ads, Google Analytics, Floodlight, and third-party tags.
**Related:** [Get started for websites](https://developers.google.com/tag-platform/tag-manager/web)
## Deploy for Mobile Apps
Use Google Tag Manager to manage analytics and advertising tools in your apps without having to rebuild and resubmit the applications' binaries to app marketplaces.
**Related:**
- [Get started for Android](https://developers.google.com/tag-platform/tag-manager/android/v5)
- [Get started for iOS](https://developers.google.com/tag-platform/tag-manager/ios/v5)
## Server-Side Tagging
Server-Side Tagging allows you to move tag code off of your website or app and into the Cloud. Server-Side Tagging can help you improve the performance and security of your website or mobile app while serving all dependent assets from your own domain.
**Related:** [Get started with Server-Side Tagging](https://developers.google.com/tag-platform/tag-manager/server-side)
## Create Custom Templates
Build your own tag and variable templates in Tag Manager. Submit templates to the Community Template Gallery and make them available worldwide.
**Related:**
- [Quick start guide](https://developers.google.com/tag-platform/tag-manager/templates)
- [Submit templates to the Community Template Gallery](https://developers.google.com/tag-platform/tag-manager/templates/gallery)
## Automate Configuration with the REST API
The Google Tag Manager API provides access to Tag Manager configuration data for an authorized user. Use the API to manage accounts, containers and container versions, tags, rules, triggers, variables, and user permissions.
**Related:** [Get started with the REST API](https://developers.google.com/tag-platform/tag-manager/api/v2/devguide)
## Additional Resources
For more information about Tag Manager features and benefits, visit the following resources:
- [Product site](https://marketingplatform.google.com/about/tag-manager/)
- [Help center](https://support.google.com/tagmanager/)
- [Help community](https://support.google.com/tagmanager/community)

168
skills/gtm-tags/SKILL.md Normal file
View File

@@ -0,0 +1,168 @@
---
name: gtm-tags
description: Expert guidance for configuring Google Tag Manager tags including GA4 configuration tags, GA4 event tags, Google Ads conversion tracking, Google Ads remarketing, custom HTML tags, third-party marketing tags (Facebook Pixel, LinkedIn Insight, TikTok Pixel), community template tags, tag sequencing, tag firing priority, consent settings, and tag timeout configuration. Use when creating tags, configuring GA4 tags, setting up Google Ads tracking, implementing marketing pixels, working with custom HTML, configuring tag firing order, setting up tag dependencies, implementing consent mode for tags, or troubleshooting tag configuration issues.
---
# GTM Tags Configuration
## Overview
Expert guidance for configuring all types of tags in Google Tag Manager, from Google Analytics 4 and Google Ads to custom HTML and third-party marketing platforms.
## When to Use This Skill
Invoke this skill when:
- Creating or configuring GTM tags of any type
- Setting up GA4 Configuration or Event tags
- Implementing Google Ads conversion tracking or remarketing
- Adding third-party marketing tags (Facebook, LinkedIn, TikTok, etc.)
- Writing custom HTML tags
- Configuring tag firing priority and sequencing
- Setting up tag timeout or consent settings
- Implementing tag dependencies or firing conditions
- Troubleshooting why a tag isn't configured correctly
- Optimizing tag configuration for performance
## Common Tag Types
### Google Analytics 4 Tags
- **GA4 Configuration Tag** - Base tag for GA4 tracking
- **GA4 Event Tag** - Custom events and conversions
- Event parameters and user properties
- E-commerce events (purchase, add_to_cart, view_item, etc.)
- Debug mode configuration
### Google Ads Tags
- **Conversion Tracking** - Track conversions and assign values
- **Remarketing** - Build audiences for retargeting
- Enhanced conversions setup
- Conversion linker tag
### Marketing Platform Tags
- Facebook Pixel (Meta Pixel)
- LinkedIn Insight Tag
- TikTok Pixel
- Twitter/X Pixel
- Pinterest Tag
- Snapchat Pixel
### Custom Tags
- Custom HTML tags for any JavaScript
- Custom Image tags
- Community Template Gallery tags
## Tag Configuration Settings
### Core Settings
- Tag Type selection
- Configuration fields (varies by tag type)
- Trigger assignment (when the tag fires)
- Exception configuration (when NOT to fire)
### Advanced Settings
- **Tag Firing Priority** - Control execution order (higher numbers fire first)
- **Tag Sequencing** - Setup tags that must fire before/after this tag
- **Tag Firing Options** - Once per event, once per page, unlimited
- **Consent Settings** - Require consent for tag firing
- **Tag Scheduling** - Set start/end dates for tag activity
### Performance Settings
- **Timeout** - Maximum time to wait for tag to complete
- **Advanced Tag Firing** - Fire in DOM Ready, Page View, or Window Loaded
## Common Workflows
### Create a GA4 Event Tag
1. Click "New Tag" in GTM workspace
2. Select "Google Analytics: GA4 Event" tag type
3. Enter Measurement ID or reference GA4 Configuration tag
4. Set Event Name (e.g., "form_submit")
5. Add Event Parameters as needed
6. Select trigger (when to fire the tag)
7. Save and test in Preview mode
### Set Up Google Ads Conversion Tag
1. Create new tag → Google Ads Conversion Tracking
2. Enter Conversion ID and Conversion Label from Google Ads
3. Set conversion value (static or variable)
4. Configure transaction ID for deduplication
5. Assign trigger (e.g., purchase completion page)
6. Test and publish
### Add Custom HTML Tag
1. Create new tag → Custom HTML
2. Paste JavaScript code in HTML field
3. Ensure code is properly formatted
4. Consider security implications
5. Set appropriate trigger
6. Test thoroughly before publishing
### Configure Tag Sequencing
1. Open tag that should fire first
2. Go to Advanced Settings → Tag Sequencing
3. Add "Setup Tag" (fires before this tag)
4. Add "Cleanup Tag" (fires after this tag)
5. Configure "pause" settings if needed
6. Test firing order in Preview mode
## Best Practices
### Tag Organization
- Use clear, consistent naming: `[Platform] - [Type] - [Description]`
- Example: `GA4 - Event - Form Submit`, `Google Ads - Conversion - Purchase`
- Group related tags in folders
- Document complex configurations in tag notes
### Performance Optimization
- Prefer native tag templates over custom HTML
- Minimize custom JavaScript in tags
- Set appropriate timeouts (avoid overly long waits)
- Remove unused tags regularly
- Consolidate similar tags when possible
### Security & Privacy
- Vet all custom HTML code carefully
- Review third-party tag templates before use
- Implement consent mode for privacy compliance
- Avoid sending PII (Personally Identifiable Information)
- Use tag permissions to control access
## References
- **references/tags.md** - Comprehensive tag configuration guide with all tag types, parameters, and advanced configuration
- **references/google-rew-regular-expressions-syntax.txt** - RegEx syntax for tag firing conditions
Search reference files for specific topics:
```bash
grep -r "GA4 Event" references/
grep -r "consent" references/
grep -r "Custom HTML" references/
```
## Integration with Other Skills
- **gtm-triggers** - Configure when tags fire
- **gtm-variables** - Use variables in tag configuration
- **gtm-debugging** - Debug tags that aren't firing correctly
- **gtm-setup** - Container setup and workspace management
- **gtm-datalayer** - Advanced data layer implementation for event tags
- **gtm-best-practices** - Tag naming conventions and optimization strategies
- **gtm-custom-templates** - Build custom tag templates
## Quick Reference
### Common Tag Types Quick List
- GA4 Configuration
- GA4 Event
- Google Ads Conversion Tracking
- Google Ads Remarketing
- Conversion Linker
- Custom HTML
- Custom Image
- Community Template (various)
### Tag Firing Priority
- Higher number = fires first (e.g., 100 fires before 50)
- Default priority = no value set
- Use for ensuring setup tags fire before tracking tags
### Consent Settings
- **No additional consent required** - Tag fires immediately
- **Require additional consent for tag to fire** - Block until consent given
- Map to consent types (analytics_storage, ad_storage, etc.)

View File

@@ -0,0 +1,462 @@
RE2 regular expression syntax reference
-------------------------­-------­-----
Single characters:
. any character, possibly including newline (s=true)
[xyz] character class
[^xyz] negated character class
\d Perl character class
\D negated Perl character class
[[:alpha:]] ASCII character class
[[:^alpha:]] negated ASCII character class
\pN Unicode character class (one-letter name)
\p{Greek} Unicode character class
\PN negated Unicode character class (one-letter name)
\P{Greek} negated Unicode character class
Composites:
xy «x» followed by «y»
x|y «x» or «y» (prefer «x»)
Repetitions:
x* zero or more «x», prefer more
x+ one or more «x», prefer more
x? zero or one «x», prefer one
x{n,m} «n» or «n»+1 or ... or «m» «x», prefer more
x{n,} «n» or more «x», prefer more
x{n} exactly «n» «x»
x*? zero or more «x», prefer fewer
x+? one or more «x», prefer fewer
x?? zero or one «x», prefer zero
x{n,m}? «n» or «n»+1 or ... or «m» «x», prefer fewer
x{n,}? «n» or more «x», prefer fewer
x{n}? exactly «n» «x»
x{} (== x*) NOT SUPPORTED vim
x{-} (== x*?) NOT SUPPORTED vim
x{-n} (== x{n}?) NOT SUPPORTED vim
x= (== x?) NOT SUPPORTED vim
Implementation restriction: The counting forms «x{n,m}», «x{n,}», and «x{n}»
reject forms that create a minimum or maximum repetition count above 1000.
Unlimited repetitions are not subject to this restriction.
Possessive repetitions:
x*+ zero or more «x», possessive NOT SUPPORTED
x++ one or more «x», possessive NOT SUPPORTED
x?+ zero or one «x», possessive NOT SUPPORTED
x{n,m}+ «n» or ... or «m» «x», possessive NOT SUPPORTED
x{n,}+ «n» or more «x», possessive NOT SUPPORTED
x{n}+ exactly «n» «x», possessive NOT SUPPORTED
Grouping:
(re) numbered capturing group (submatch)
(?P<name>re) named & numbered capturing group (submatch)
(?<name>re) named & numbered capturing group (submatch)
(?'name're) named & numbered capturing group (submatch) NOT SUPPORTED
(?:re) non-capturing group
(?flags) set flags within current group; non-capturing
(?flags:re) set flags during re; non-capturing
(?#text) comment NOT SUPPORTED
(?|x|y|z) branch numbering reset NOT SUPPORTED
(?>re) possessive match of «re» NOT SUPPORTED
re@> possessive match of «re» NOT SUPPORTED vim
%(re) non-capturing group NOT SUPPORTED vim
Flags:
i case-insensitive (default false)
m multi-line mode: «^» and «$» match begin/end line in addition to begin/end text (default false)
s let «.» match «\n» (default false)
U ungreedy: swap meaning of «x*» and «x*?», «x+» and «x+?», etc (default false)
Flag syntax is «xyz» (set) or «-xyz» (clear) or «xy-z» (set «xy», clear «z»).
Empty strings:
^ at beginning of text or line («m»=true)
$ at end of text (like «\z» not «\Z») or line («m»=true)
\A at beginning of text
\b at ASCII word boundary («\w» on one side and «\W», «\A», or «\z» on the other)
\B not at ASCII word boundary
\G at beginning of subtext being searched NOT SUPPORTED pcre
\G at end of last match NOT SUPPORTED perl
\Z at end of text, or before newline at end of text NOT SUPPORTED
\z at end of text
(?=re) before text matching «re» NOT SUPPORTED
(?!re) before text not matching «re» NOT SUPPORTED
(?<=re) after text matching «re» NOT SUPPORTED
(?<!re) after text not matching «re» NOT SUPPORTED
re& before text matching «re» NOT SUPPORTED vim
re@= before text matching «re» NOT SUPPORTED vim
re@! before text not matching «re» NOT SUPPORTED vim
re@<= after text matching «re» NOT SUPPORTED vim
re@<! after text not matching «re» NOT SUPPORTED vim
\zs sets start of match (= \K) NOT SUPPORTED vim
\ze sets end of match NOT SUPPORTED vim
\%^ beginning of file NOT SUPPORTED vim
\%$ end of file NOT SUPPORTED vim
\%V on screen NOT SUPPORTED vim
\%# cursor position NOT SUPPORTED vim
\%'m mark «m» position NOT SUPPORTED vim
\%23l in line 23 NOT SUPPORTED vim
\%23c in column 23 NOT SUPPORTED vim
\%23v in virtual column 23 NOT SUPPORTED vim
Escape sequences:
\a bell (== \007)
\f form feed (== \014)
\t horizontal tab (== \011)
\n newline (== \012)
\r carriage return (== \015)
\v vertical tab character (== \013)
\* literal «*», for any punctuation character «*»
\123 octal character code (up to three digits)
\x7F hex character code (exactly two digits)
\x{10FFFF} hex character code
\C match a single byte even in UTF-8 mode
\Q...\E literal text «...» even if «...» has punctuation
\1 backreference NOT SUPPORTED
\b backspace NOT SUPPORTED (use «\010»)
\cK control char ^K NOT SUPPORTED (use «\001» etc)
\e escape NOT SUPPORTED (use «\033»)
\g1 backreference NOT SUPPORTED
\g{1} backreference NOT SUPPORTED
\g{+1} backreference NOT SUPPORTED
\g{-1} backreference NOT SUPPORTED
\g{name} named backreference NOT SUPPORTED
\g<name> subroutine call NOT SUPPORTED
\g'name' subroutine call NOT SUPPORTED
\k<name> named backreference NOT SUPPORTED
\k'name' named backreference NOT SUPPORTED
\lX lowercase «X» NOT SUPPORTED
\ux uppercase «x» NOT SUPPORTED
\L...\E lowercase text «...» NOT SUPPORTED
\K reset beginning of «$0» NOT SUPPORTED
\N{name} named Unicode character NOT SUPPORTED
\R line break NOT SUPPORTED
\U...\E upper case text «...» NOT SUPPORTED
\X extended Unicode sequence NOT SUPPORTED
\%d123 decimal character 123 NOT SUPPORTED vim
\%xFF hex character FF NOT SUPPORTED vim
\%o123 octal character 123 NOT SUPPORTED vim
\%u1234 Unicode character 0x1234 NOT SUPPORTED vim
\%U12345678 Unicode character 0x12345678 NOT SUPPORTED vim
Character class elements:
x single character
A-Z character range (inclusive)
\d Perl character class
[:foo:] ASCII character class «foo»
\p{Foo} Unicode character class «Foo»
\pF Unicode character class «F» (one-letter name)
Named character classes as character class elements:
[\d] digits (== \d)
[^\d] not digits (== \D)
[\D] not digits (== \D)
[^\D] not not digits (== \d)
[[:name:]] named ASCII class inside character class (== [:name:])
[^[:name:]] named ASCII class inside negated character class (== [:^name:])
[\p{Name}] named Unicode property inside character class (== \p{Name})
[^\p{Name}] named Unicode property inside negated character class (== \P{Name})
Perl character classes (all ASCII-only):
\d digits (== [0-9])
\D not digits (== [^0-9])
\s whitespace (== [\t\n\f\r ])
\S not whitespace (== [^\t\n\f\r ])
\w word characters (== [0-9A-Za-z_])
\W not word characters (== [^0-9A-Za-z_])
\h horizontal space NOT SUPPORTED
\H not horizontal space NOT SUPPORTED
\v vertical space NOT SUPPORTED
\V not vertical space NOT SUPPORTED
ASCII character classes:
[[:alnum:]] alphanumeric (== [0-9A-Za-z])
[[:alpha:]] alphabetic (== [A-Za-z])
[[:ascii:]] ASCII (== [\x00-\x7F])
[[:blank:]] blank (== [\t ])
[[:cntrl:]] control (== [\x00-\x1F\x7F])
[[:digit:]] digits (== [0-9])
[[:graph:]] graphical (== [!-~] == [A-Za-z0-9!"#$%&'()*+,\-./:;<=>?@[\\\]^_`{|}~])
[[:lower:]] lower case (== [a-z])
[[:print:]] printable (== [ -~] == [ [:graph:]])
[[:punct:]] punctuation (== [!-/:-@[-`{-~])
[[:space:]] whitespace (== [\t\n\v\f\r ])
[[:upper:]] upper case (== [A-Z])
[[:word:]] word characters (== [0-9A-Za-z_])
[[:xdigit:]] hex digit (== [0-9A-Fa-f])
Unicode character class names--general category:
C other
Cc control
Cf format
Cn unassigned code points NOT SUPPORTED
Co private use
Cs surrogate
L letter
LC cased letter NOT SUPPORTED
L& cased letter NOT SUPPORTED
Ll lowercase letter
Lm modifier letter
Lo other letter
Lt titlecase letter
Lu uppercase letter
M mark
Mc spacing mark
Me enclosing mark
Mn non-spacing mark
N number
Nd decimal number
Nl letter number
No other number
P punctuation
Pc connector punctuation
Pd dash punctuation
Pe close punctuation
Pf final punctuation
Pi initial punctuation
Po other punctuation
Ps open punctuation
S symbol
Sc currency symbol
Sk modifier symbol
Sm math symbol
So other symbol
Z separator
Zl line separator
Zp paragraph separator
Zs space separator
Unicode character class names--scripts:
Adlam
Ahom
Anatolian_Hieroglyphs
Arabic
Armenian
Avestan
Balinese
Bamum
Bassa_Vah
Batak
Bengali
Bhaiksuki
Bopomofo
Brahmi
Braille
Buginese
Buhid
Canadian_Aboriginal
Carian
Caucasian_Albanian
Chakma
Cham
Cherokee
Chorasmian
Common
Coptic
Cuneiform
Cypriot
Cypro_Minoan
Cyrillic
Deseret
Devanagari
Dives_Akuru
Dogra
Duployan
Egyptian_Hieroglyphs
Elbasan
Elymaic
Ethiopic
Georgian
Glagolitic
Gothic
Grantha
Greek
Gujarati
Gunjala_Gondi
Gurmukhi
Han
Hangul
Hanifi_Rohingya
Hanunoo
Hatran
Hebrew
Hiragana
Imperial_Aramaic
Inherited
Inscriptional_Pahlavi
Inscriptional_Parthian
Javanese
Kaithi
Kannada
Katakana
Kawi
Kayah_Li
Kharoshthi
Khitan_Small_Script
Khmer
Khojki
Khudawadi
Lao
Latin
Lepcha
Limbu
Linear_A
Linear_B
Lisu
Lycian
Lydian
Mahajani
Makasar
Malayalam
Mandaic
Manichaean
Marchen
Masaram_Gondi
Medefaidrin
Meetei_Mayek
Mende_Kikakui
Meroitic_Cursive
Meroitic_Hieroglyphs
Miao
Modi
Mongolian
Mro
Multani
Myanmar
Nabataean
Nag_Mundari
Nandinagari
New_Tai_Lue
Newa
Nko
Nushu
Nyiakeng_Puachue_Hmong
Ogham
Ol_Chiki
Old_Hungarian
Old_Italic
Old_North_Arabian
Old_Permic
Old_Persian
Old_Sogdian
Old_South_Arabian
Old_Turkic
Old_Uyghur
Oriya
Osage
Osmanya
Pahawh_Hmong
Palmyrene
Pau_Cin_Hau
Phags_Pa
Phoenician
Psalter_Pahlavi
Rejang
Runic
Samaritan
Saurashtra
Sharada
Shavian
Siddham
SignWriting
Sinhala
Sogdian
Sora_Sompeng
Soyombo
Sundanese
Syloti_Nagri
Syriac
Tagalog
Tagbanwa
Tai_Le
Tai_Tham
Tai_Viet
Takri
Tamil
Tangsa
Tangut
Telugu
Thaana
Thai
Tibetan
Tifinagh
Tirhuta
Toto
Ugaritic
Vai
Vithkuqi
Wancho
Warang_Citi
Yezidi
Yi
Zanabazar_Square
Vim character classes:
\i identifier character NOT SUPPORTED vim
\I «\i» except digits NOT SUPPORTED vim
\k keyword character NOT SUPPORTED vim
\K «\k» except digits NOT SUPPORTED vim
\f file name character NOT SUPPORTED vim
\F «\f» except digits NOT SUPPORTED vim
\p printable character NOT SUPPORTED vim
\P «\p» except digits NOT SUPPORTED vim
\s whitespace character (== [ \t]) NOT SUPPORTED vim
\S non-white space character (== [^ \t]) NOT SUPPORTED vim
\d digits (== [0-9]) vim
\D not «\d» vim
\x hex digits (== [0-9A-Fa-f]) NOT SUPPORTED vim
\X not «\x» NOT SUPPORTED vim
\o octal digits (== [0-7]) NOT SUPPORTED vim
\O not «\o» NOT SUPPORTED vim
\w word character vim
\W not «\w» vim
\h head of word character NOT SUPPORTED vim
\H not «\h» NOT SUPPORTED vim
\a alphabetic NOT SUPPORTED vim
\A not «\a» NOT SUPPORTED vim
\l lowercase NOT SUPPORTED vim
\L not lowercase NOT SUPPORTED vim
\u uppercase NOT SUPPORTED vim
\U not uppercase NOT SUPPORTED vim
\_x «\x» plus newline, for any «x» NOT SUPPORTED vim
Vim flags:
\c ignore case NOT SUPPORTED vim
\C match case NOT SUPPORTED vim
\m magic NOT SUPPORTED vim
\M nomagic NOT SUPPORTED vim
\v verymagic NOT SUPPORTED vim
\V verynomagic NOT SUPPORTED vim
\Z ignore differences in Unicode combining characters NOT SUPPORTED vim
Magic:
(?{code}) arbitrary Perl code NOT SUPPORTED perl
(??{code}) postponed arbitrary Perl code NOT SUPPORTED perl
(?n) recursive call to regexp capturing group «n» NOT SUPPORTED
(?+n) recursive call to relative group «+n» NOT SUPPORTED
(?-n) recursive call to relative group «-n» NOT SUPPORTED
(?C) PCRE callout NOT SUPPORTED pcre
(?R) recursive call to entire regexp (== (?0)) NOT SUPPORTED
(?&name) recursive call to named group NOT SUPPORTED
(?P=name) named backreference NOT SUPPORTED
(?P>name) recursive call to named group NOT SUPPORTED
(?(cond)true|false) conditional branch NOT SUPPORTED
(?(cond)true) conditional branch NOT SUPPORTED
(*ACCEPT) make regexps more like Prolog NOT SUPPORTED
(*COMMIT) NOT SUPPORTED
(*F) NOT SUPPORTED
(*FAIL) NOT SUPPORTED
(*MARK) NOT SUPPORTED
(*PRUNE) NOT SUPPORTED
(*SKIP) NOT SUPPORTED
(*THEN) NOT SUPPORTED
(*ANY) set newline convention NOT SUPPORTED
(*ANYCRLF) NOT SUPPORTED
(*CR) NOT SUPPORTED
(*CRLF) NOT SUPPORTED
(*LF) NOT SUPPORTED
(*BSR_ANYCRLF) set \R convention NOT SUPPORTED pcre
(*BSR_UNICODE) NOT SUPPORTED pcre

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,271 @@
---
name: gtm-triggers
description: Expert guidance for configuring Google Tag Manager triggers including page view triggers, click triggers (all elements, just links), form submission triggers, scroll depth tracking, element visibility triggers, video triggers (YouTube), custom event triggers, timer triggers, history change triggers for SPAs, JavaScript error triggers, trigger conditions, RegEx patterns, trigger exceptions, auto-event variables, and combining multiple trigger conditions. Use when creating triggers, setting up click tracking, configuring form submit tracking, implementing scroll tracking, working with custom events, debugging trigger conditions, using RegEx in triggers, setting trigger exceptions, or troubleshooting why triggers aren't firing.
---
# GTM Triggers Configuration
## Overview
Expert guidance for configuring all types of triggers in Google Tag Manager that control when tags fire, from simple page views to complex conditional triggers with RegEx patterns.
## When to Use This Skill
Invoke this skill when:
- Creating or configuring GTM triggers
- Setting up page view or DOM-based triggers
- Implementing click tracking (buttons, links, elements)
- Configuring form submission tracking
- Setting up scroll depth or element visibility triggers
- Working with custom event triggers from data layer
- Creating timer or history change triggers
- Using RegEx patterns in trigger conditions
- Setting up trigger exceptions (when NOT to fire)
- Combining multiple conditions in triggers
- Debugging why triggers aren't firing
- Optimizing trigger performance
## Trigger Types
### Pageview Triggers
- **Page View** - Fires on every page load (including virtual pages)
- **DOM Ready** - Fires when DOM is ready (before images load)
- **Window Loaded** - Fires when page fully loads (including images)
Use cases:
- Page View: Most common for tracking page views
- DOM Ready: Fire tags before full page load for performance
- Window Loaded: When you need all page resources loaded
### Click Triggers
- **All Elements** - Track clicks on any element (buttons, divs, images, etc.)
- **Just Links** - Track clicks only on `<a>` tags
Auto-Event Variables available:
- Click Element, Click Classes, Click ID
- Click URL, Click Text
- Click Target
### Form Triggers
- **Form Submission** - Fires when form is submitted
Auto-Event Variables available:
- Form Element, Form Classes, Form ID
- Form Target, Form URL
- Form Text
### User Engagement Triggers
- **Scroll Depth** - Track when users scroll to specific depths
- Vertical Scroll Depths: 25%, 50%, 75%, 90%, etc.
- Horizontal scrolling also supported
- **Element Visibility** - Fire when element becomes visible
- Minimum visibility percentage
- On-screen duration requirements
- **YouTube Video** - Track video plays, pauses, progress
- Requires YouTube videos to have enablejsapi=1
### Custom Event Triggers
- **Custom Event** - Fire when specific data layer event occurs
- Event name must match `dataLayer.push({'event': 'event_name'})`
- Most flexible trigger type for custom implementations
### Timer Triggers
- **Timer** - Fire repeatedly at intervals
- Set interval (milliseconds)
- Set limit on number of times to fire
- Use for tracking time on page, polling, etc.
### History Triggers
- **History Change** - Fire on URL changes without page reload
- Essential for Single Page Applications (SPAs)
- Tracks pushState, replaceState, and hash changes
### Other Triggers
- **JavaScript Error** - Fire when JavaScript errors occur
- **Trigger Group** - Combine multiple triggers with AND logic
- **Window Resize** - Fire when browser window resizes (custom via Custom HTML)
## Trigger Configuration
### Basic Configuration
1. **Trigger Type** - Select the type of trigger
2. **Trigger Name** - Use clear naming convention
3. **Trigger Conditions** - Define when to fire
4. **Trigger Exceptions** - Define when NOT to fire
### Trigger Conditions (Filters)
Combine multiple conditions with AND/OR logic:
**Condition Structure:**
- Variable (e.g., Click URL, Page Path)
- Operator (equals, contains, matches RegEx, etc.)
- Value (static text or variable)
**Common Operators:**
- `equals` - Exact match
- `contains` - Substring match
- `matches RegEx` - Pattern matching
- `starts with` - Prefix match
- `ends with` - Suffix match
- `less than` / `greater than` - Numeric comparison
- `CSS selector` - Match element with selector
**Example Conditions:**
```
Click URL contains /checkout
Page Path equals /thank-you
Click Classes matches RegEx ^btn-primary$
Form ID equals contact-form
```
### Trigger Exceptions
Prevent trigger from firing in specific cases:
- Same format as conditions
- Useful for excluding specific pages, elements, or scenarios
**Example:**
Trigger on all clicks EXCEPT:
- Click URL contains /admin
- Click Classes contains no-track
### RegEx in Triggers
Use Regular Expressions for complex pattern matching:
- `.*` - Match any characters
- `^` - Start of string
- `$` - End of string
- `|` - OR operator
- `[a-z]` - Character range
- `\d` - Any digit
**Examples:**
```
Page Path matches RegEx: ^/(products|services)/.*
Click URL matches RegEx: \.(pdf|docx?)$
Custom Event equals: purchase|checkout|lead
```
See references/google-rew-regular-expressions-syntax.txt for complete RegEx syntax.
## Common Workflows
### Create Click Trigger for Specific Button
1. Create new trigger → Click - All Elements
2. Set condition: Click Classes contains "cta-button"
3. Or use: Click ID equals "signup-btn"
4. Test in Preview mode by clicking button
5. Verify in Tags Fired section
### Set Up Form Submission Trigger
1. Create new trigger → Form Submission
2. Set condition: Form ID equals "contact-form"
3. Or use: Page Path equals /contact
4. Set exception if needed (e.g., exclude test forms)
5. Test by submitting form in Preview mode
### Configure Scroll Depth Trigger
1. Create new trigger → Scroll Depth
2. Select Vertical Scroll Depths
3. Choose percentages: 25, 50, 75, 90
4. Set Page Path condition if needed (specific pages only)
5. Test by scrolling on page
### Create Custom Event Trigger
1. Ensure data layer push is implemented: `dataLayer.push({'event': 'add_to_cart'})`
2. Create new trigger → Custom Event
3. Set Event name: add_to_cart
4. Add conditions as needed (e.g., fire only on specific pages)
5. Test in Preview mode, check Data Layer tab
### Set Up History Change Trigger for SPA
1. Create new trigger → History Change
2. Add condition: Page Path matches RegEx (if needed)
3. Test by navigating within SPA
4. Verify trigger fires on URL changes without page reload
## Best Practices
### Trigger Naming
Use consistent format: `[Event Type] - [Description]`
Examples:
- `Click - CTA Button`
- `Page View - Homepage`
- `Form Submit - Contact Form`
- `Custom Event - Add to Cart`
### Trigger Optimization
- Use specific conditions to avoid over-firing
- Set exceptions to exclude unwanted scenarios
- Test thoroughly in Preview mode
- Use built-in variables when possible (faster than custom JS)
- Avoid overly complex RegEx patterns
### Common Pitfalls
- **Click triggers not firing**: Element might be removed before click registers
- Solution: Use "Wait for Tags" or increase timeout
- **Form triggers not firing**: Form submits via AJAX without traditional submit
- Solution: Use custom event trigger instead
- **History triggers over-firing**: Fires on every URL parameter change
- Solution: Add specific Page Path conditions
### Auto-Event Variables
Enable relevant built-in variables for triggers:
- Click triggers: Click Element, Click Classes, Click ID, Click URL, Click Text
- Form triggers: Form Element, Form Classes, Form ID, Form URL, Form Text
- Scroll triggers: Scroll Depth Threshold, Scroll Depth Units
- Video triggers: Video Provider, Video Status, Video URL, Video Title
## References
- **references/triggers.md** - Comprehensive trigger configuration guide with all trigger types, conditions, and advanced patterns
- **references/google-rew-regular-expressions-syntax.txt** - RegEx syntax for trigger conditions
Search reference files for specific topics:
```bash
grep -r "Custom Event" references/
grep -r "scroll depth" references/
grep -r "RegEx" references/
```
## Integration with Other Skills
- **gtm-tags** - Configure tags that use these triggers
- **gtm-variables** - Use variables in trigger conditions
- **gtm-debugging** - Debug triggers that aren't firing
- **gtm-datalayer** - Implement custom events for custom event triggers
- **gtm-setup** - Container setup and built-in variables
- **gtm-best-practices** - Trigger naming conventions and optimization
## Quick Reference
### Trigger Type Selection Guide
- **Simple page tracking**: Page View
- **Button/link clicks**: Click triggers
- **Form submissions**: Form Submission
- **User engagement**: Scroll Depth, Element Visibility
- **Custom implementation**: Custom Event
- **SPA navigation**: History Change
- **Polling/time-based**: Timer
- **Error monitoring**: JavaScript Error
### Common Condition Patterns
```
// Homepage only
Page Path equals /
// All product pages
Page Path starts with /products/
// PDF downloads
Click URL ends with .pdf
// Multiple pages with RegEx
Page Path matches RegEx ^/(about|contact|services)$
// Exclude admin pages
Page Path does not contain /admin/
```
### Debugging Checklist
- [ ] Trigger type is correct for event
- [ ] Trigger conditions are specific enough
- [ ] Built-in variables are enabled
- [ ] No conflicting trigger exceptions
- [ ] Testing in Preview mode
- [ ] Checking Variables tab for condition values

View File

@@ -0,0 +1,462 @@
RE2 regular expression syntax reference
-------------------------­-------­-----
Single characters:
. any character, possibly including newline (s=true)
[xyz] character class
[^xyz] negated character class
\d Perl character class
\D negated Perl character class
[[:alpha:]] ASCII character class
[[:^alpha:]] negated ASCII character class
\pN Unicode character class (one-letter name)
\p{Greek} Unicode character class
\PN negated Unicode character class (one-letter name)
\P{Greek} negated Unicode character class
Composites:
xy «x» followed by «y»
x|y «x» or «y» (prefer «x»)
Repetitions:
x* zero or more «x», prefer more
x+ one or more «x», prefer more
x? zero or one «x», prefer one
x{n,m} «n» or «n»+1 or ... or «m» «x», prefer more
x{n,} «n» or more «x», prefer more
x{n} exactly «n» «x»
x*? zero or more «x», prefer fewer
x+? one or more «x», prefer fewer
x?? zero or one «x», prefer zero
x{n,m}? «n» or «n»+1 or ... or «m» «x», prefer fewer
x{n,}? «n» or more «x», prefer fewer
x{n}? exactly «n» «x»
x{} (== x*) NOT SUPPORTED vim
x{-} (== x*?) NOT SUPPORTED vim
x{-n} (== x{n}?) NOT SUPPORTED vim
x= (== x?) NOT SUPPORTED vim
Implementation restriction: The counting forms «x{n,m}», «x{n,}», and «x{n}»
reject forms that create a minimum or maximum repetition count above 1000.
Unlimited repetitions are not subject to this restriction.
Possessive repetitions:
x*+ zero or more «x», possessive NOT SUPPORTED
x++ one or more «x», possessive NOT SUPPORTED
x?+ zero or one «x», possessive NOT SUPPORTED
x{n,m}+ «n» or ... or «m» «x», possessive NOT SUPPORTED
x{n,}+ «n» or more «x», possessive NOT SUPPORTED
x{n}+ exactly «n» «x», possessive NOT SUPPORTED
Grouping:
(re) numbered capturing group (submatch)
(?P<name>re) named & numbered capturing group (submatch)
(?<name>re) named & numbered capturing group (submatch)
(?'name're) named & numbered capturing group (submatch) NOT SUPPORTED
(?:re) non-capturing group
(?flags) set flags within current group; non-capturing
(?flags:re) set flags during re; non-capturing
(?#text) comment NOT SUPPORTED
(?|x|y|z) branch numbering reset NOT SUPPORTED
(?>re) possessive match of «re» NOT SUPPORTED
re@> possessive match of «re» NOT SUPPORTED vim
%(re) non-capturing group NOT SUPPORTED vim
Flags:
i case-insensitive (default false)
m multi-line mode: «^» and «$» match begin/end line in addition to begin/end text (default false)
s let «.» match «\n» (default false)
U ungreedy: swap meaning of «x*» and «x*?», «x+» and «x+?», etc (default false)
Flag syntax is «xyz» (set) or «-xyz» (clear) or «xy-z» (set «xy», clear «z»).
Empty strings:
^ at beginning of text or line («m»=true)
$ at end of text (like «\z» not «\Z») or line («m»=true)
\A at beginning of text
\b at ASCII word boundary («\w» on one side and «\W», «\A», or «\z» on the other)
\B not at ASCII word boundary
\G at beginning of subtext being searched NOT SUPPORTED pcre
\G at end of last match NOT SUPPORTED perl
\Z at end of text, or before newline at end of text NOT SUPPORTED
\z at end of text
(?=re) before text matching «re» NOT SUPPORTED
(?!re) before text not matching «re» NOT SUPPORTED
(?<=re) after text matching «re» NOT SUPPORTED
(?<!re) after text not matching «re» NOT SUPPORTED
re& before text matching «re» NOT SUPPORTED vim
re@= before text matching «re» NOT SUPPORTED vim
re@! before text not matching «re» NOT SUPPORTED vim
re@<= after text matching «re» NOT SUPPORTED vim
re@<! after text not matching «re» NOT SUPPORTED vim
\zs sets start of match (= \K) NOT SUPPORTED vim
\ze sets end of match NOT SUPPORTED vim
\%^ beginning of file NOT SUPPORTED vim
\%$ end of file NOT SUPPORTED vim
\%V on screen NOT SUPPORTED vim
\%# cursor position NOT SUPPORTED vim
\%'m mark «m» position NOT SUPPORTED vim
\%23l in line 23 NOT SUPPORTED vim
\%23c in column 23 NOT SUPPORTED vim
\%23v in virtual column 23 NOT SUPPORTED vim
Escape sequences:
\a bell (== \007)
\f form feed (== \014)
\t horizontal tab (== \011)
\n newline (== \012)
\r carriage return (== \015)
\v vertical tab character (== \013)
\* literal «*», for any punctuation character «*»
\123 octal character code (up to three digits)
\x7F hex character code (exactly two digits)
\x{10FFFF} hex character code
\C match a single byte even in UTF-8 mode
\Q...\E literal text «...» even if «...» has punctuation
\1 backreference NOT SUPPORTED
\b backspace NOT SUPPORTED (use «\010»)
\cK control char ^K NOT SUPPORTED (use «\001» etc)
\e escape NOT SUPPORTED (use «\033»)
\g1 backreference NOT SUPPORTED
\g{1} backreference NOT SUPPORTED
\g{+1} backreference NOT SUPPORTED
\g{-1} backreference NOT SUPPORTED
\g{name} named backreference NOT SUPPORTED
\g<name> subroutine call NOT SUPPORTED
\g'name' subroutine call NOT SUPPORTED
\k<name> named backreference NOT SUPPORTED
\k'name' named backreference NOT SUPPORTED
\lX lowercase «X» NOT SUPPORTED
\ux uppercase «x» NOT SUPPORTED
\L...\E lowercase text «...» NOT SUPPORTED
\K reset beginning of «$0» NOT SUPPORTED
\N{name} named Unicode character NOT SUPPORTED
\R line break NOT SUPPORTED
\U...\E upper case text «...» NOT SUPPORTED
\X extended Unicode sequence NOT SUPPORTED
\%d123 decimal character 123 NOT SUPPORTED vim
\%xFF hex character FF NOT SUPPORTED vim
\%o123 octal character 123 NOT SUPPORTED vim
\%u1234 Unicode character 0x1234 NOT SUPPORTED vim
\%U12345678 Unicode character 0x12345678 NOT SUPPORTED vim
Character class elements:
x single character
A-Z character range (inclusive)
\d Perl character class
[:foo:] ASCII character class «foo»
\p{Foo} Unicode character class «Foo»
\pF Unicode character class «F» (one-letter name)
Named character classes as character class elements:
[\d] digits (== \d)
[^\d] not digits (== \D)
[\D] not digits (== \D)
[^\D] not not digits (== \d)
[[:name:]] named ASCII class inside character class (== [:name:])
[^[:name:]] named ASCII class inside negated character class (== [:^name:])
[\p{Name}] named Unicode property inside character class (== \p{Name})
[^\p{Name}] named Unicode property inside negated character class (== \P{Name})
Perl character classes (all ASCII-only):
\d digits (== [0-9])
\D not digits (== [^0-9])
\s whitespace (== [\t\n\f\r ])
\S not whitespace (== [^\t\n\f\r ])
\w word characters (== [0-9A-Za-z_])
\W not word characters (== [^0-9A-Za-z_])
\h horizontal space NOT SUPPORTED
\H not horizontal space NOT SUPPORTED
\v vertical space NOT SUPPORTED
\V not vertical space NOT SUPPORTED
ASCII character classes:
[[:alnum:]] alphanumeric (== [0-9A-Za-z])
[[:alpha:]] alphabetic (== [A-Za-z])
[[:ascii:]] ASCII (== [\x00-\x7F])
[[:blank:]] blank (== [\t ])
[[:cntrl:]] control (== [\x00-\x1F\x7F])
[[:digit:]] digits (== [0-9])
[[:graph:]] graphical (== [!-~] == [A-Za-z0-9!"#$%&'()*+,\-./:;<=>?@[\\\]^_`{|}~])
[[:lower:]] lower case (== [a-z])
[[:print:]] printable (== [ -~] == [ [:graph:]])
[[:punct:]] punctuation (== [!-/:-@[-`{-~])
[[:space:]] whitespace (== [\t\n\v\f\r ])
[[:upper:]] upper case (== [A-Z])
[[:word:]] word characters (== [0-9A-Za-z_])
[[:xdigit:]] hex digit (== [0-9A-Fa-f])
Unicode character class names--general category:
C other
Cc control
Cf format
Cn unassigned code points NOT SUPPORTED
Co private use
Cs surrogate
L letter
LC cased letter NOT SUPPORTED
L& cased letter NOT SUPPORTED
Ll lowercase letter
Lm modifier letter
Lo other letter
Lt titlecase letter
Lu uppercase letter
M mark
Mc spacing mark
Me enclosing mark
Mn non-spacing mark
N number
Nd decimal number
Nl letter number
No other number
P punctuation
Pc connector punctuation
Pd dash punctuation
Pe close punctuation
Pf final punctuation
Pi initial punctuation
Po other punctuation
Ps open punctuation
S symbol
Sc currency symbol
Sk modifier symbol
Sm math symbol
So other symbol
Z separator
Zl line separator
Zp paragraph separator
Zs space separator
Unicode character class names--scripts:
Adlam
Ahom
Anatolian_Hieroglyphs
Arabic
Armenian
Avestan
Balinese
Bamum
Bassa_Vah
Batak
Bengali
Bhaiksuki
Bopomofo
Brahmi
Braille
Buginese
Buhid
Canadian_Aboriginal
Carian
Caucasian_Albanian
Chakma
Cham
Cherokee
Chorasmian
Common
Coptic
Cuneiform
Cypriot
Cypro_Minoan
Cyrillic
Deseret
Devanagari
Dives_Akuru
Dogra
Duployan
Egyptian_Hieroglyphs
Elbasan
Elymaic
Ethiopic
Georgian
Glagolitic
Gothic
Grantha
Greek
Gujarati
Gunjala_Gondi
Gurmukhi
Han
Hangul
Hanifi_Rohingya
Hanunoo
Hatran
Hebrew
Hiragana
Imperial_Aramaic
Inherited
Inscriptional_Pahlavi
Inscriptional_Parthian
Javanese
Kaithi
Kannada
Katakana
Kawi
Kayah_Li
Kharoshthi
Khitan_Small_Script
Khmer
Khojki
Khudawadi
Lao
Latin
Lepcha
Limbu
Linear_A
Linear_B
Lisu
Lycian
Lydian
Mahajani
Makasar
Malayalam
Mandaic
Manichaean
Marchen
Masaram_Gondi
Medefaidrin
Meetei_Mayek
Mende_Kikakui
Meroitic_Cursive
Meroitic_Hieroglyphs
Miao
Modi
Mongolian
Mro
Multani
Myanmar
Nabataean
Nag_Mundari
Nandinagari
New_Tai_Lue
Newa
Nko
Nushu
Nyiakeng_Puachue_Hmong
Ogham
Ol_Chiki
Old_Hungarian
Old_Italic
Old_North_Arabian
Old_Permic
Old_Persian
Old_Sogdian
Old_South_Arabian
Old_Turkic
Old_Uyghur
Oriya
Osage
Osmanya
Pahawh_Hmong
Palmyrene
Pau_Cin_Hau
Phags_Pa
Phoenician
Psalter_Pahlavi
Rejang
Runic
Samaritan
Saurashtra
Sharada
Shavian
Siddham
SignWriting
Sinhala
Sogdian
Sora_Sompeng
Soyombo
Sundanese
Syloti_Nagri
Syriac
Tagalog
Tagbanwa
Tai_Le
Tai_Tham
Tai_Viet
Takri
Tamil
Tangsa
Tangut
Telugu
Thaana
Thai
Tibetan
Tifinagh
Tirhuta
Toto
Ugaritic
Vai
Vithkuqi
Wancho
Warang_Citi
Yezidi
Yi
Zanabazar_Square
Vim character classes:
\i identifier character NOT SUPPORTED vim
\I «\i» except digits NOT SUPPORTED vim
\k keyword character NOT SUPPORTED vim
\K «\k» except digits NOT SUPPORTED vim
\f file name character NOT SUPPORTED vim
\F «\f» except digits NOT SUPPORTED vim
\p printable character NOT SUPPORTED vim
\P «\p» except digits NOT SUPPORTED vim
\s whitespace character (== [ \t]) NOT SUPPORTED vim
\S non-white space character (== [^ \t]) NOT SUPPORTED vim
\d digits (== [0-9]) vim
\D not «\d» vim
\x hex digits (== [0-9A-Fa-f]) NOT SUPPORTED vim
\X not «\x» NOT SUPPORTED vim
\o octal digits (== [0-7]) NOT SUPPORTED vim
\O not «\o» NOT SUPPORTED vim
\w word character vim
\W not «\w» vim
\h head of word character NOT SUPPORTED vim
\H not «\h» NOT SUPPORTED vim
\a alphabetic NOT SUPPORTED vim
\A not «\a» NOT SUPPORTED vim
\l lowercase NOT SUPPORTED vim
\L not lowercase NOT SUPPORTED vim
\u uppercase NOT SUPPORTED vim
\U not uppercase NOT SUPPORTED vim
\_x «\x» plus newline, for any «x» NOT SUPPORTED vim
Vim flags:
\c ignore case NOT SUPPORTED vim
\C match case NOT SUPPORTED vim
\m magic NOT SUPPORTED vim
\M nomagic NOT SUPPORTED vim
\v verymagic NOT SUPPORTED vim
\V verynomagic NOT SUPPORTED vim
\Z ignore differences in Unicode combining characters NOT SUPPORTED vim
Magic:
(?{code}) arbitrary Perl code NOT SUPPORTED perl
(??{code}) postponed arbitrary Perl code NOT SUPPORTED perl
(?n) recursive call to regexp capturing group «n» NOT SUPPORTED
(?+n) recursive call to relative group «+n» NOT SUPPORTED
(?-n) recursive call to relative group «-n» NOT SUPPORTED
(?C) PCRE callout NOT SUPPORTED pcre
(?R) recursive call to entire regexp (== (?0)) NOT SUPPORTED
(?&name) recursive call to named group NOT SUPPORTED
(?P=name) named backreference NOT SUPPORTED
(?P>name) recursive call to named group NOT SUPPORTED
(?(cond)true|false) conditional branch NOT SUPPORTED
(?(cond)true) conditional branch NOT SUPPORTED
(*ACCEPT) make regexps more like Prolog NOT SUPPORTED
(*COMMIT) NOT SUPPORTED
(*F) NOT SUPPORTED
(*FAIL) NOT SUPPORTED
(*MARK) NOT SUPPORTED
(*PRUNE) NOT SUPPORTED
(*SKIP) NOT SUPPORTED
(*THEN) NOT SUPPORTED
(*ANY) set newline convention NOT SUPPORTED
(*ANYCRLF) NOT SUPPORTED
(*CR) NOT SUPPORTED
(*CRLF) NOT SUPPORTED
(*LF) NOT SUPPORTED
(*BSR_ANYCRLF) set \R convention NOT SUPPORTED pcre
(*BSR_UNICODE) NOT SUPPORTED pcre

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,427 @@
---
name: gtm-variables
description: Expert guidance for configuring Google Tag Manager variables including built-in variables (Page URL, Page Path, Referrer, Click variables, Form variables), data layer variables, custom JavaScript variables, first-party cookies, lookup tables, regex tables, constant variables, URL variables, DOM element variables, auto-event variables, container variables, and user-defined variables. Use when creating variables, configuring data layer variables, writing custom JavaScript variables, parsing URLs, reading cookies, setting up lookup tables, extracting values from DOM elements, debugging variable values, or working with variable formatting and transformations.
---
# GTM Variables Configuration
## Overview
Expert guidance for configuring all types of variables in Google Tag Manager that capture, store, and reuse dynamic values across tags and triggers.
## When to Use This Skill
Invoke this skill when:
- Creating or configuring GTM variables
- Setting up data layer variables
- Writing custom JavaScript variables
- Working with built-in variables
- Parsing URL parameters or components
- Reading first-party cookies
- Creating lookup tables or regex tables
- Extracting values from DOM elements
- Setting up constant values
- Debugging variable values in Preview mode
- Formatting or transforming variable data
- Optimizing variable performance
## Built-in Variables
Built-in variables are pre-configured by GTM. Enable them in Variables → Configure:
### Page Variables
- **Page URL** - Full URL of current page
- **Page Hostname** - Domain name
- **Page Path** - Path portion of URL (after domain)
- **Referrer** - Previous page URL
- **Random Number** - Random number for cache busting
### Click Variables
(Enable when using click triggers)
- **Click Element** - Clicked DOM element
- **Click Classes** - CSS classes of clicked element
- **Click ID** - ID attribute of clicked element
- **Click Target** - Target attribute of clicked link
- **Click URL** - href of clicked link
- **Click Text** - Text content of clicked element
### Form Variables
(Enable when using form triggers)
- **Form Element** - Submitted form DOM element
- **Form Classes** - CSS classes of form
- **Form ID** - ID attribute of form
- **Form Target** - Target attribute of form
- **Form URL** - Action URL of form
- **Form Text** - Text content of form
### Error Variables
(Enable for JavaScript error tracking)
- **Error Message** - JavaScript error message
- **Error URL** - URL where error occurred
- **Error Line** - Line number of error
- **Debug Mode** - Whether Preview mode is active
### Video Variables
(Enable for YouTube video tracking)
- **Video Provider** - Video platform (YouTube)
- **Video Status** - Play state (start, pause, complete)
- **Video URL** - URL of video
- **Video Title** - Title of video
- **Video Duration** - Length of video
- **Video Current Time** - Playback position
- **Video Percent** - Percentage watched
### Scroll Variables
- **Scroll Depth Threshold** - Percentage depth reached
- **Scroll Depth Units** - Pixels or percentage
- **Scroll Direction** - Vertical or horizontal
### Container Variables
- **Container ID** - GTM container ID
- **Container Version** - Published container version
- **Environment Name** - Environment (Live, Preview, etc.)
### History Variables
- **New History Fragment** - New URL fragment after history change
- **Old History Fragment** - Previous URL fragment
- **New History State** - New history state object
- **Old History State** - Previous history state
## User-Defined Variables
Create custom variables in Variables → New:
### Data Layer Variable
Most common variable type for accessing data layer values.
**Configuration:**
- **Data Layer Variable Name**: Path to value in data layer
- Use dot notation: `ecommerce.purchase.transaction_id`
- Use bracket notation for arrays: `products.0.name`
- **Data Layer Version**: Usually "Version 2"
- **Default Value**: Fallback if variable not found
**Example:**
```javascript
// Data Layer:
dataLayer.push({
'event': 'purchase',
'userId': '12345',
'ecommerce': {
'transaction_id': 'T_12345',
'value': 99.99
}
});
// Variables:
userId "12345"
ecommerce.transaction_id "T_12345"
ecommerce.value 99.99
```
### Custom JavaScript Variable
Execute JavaScript to return dynamic values.
**Best Practices:**
- Keep code simple and fast
- Always return a value
- Use for complex logic not possible with other variable types
- Avoid DOM manipulation (read-only)
- Test thoroughly
**Example:**
```javascript
function() {
// Get current date
return new Date().toISOString();
}
```
```javascript
function() {
// Get query parameter
var urlParams = new URLSearchParams(window.location.search);
return urlParams.get('utm_campaign') || 'direct';
}
```
```javascript
function() {
// Format price
var price = {{DL - Price}}; // Reference another variable
return '$' + parseFloat(price).toFixed(2);
}
```
### First-Party Cookie
Read cookie values from the browser.
**Configuration:**
- **Cookie Name**: Name of cookie to read
- **URL Decode**: Decode URI-encoded values
- **Default Value**: Return if cookie not found
**Example:**
- Cookie Name: `_ga` → Read Google Analytics cookie
- Cookie Name: `user_consent` → Read custom consent cookie
### Constant
Store static values to reuse across tags.
**Use Cases:**
- GA4 Measurement ID
- Google Ads Conversion ID
- API keys (if not sensitive)
- Common parameter values
**Example:**
- Constant: `G-XXXXXXXXXX` (GA4 Measurement ID)
- Constant: `AW-123456789` (Google Ads ID)
### URL Variable
Parse components from current page URL or custom URL.
**Component Types:**
- Full URL
- Protocol
- Hostname
- Port
- Path
- Query
- Fragment
- Specific Query Parameter
**Example:**
URL: `https://example.com/products?category=shoes&sale=true#top`
- Component: Hostname → `example.com`
- Component: Path → `/products`
- Component: Query → `category=shoes&sale=true`
- Component: Query Key `category``shoes`
- Component: Fragment → `top`
### Lookup Table
Map input values to output values (like a switch statement).
**Configuration:**
- **Input Variable**: Variable to check
- **Lookup Table**: Input → Output mappings
- **Default Value**: Return if no match
**Example:**
Input: {{Page Path}}
| Input | Output |
|-------|--------|
| / | homepage |
| /products | product_listing |
| /checkout | checkout |
Default: other
### RegEx Table
Similar to Lookup Table but uses Regular Expressions for pattern matching.
**Configuration:**
- **Input Variable**: Variable to check
- **Pattern Table**: RegEx patterns → Output values
- **Default Value**: Return if no match
**Example:**
Input: {{Page Path}}
| Pattern | Output |
|---------|--------|
| ^/$ | homepage |
| ^/products/.* | product_page |
| ^/blog/.* | blog_post |
| ^/checkout | checkout |
Default: other
### DOM Element
Extract values from page elements using CSS selectors.
**Configuration:**
- **Selection Method**: CSS Selector or Element ID
- **Selector**: CSS selector or ID
- **Attribute Name**: Which attribute to get (blank = text content)
**Examples:**
- Selector: `h1` → Get first H1 text
- Selector: `#product-price`, Attribute: `data-price` → Get price from data attribute
- Selector: `.user-email` → Get email element text
### Auto-Event Variable
Access properties of auto-events (clicks, forms, etc.).
**Variable Type**: Select specific auto-event property
- Click Element, Click Classes, Click ID, etc.
- Form Element, Form Classes, Form ID, etc.
These are usually just enabled as built-in variables instead.
### Custom Event Variable
Access event parameters from enhanced measurement or custom events.
**Configuration:**
- **Event Parameter**: Name of parameter to capture
- Works with GA4 events
### Google Sheets Variable
(Available in GTM web containers)
Fetch values from Google Sheets.
**Use Cases:**
- Dynamic lookup tables
- A/B test configurations
- Feature flags
### HTTP Referrer
Get the referrer URL (same as built-in Referrer variable, but user-defined for custom formatting).
### JavaScript Variable
Access global JavaScript variables.
**Configuration:**
- **Global Variable Name**: Name of window variable
- Use dot notation for nested properties
**Example:**
- Global Variable Name: `dataLayer` → Access data layer array
- Global Variable Name: `user.email` → Access window.user.email
## Common Workflows
### Create Data Layer Variable
1. Variables → New → Data Layer Variable
2. Set Data Layer Variable Name (e.g., `userId`)
3. Set Default Value (optional)
4. Save with clear name: `DL - User ID`
5. Test in Preview mode → Variables tab
### Create Custom JavaScript Variable
1. Variables → New → Custom JavaScript
2. Write function that returns value:
```javascript
function() {
return /* your logic */;
}
```
3. Test return value in Preview mode
4. Save with clear name: `CJS - Description`
### Create Lookup Table
1. Variables → New → Lookup Table
2. Select Input Variable
3. Add Input → Output mappings
4. Set Default Value
5. Test with various inputs in Preview mode
6. Save with clear name: `LUT - Description`
### Parse URL Parameter
1. Variables → New → URL
2. Component Type: Query
3. Query Key: parameter name (e.g., `utm_source`)
4. Default Value: `(direct)` or other fallback
5. Save as: `URL - UTM Source`
### Read Cookie Value
1. Variables → New → 1st Party Cookie
2. Cookie Name: cookie to read
3. Enable URL Decode if needed
4. Set Default Value if cookie might not exist
5. Save as: `Cookie - Name`
## Best Practices
### Variable Naming
Use consistent prefix format: `[Type] - [Description]`
Examples:
- `DL - User ID` (Data Layer)
- `CJS - Format Price` (Custom JavaScript)
- `URL - UTM Campaign` (URL)
- `Cookie - Session ID` (First-Party Cookie)
- `Constant - GA4 ID` (Constant)
- `LUT - Page Type` (Lookup Table)
### Performance Optimization
- Prefer built-in variables over custom JavaScript
- Prefer data layer variables over DOM scraping
- Keep custom JavaScript simple and fast
- Avoid DOM queries in custom JavaScript when possible
- Cache complex calculations in data layer instead
- Remove unused variables regularly
### Common Pitfalls
- **Undefined variables**: Check spelling, data layer structure, timing
- **Empty values**: Set meaningful default values
- **Variable not updating**: Ensure data layer push happens before variable read
- **Performance issues**: Avoid complex DOM queries in custom JS variables
### Data Layer Best Practices
- Push data to data layer before GTM fires
- Use consistent data layer structure
- Document data layer schema
- Validate data layer in Preview mode
- See **gtm-datalayer** skill for advanced patterns
## References
- **references/variables.md** - Comprehensive variable configuration guide with all variable types and advanced patterns
- **references/google-rew-regular-expressions-syntax.txt** - RegEx syntax for regex tables
Search reference files for specific topics:
```bash
grep -r "Data Layer Variable" references/
grep -r "Custom JavaScript" references/
grep -r "Lookup Table" references/
```
## Integration with Other Skills
- **gtm-tags** - Use variables in tag configuration
- **gtm-triggers** - Use variables in trigger conditions
- **gtm-datalayer** - Implement data layer for data layer variables
- **gtm-debugging** - Debug variable values in Preview mode
- **gtm-setup** - Enable built-in variables
- **gtm-best-practices** - Variable naming conventions and optimization
## Quick Reference
### Variable Type Selection Guide
- **From data layer**: Data Layer Variable
- **From URL**: URL Variable
- **From cookie**: 1st Party Cookie
- **From page element**: DOM Element Variable
- **Static value**: Constant
- **Complex logic**: Custom JavaScript
- **Value mapping**: Lookup Table or RegEx Table
- **Auto-event data**: Built-in Variables (enable them)
### Common Custom JavaScript Patterns
```javascript
// Get current timestamp
function() {
return Date.now();
}
// Get query parameter
function() {
var params = new URLSearchParams(window.location.search);
return params.get('campaign') || 'none';
}
// Format currency
function() {
var value = {{DL - Price}};
return '$' + parseFloat(value).toFixed(2);
}
// Get array length
function() {
var items = {{DL - Cart Items}} || [];
return items.length;
}
```
### Debugging Checklist
- [ ] Variable name matches data layer path exactly
- [ ] Data layer push happens before variable is read
- [ ] Default value is set for optional variables
- [ ] Built-in variables are enabled
- [ ] Testing in Preview mode → Variables tab
- [ ] Checking variable value at right event

View File

@@ -0,0 +1,462 @@
RE2 regular expression syntax reference
-------------------------­-------­-----
Single characters:
. any character, possibly including newline (s=true)
[xyz] character class
[^xyz] negated character class
\d Perl character class
\D negated Perl character class
[[:alpha:]] ASCII character class
[[:^alpha:]] negated ASCII character class
\pN Unicode character class (one-letter name)
\p{Greek} Unicode character class
\PN negated Unicode character class (one-letter name)
\P{Greek} negated Unicode character class
Composites:
xy «x» followed by «y»
x|y «x» or «y» (prefer «x»)
Repetitions:
x* zero or more «x», prefer more
x+ one or more «x», prefer more
x? zero or one «x», prefer one
x{n,m} «n» or «n»+1 or ... or «m» «x», prefer more
x{n,} «n» or more «x», prefer more
x{n} exactly «n» «x»
x*? zero or more «x», prefer fewer
x+? one or more «x», prefer fewer
x?? zero or one «x», prefer zero
x{n,m}? «n» or «n»+1 or ... or «m» «x», prefer fewer
x{n,}? «n» or more «x», prefer fewer
x{n}? exactly «n» «x»
x{} (== x*) NOT SUPPORTED vim
x{-} (== x*?) NOT SUPPORTED vim
x{-n} (== x{n}?) NOT SUPPORTED vim
x= (== x?) NOT SUPPORTED vim
Implementation restriction: The counting forms «x{n,m}», «x{n,}», and «x{n}»
reject forms that create a minimum or maximum repetition count above 1000.
Unlimited repetitions are not subject to this restriction.
Possessive repetitions:
x*+ zero or more «x», possessive NOT SUPPORTED
x++ one or more «x», possessive NOT SUPPORTED
x?+ zero or one «x», possessive NOT SUPPORTED
x{n,m}+ «n» or ... or «m» «x», possessive NOT SUPPORTED
x{n,}+ «n» or more «x», possessive NOT SUPPORTED
x{n}+ exactly «n» «x», possessive NOT SUPPORTED
Grouping:
(re) numbered capturing group (submatch)
(?P<name>re) named & numbered capturing group (submatch)
(?<name>re) named & numbered capturing group (submatch)
(?'name're) named & numbered capturing group (submatch) NOT SUPPORTED
(?:re) non-capturing group
(?flags) set flags within current group; non-capturing
(?flags:re) set flags during re; non-capturing
(?#text) comment NOT SUPPORTED
(?|x|y|z) branch numbering reset NOT SUPPORTED
(?>re) possessive match of «re» NOT SUPPORTED
re@> possessive match of «re» NOT SUPPORTED vim
%(re) non-capturing group NOT SUPPORTED vim
Flags:
i case-insensitive (default false)
m multi-line mode: «^» and «$» match begin/end line in addition to begin/end text (default false)
s let «.» match «\n» (default false)
U ungreedy: swap meaning of «x*» and «x*?», «x+» and «x+?», etc (default false)
Flag syntax is «xyz» (set) or «-xyz» (clear) or «xy-z» (set «xy», clear «z»).
Empty strings:
^ at beginning of text or line («m»=true)
$ at end of text (like «\z» not «\Z») or line («m»=true)
\A at beginning of text
\b at ASCII word boundary («\w» on one side and «\W», «\A», or «\z» on the other)
\B not at ASCII word boundary
\G at beginning of subtext being searched NOT SUPPORTED pcre
\G at end of last match NOT SUPPORTED perl
\Z at end of text, or before newline at end of text NOT SUPPORTED
\z at end of text
(?=re) before text matching «re» NOT SUPPORTED
(?!re) before text not matching «re» NOT SUPPORTED
(?<=re) after text matching «re» NOT SUPPORTED
(?<!re) after text not matching «re» NOT SUPPORTED
re& before text matching «re» NOT SUPPORTED vim
re@= before text matching «re» NOT SUPPORTED vim
re@! before text not matching «re» NOT SUPPORTED vim
re@<= after text matching «re» NOT SUPPORTED vim
re@<! after text not matching «re» NOT SUPPORTED vim
\zs sets start of match (= \K) NOT SUPPORTED vim
\ze sets end of match NOT SUPPORTED vim
\%^ beginning of file NOT SUPPORTED vim
\%$ end of file NOT SUPPORTED vim
\%V on screen NOT SUPPORTED vim
\%# cursor position NOT SUPPORTED vim
\%'m mark «m» position NOT SUPPORTED vim
\%23l in line 23 NOT SUPPORTED vim
\%23c in column 23 NOT SUPPORTED vim
\%23v in virtual column 23 NOT SUPPORTED vim
Escape sequences:
\a bell (== \007)
\f form feed (== \014)
\t horizontal tab (== \011)
\n newline (== \012)
\r carriage return (== \015)
\v vertical tab character (== \013)
\* literal «*», for any punctuation character «*»
\123 octal character code (up to three digits)
\x7F hex character code (exactly two digits)
\x{10FFFF} hex character code
\C match a single byte even in UTF-8 mode
\Q...\E literal text «...» even if «...» has punctuation
\1 backreference NOT SUPPORTED
\b backspace NOT SUPPORTED (use «\010»)
\cK control char ^K NOT SUPPORTED (use «\001» etc)
\e escape NOT SUPPORTED (use «\033»)
\g1 backreference NOT SUPPORTED
\g{1} backreference NOT SUPPORTED
\g{+1} backreference NOT SUPPORTED
\g{-1} backreference NOT SUPPORTED
\g{name} named backreference NOT SUPPORTED
\g<name> subroutine call NOT SUPPORTED
\g'name' subroutine call NOT SUPPORTED
\k<name> named backreference NOT SUPPORTED
\k'name' named backreference NOT SUPPORTED
\lX lowercase «X» NOT SUPPORTED
\ux uppercase «x» NOT SUPPORTED
\L...\E lowercase text «...» NOT SUPPORTED
\K reset beginning of «$0» NOT SUPPORTED
\N{name} named Unicode character NOT SUPPORTED
\R line break NOT SUPPORTED
\U...\E upper case text «...» NOT SUPPORTED
\X extended Unicode sequence NOT SUPPORTED
\%d123 decimal character 123 NOT SUPPORTED vim
\%xFF hex character FF NOT SUPPORTED vim
\%o123 octal character 123 NOT SUPPORTED vim
\%u1234 Unicode character 0x1234 NOT SUPPORTED vim
\%U12345678 Unicode character 0x12345678 NOT SUPPORTED vim
Character class elements:
x single character
A-Z character range (inclusive)
\d Perl character class
[:foo:] ASCII character class «foo»
\p{Foo} Unicode character class «Foo»
\pF Unicode character class «F» (one-letter name)
Named character classes as character class elements:
[\d] digits (== \d)
[^\d] not digits (== \D)
[\D] not digits (== \D)
[^\D] not not digits (== \d)
[[:name:]] named ASCII class inside character class (== [:name:])
[^[:name:]] named ASCII class inside negated character class (== [:^name:])
[\p{Name}] named Unicode property inside character class (== \p{Name})
[^\p{Name}] named Unicode property inside negated character class (== \P{Name})
Perl character classes (all ASCII-only):
\d digits (== [0-9])
\D not digits (== [^0-9])
\s whitespace (== [\t\n\f\r ])
\S not whitespace (== [^\t\n\f\r ])
\w word characters (== [0-9A-Za-z_])
\W not word characters (== [^0-9A-Za-z_])
\h horizontal space NOT SUPPORTED
\H not horizontal space NOT SUPPORTED
\v vertical space NOT SUPPORTED
\V not vertical space NOT SUPPORTED
ASCII character classes:
[[:alnum:]] alphanumeric (== [0-9A-Za-z])
[[:alpha:]] alphabetic (== [A-Za-z])
[[:ascii:]] ASCII (== [\x00-\x7F])
[[:blank:]] blank (== [\t ])
[[:cntrl:]] control (== [\x00-\x1F\x7F])
[[:digit:]] digits (== [0-9])
[[:graph:]] graphical (== [!-~] == [A-Za-z0-9!"#$%&'()*+,\-./:;<=>?@[\\\]^_`{|}~])
[[:lower:]] lower case (== [a-z])
[[:print:]] printable (== [ -~] == [ [:graph:]])
[[:punct:]] punctuation (== [!-/:-@[-`{-~])
[[:space:]] whitespace (== [\t\n\v\f\r ])
[[:upper:]] upper case (== [A-Z])
[[:word:]] word characters (== [0-9A-Za-z_])
[[:xdigit:]] hex digit (== [0-9A-Fa-f])
Unicode character class names--general category:
C other
Cc control
Cf format
Cn unassigned code points NOT SUPPORTED
Co private use
Cs surrogate
L letter
LC cased letter NOT SUPPORTED
L& cased letter NOT SUPPORTED
Ll lowercase letter
Lm modifier letter
Lo other letter
Lt titlecase letter
Lu uppercase letter
M mark
Mc spacing mark
Me enclosing mark
Mn non-spacing mark
N number
Nd decimal number
Nl letter number
No other number
P punctuation
Pc connector punctuation
Pd dash punctuation
Pe close punctuation
Pf final punctuation
Pi initial punctuation
Po other punctuation
Ps open punctuation
S symbol
Sc currency symbol
Sk modifier symbol
Sm math symbol
So other symbol
Z separator
Zl line separator
Zp paragraph separator
Zs space separator
Unicode character class names--scripts:
Adlam
Ahom
Anatolian_Hieroglyphs
Arabic
Armenian
Avestan
Balinese
Bamum
Bassa_Vah
Batak
Bengali
Bhaiksuki
Bopomofo
Brahmi
Braille
Buginese
Buhid
Canadian_Aboriginal
Carian
Caucasian_Albanian
Chakma
Cham
Cherokee
Chorasmian
Common
Coptic
Cuneiform
Cypriot
Cypro_Minoan
Cyrillic
Deseret
Devanagari
Dives_Akuru
Dogra
Duployan
Egyptian_Hieroglyphs
Elbasan
Elymaic
Ethiopic
Georgian
Glagolitic
Gothic
Grantha
Greek
Gujarati
Gunjala_Gondi
Gurmukhi
Han
Hangul
Hanifi_Rohingya
Hanunoo
Hatran
Hebrew
Hiragana
Imperial_Aramaic
Inherited
Inscriptional_Pahlavi
Inscriptional_Parthian
Javanese
Kaithi
Kannada
Katakana
Kawi
Kayah_Li
Kharoshthi
Khitan_Small_Script
Khmer
Khojki
Khudawadi
Lao
Latin
Lepcha
Limbu
Linear_A
Linear_B
Lisu
Lycian
Lydian
Mahajani
Makasar
Malayalam
Mandaic
Manichaean
Marchen
Masaram_Gondi
Medefaidrin
Meetei_Mayek
Mende_Kikakui
Meroitic_Cursive
Meroitic_Hieroglyphs
Miao
Modi
Mongolian
Mro
Multani
Myanmar
Nabataean
Nag_Mundari
Nandinagari
New_Tai_Lue
Newa
Nko
Nushu
Nyiakeng_Puachue_Hmong
Ogham
Ol_Chiki
Old_Hungarian
Old_Italic
Old_North_Arabian
Old_Permic
Old_Persian
Old_Sogdian
Old_South_Arabian
Old_Turkic
Old_Uyghur
Oriya
Osage
Osmanya
Pahawh_Hmong
Palmyrene
Pau_Cin_Hau
Phags_Pa
Phoenician
Psalter_Pahlavi
Rejang
Runic
Samaritan
Saurashtra
Sharada
Shavian
Siddham
SignWriting
Sinhala
Sogdian
Sora_Sompeng
Soyombo
Sundanese
Syloti_Nagri
Syriac
Tagalog
Tagbanwa
Tai_Le
Tai_Tham
Tai_Viet
Takri
Tamil
Tangsa
Tangut
Telugu
Thaana
Thai
Tibetan
Tifinagh
Tirhuta
Toto
Ugaritic
Vai
Vithkuqi
Wancho
Warang_Citi
Yezidi
Yi
Zanabazar_Square
Vim character classes:
\i identifier character NOT SUPPORTED vim
\I «\i» except digits NOT SUPPORTED vim
\k keyword character NOT SUPPORTED vim
\K «\k» except digits NOT SUPPORTED vim
\f file name character NOT SUPPORTED vim
\F «\f» except digits NOT SUPPORTED vim
\p printable character NOT SUPPORTED vim
\P «\p» except digits NOT SUPPORTED vim
\s whitespace character (== [ \t]) NOT SUPPORTED vim
\S non-white space character (== [^ \t]) NOT SUPPORTED vim
\d digits (== [0-9]) vim
\D not «\d» vim
\x hex digits (== [0-9A-Fa-f]) NOT SUPPORTED vim
\X not «\x» NOT SUPPORTED vim
\o octal digits (== [0-7]) NOT SUPPORTED vim
\O not «\o» NOT SUPPORTED vim
\w word character vim
\W not «\w» vim
\h head of word character NOT SUPPORTED vim
\H not «\h» NOT SUPPORTED vim
\a alphabetic NOT SUPPORTED vim
\A not «\a» NOT SUPPORTED vim
\l lowercase NOT SUPPORTED vim
\L not lowercase NOT SUPPORTED vim
\u uppercase NOT SUPPORTED vim
\U not uppercase NOT SUPPORTED vim
\_x «\x» plus newline, for any «x» NOT SUPPORTED vim
Vim flags:
\c ignore case NOT SUPPORTED vim
\C match case NOT SUPPORTED vim
\m magic NOT SUPPORTED vim
\M nomagic NOT SUPPORTED vim
\v verymagic NOT SUPPORTED vim
\V verynomagic NOT SUPPORTED vim
\Z ignore differences in Unicode combining characters NOT SUPPORTED vim
Magic:
(?{code}) arbitrary Perl code NOT SUPPORTED perl
(??{code}) postponed arbitrary Perl code NOT SUPPORTED perl
(?n) recursive call to regexp capturing group «n» NOT SUPPORTED
(?+n) recursive call to relative group «+n» NOT SUPPORTED
(?-n) recursive call to relative group «-n» NOT SUPPORTED
(?C) PCRE callout NOT SUPPORTED pcre
(?R) recursive call to entire regexp (== (?0)) NOT SUPPORTED
(?&name) recursive call to named group NOT SUPPORTED
(?P=name) named backreference NOT SUPPORTED
(?P>name) recursive call to named group NOT SUPPORTED
(?(cond)true|false) conditional branch NOT SUPPORTED
(?(cond)true) conditional branch NOT SUPPORTED
(*ACCEPT) make regexps more like Prolog NOT SUPPORTED
(*COMMIT) NOT SUPPORTED
(*F) NOT SUPPORTED
(*FAIL) NOT SUPPORTED
(*MARK) NOT SUPPORTED
(*PRUNE) NOT SUPPORTED
(*SKIP) NOT SUPPORTED
(*THEN) NOT SUPPORTED
(*ANY) set newline convention NOT SUPPORTED
(*ANYCRLF) NOT SUPPORTED
(*CR) NOT SUPPORTED
(*CRLF) NOT SUPPORTED
(*LF) NOT SUPPORTED
(*BSR_ANYCRLF) set \R convention NOT SUPPORTED pcre
(*BSR_UNICODE) NOT SUPPORTED pcre

File diff suppressed because it is too large Load Diff