1607 lines
31 KiB
Markdown
1607 lines
31 KiB
Markdown
# Google Tag Manager - Variables
|
|
|
|
## Overview
|
|
|
|
Variables in Google Tag Manager are placeholders that store and retrieve values. They are the "what" component of the Tag-Trigger-Variable system, providing dynamic data to tags and triggers.
|
|
|
|
**What Variables Do:**
|
|
|
|
- Store dynamic values (page URL, click text, user data)
|
|
- Read from data layer
|
|
- Execute JavaScript to compute values
|
|
- Retrieve cookie values
|
|
- Provide reusable values across tags
|
|
- Enable conditional tag firing in triggers
|
|
|
|
## Technical Constraints
|
|
|
|
### JavaScript Variables (ES5 Requirement)
|
|
|
|
**CRITICAL:** Custom JavaScript Variables in GTM require **ECMAScript 5 (ES5)** syntax, NOT modern ES6+.
|
|
|
|
**ES6 Features NOT Supported:**
|
|
|
|
```javascript
|
|
// ❌ WILL FAIL - ES6 syntax
|
|
const myVar = 'value';
|
|
let count = 0;
|
|
const arrow = () => 'result';
|
|
const template = `Hello ${name}`;
|
|
const {property} = object;
|
|
const [first, second] = array;
|
|
|
|
// ✅ CORRECT - ES5 syntax
|
|
var myVar = 'value';
|
|
var count = 0;
|
|
var regularFunc = function() { return 'result'; };
|
|
var concatenated = 'Hello ' + name;
|
|
var property = object.property;
|
|
var first = array[0];
|
|
var second = array[1];
|
|
```
|
|
|
|
**Custom JavaScript variables must:**
|
|
- Use `var` for declarations
|
|
- Use `function() {}` syntax (not arrow functions)
|
|
- Use string concatenation (not template literals)
|
|
- Use bracket/dot notation (not destructuring)
|
|
- Return a value
|
|
|
|
**See Also:** [Best Practices - JavaScript in GTM](./best-practices.md#javascript-in-google-tag-manager-es5-requirement)
|
|
|
|
### Regex Table Variables (RE2 Format)
|
|
|
|
**CRITICAL:** Regex Table variables use **RE2 (GoLang regex)** format, NOT standard JavaScript regex.
|
|
|
|
**NOT Supported in RE2:**
|
|
- ❌ Backreferences: `\1`, `\2`
|
|
- ❌ Lookahead: `(?=...)`
|
|
- ❌ Lookbehind: `(?<=...)`
|
|
|
|
**Supported in RE2:**
|
|
- ✅ Character classes: `[abc]`, `\d`, `\w`
|
|
- ✅ Quantifiers: `*`, `+`, `?`, `{n,m}`
|
|
- ✅ Anchors: `^`, `$`
|
|
- ✅ Alternation: `|`
|
|
- ✅ Groups: `(...)`
|
|
- ✅ Case-insensitive: `(?i)`
|
|
|
|
**Example Regex Table:**
|
|
|
|
```
|
|
Input Variable: {{Page Path}}
|
|
|
|
Pattern | Output
|
|
---------------------|--------
|
|
^/products/ | product
|
|
^/category/ | category
|
|
^/blog/\d{4}/ | blog_post
|
|
(?i)checkout | checkout (case-insensitive)
|
|
```
|
|
|
|
**See Also:**
|
|
- [Best Practices - Regular Expressions](./best-practices.md#regular-expressions-in-google-tag-manager-re2-format)
|
|
- Complete RE2 syntax: `.claude/skills/gtm-core/gtm-core/references/google-rew-regular-expressions-syntax.txt`
|
|
|
|
## Variable Basics
|
|
|
|
### How Variables Work
|
|
|
|
Variables in GTM are referenced using double curly braces: `{{Variable Name}}`
|
|
|
|
**Example:**
|
|
|
|
```
|
|
Tag Configuration:
|
|
Measurement ID: {{Constant - GA4 Measurement ID}}
|
|
User ID: {{DLV - User ID}}
|
|
Page URL: {{Page URL}}
|
|
|
|
Trigger Configuration:
|
|
Condition: {{Page Path}} contains /checkout
|
|
```
|
|
|
|
### Variable Types
|
|
|
|
GTM has two main categories of variables:
|
|
|
|
1. **Built-in Variables** - Predefined variables provided by GTM
|
|
2. **User-Defined Variables** - Custom variables you create
|
|
|
|
### Variable Resolution
|
|
|
|
When a tag fires, GTM resolves all variable references:
|
|
|
|
```
|
|
1. Tag fires
|
|
2. GTM finds {{Variable Name}} references
|
|
3. Variable evaluates and returns value
|
|
4. Value replaces {{Variable Name}} in tag
|
|
5. Tag sends data to platform
|
|
```
|
|
|
|
### Variable Naming Syntax
|
|
|
|
Variables are referenced with double curly braces:
|
|
|
|
```javascript
|
|
{{Variable Name}}
|
|
```
|
|
|
|
**Case-Sensitive:** `{{Page URL}}` ≠ `{{page url}}`
|
|
|
|
**Spaces Allowed:** `{{DLV - User ID}}` is valid
|
|
|
|
**Common Prefixes:**
|
|
- `DLV` - Data Layer Variable
|
|
- `JS` - Custom JavaScript
|
|
- `Constant` - Constant value
|
|
- `1P Cookie` - First Party Cookie
|
|
- `URL` - URL variable
|
|
|
|
## Built-in Variables
|
|
|
|
Built-in variables are predefined by GTM and automatically capture common page and event data.
|
|
|
|
### Enabling Built-in Variables
|
|
|
|
Variables → Configure Built-In Variables → Check boxes to enable
|
|
|
|
**Recommended to enable:**
|
|
- Page variables (URL, Path, Hostname, Referrer)
|
|
- Click variables (Element, ID, Classes, URL, Text)
|
|
- Container variables (Container ID, Version)
|
|
|
|
### Page Variables
|
|
|
|
**{{Page URL}}**
|
|
- Full page URL including protocol, domain, path, query
|
|
- Example: `https://example.com/products?id=123`
|
|
|
|
**{{Page Hostname}}**
|
|
- Domain name only
|
|
- Example: `example.com` or `www.example.com`
|
|
|
|
**{{Page Path}}**
|
|
- URL path without domain or query string
|
|
- Example: `/products/category/item`
|
|
|
|
**{{Referrer}}**
|
|
- URL of previous page
|
|
- Example: `https://google.com/search?q=example`
|
|
|
|
**{{Page Fragment}}**
|
|
- URL hash/fragment
|
|
- Example: `section-1` from `page.html#section-1`
|
|
|
|
### Click Variables
|
|
|
|
**{{Click Element}}**
|
|
- The DOM element that was clicked
|
|
- Returns: Element object
|
|
|
|
**{{Click ID}}**
|
|
- ID attribute of clicked element
|
|
- Example: `submit-button`
|
|
|
|
**{{Click Classes}}**
|
|
- CSS classes of clicked element
|
|
- Example: `btn btn-primary cta`
|
|
|
|
**{{Click URL}}**
|
|
- href attribute of clicked link
|
|
- Example: `https://example.com/page` or `mailto:email@example.com`
|
|
|
|
**{{Click Text}}**
|
|
- Text content of clicked element
|
|
- Example: `Sign Up Now`
|
|
|
|
**{{Click Target}}**
|
|
- Target attribute of clicked link
|
|
- Example: `_blank`, `_self`
|
|
|
|
### Form Variables
|
|
|
|
**{{Form Element}}**
|
|
- The form DOM element
|
|
- Returns: Form element object
|
|
|
|
**{{Form ID}}**
|
|
- ID attribute of form
|
|
- Example: `contact-form`
|
|
|
|
**{{Form Classes}}**
|
|
- CSS classes of form
|
|
- Example: `contact-form newsletter-signup`
|
|
|
|
**{{Form URL}}**
|
|
- Action URL of form
|
|
- Example: `/submit-contact`
|
|
|
|
**{{Form Text}}**
|
|
- Text content within form
|
|
- Example: Combined text from labels and buttons
|
|
|
|
**Important:** Never capture actual form field values containing PII.
|
|
|
|
### Video Variables
|
|
|
|
**{{Video Status}}**
|
|
- Current video status
|
|
- Values: `start`, `pause`, `complete`, `progress`, `seek`, `buffering`
|
|
|
|
**{{Video URL}}**
|
|
- YouTube video URL
|
|
- Example: `https://www.youtube.com/watch?v=VIDEO_ID`
|
|
|
|
**{{Video Title}}**
|
|
- Video title from YouTube
|
|
- Example: `Product Demo Video`
|
|
|
|
**{{Video Duration}}**
|
|
- Total video length in seconds
|
|
- Example: `180`
|
|
|
|
**{{Video Current Time}}**
|
|
- Current playback position in seconds
|
|
- Example: `45`
|
|
|
|
**{{Video Percent}}**
|
|
- Percentage of video watched
|
|
- Example: `25`
|
|
|
|
**{{Video Provider}}**
|
|
- Video platform
|
|
- Example: `youtube`
|
|
|
|
**{{Video Visible}}**
|
|
- Whether video is in viewport
|
|
- Values: `true` or `false`
|
|
|
|
### Scroll Variables
|
|
|
|
**{{Scroll Depth Threshold}}**
|
|
- The scroll threshold reached
|
|
- Example: `75` (from 75% threshold)
|
|
|
|
**{{Scroll Depth Units}}**
|
|
- Unit type of threshold
|
|
- Values: `percent` or `pixels`
|
|
|
|
**{{Scroll Direction}}**
|
|
- Scroll direction
|
|
- Values: `vertical` or `horizontal`
|
|
|
|
### Visibility Variables
|
|
|
|
**{{Percent Visible}}**
|
|
- Percentage of element visible in viewport
|
|
- Example: `50`
|
|
|
|
**{{On-Screen Duration}}**
|
|
- Duration element was visible (milliseconds)
|
|
- Example: `2000`
|
|
|
|
### Error Variables
|
|
|
|
**{{Error Message}}**
|
|
- JavaScript error message
|
|
- Example: `Uncaught TypeError: Cannot read property 'x' of undefined`
|
|
|
|
**{{Error URL}}**
|
|
- URL where error occurred
|
|
- Example: `https://example.com/script.js`
|
|
|
|
**{{Error Line}}**
|
|
- Line number in source file
|
|
- Example: `42`
|
|
|
|
### Utility Variables
|
|
|
|
**{{Container ID}}**
|
|
- GTM container ID
|
|
- Example: `GTM-XXXXXX`
|
|
|
|
**{{Container Version}}**
|
|
- Published container version number
|
|
- Example: `12`
|
|
|
|
**{{Debug Mode}}**
|
|
- Whether GTM is in debug/preview mode
|
|
- Values: `true` or `false`
|
|
|
|
**{{Random Number}}**
|
|
- Random integer 0 to 2147483647
|
|
- Use for: Cache busting, sampling
|
|
|
|
**{{Environment Name}}**
|
|
- Current GTM environment
|
|
- Values: `Live`, `Latest`, `Environment Name`
|
|
|
|
**{{HTML ID}}**
|
|
- ID attribute of GTM container element
|
|
- Example: `gtm-container`
|
|
|
|
## User-Defined Variable Types
|
|
|
|
Create custom variables to extend GTM functionality.
|
|
|
|
### Data Layer Variable
|
|
|
|
Reads values from the data layer.
|
|
|
|
**Purpose:**
|
|
- Access data pushed to data layer
|
|
- Read ecommerce data
|
|
- Retrieve custom event data
|
|
- Get user information
|
|
|
|
**Configuration:**
|
|
|
|
```
|
|
Variable Type: Data Layer Variable
|
|
Data Layer Variable Name: userId
|
|
(reads from dataLayer.userId)
|
|
|
|
Data Layer Version: Version 2
|
|
Set Default Value: (optional)
|
|
Default Value: unknown
|
|
```
|
|
|
|
**Data Layer Structure:**
|
|
|
|
```javascript
|
|
dataLayer.push({
|
|
'userId': '12345',
|
|
'userType': 'premium',
|
|
'pageCategory': 'product',
|
|
'ecommerce': {
|
|
'currency': 'USD',
|
|
'value': 99.99
|
|
}
|
|
});
|
|
```
|
|
|
|
**Variable Examples:**
|
|
|
|
```
|
|
Name: DLV - User ID
|
|
Data Layer Variable Name: userId
|
|
Returns: "12345"
|
|
|
|
Name: DLV - User Type
|
|
Data Layer Variable Name: userType
|
|
Returns: "premium"
|
|
|
|
Name: DLV - Currency
|
|
Data Layer Variable Name: ecommerce.currency
|
|
Returns: "USD"
|
|
|
|
Name: DLV - Transaction Value
|
|
Data Layer Variable Name: ecommerce.value
|
|
Returns: 99.99
|
|
```
|
|
|
|
**Nested Values:**
|
|
|
|
Use dot notation for nested objects:
|
|
|
|
```javascript
|
|
dataLayer.push({
|
|
'user': {
|
|
'id': '12345',
|
|
'preferences': {
|
|
'newsletter': true
|
|
}
|
|
}
|
|
});
|
|
|
|
// Variable Configuration:
|
|
Data Layer Variable Name: user.id
|
|
Returns: "12345"
|
|
|
|
Data Layer Variable Name: user.preferences.newsletter
|
|
Returns: true
|
|
```
|
|
|
|
**Array Access:**
|
|
|
|
Use array index notation:
|
|
|
|
```javascript
|
|
dataLayer.push({
|
|
'products': [
|
|
{'id': 'SKU001', 'name': 'Product 1'},
|
|
{'id': 'SKU002', 'name': 'Product 2'}
|
|
]
|
|
});
|
|
|
|
// Variable Configuration:
|
|
Data Layer Variable Name: products.0.id
|
|
Returns: "SKU001"
|
|
|
|
Data Layer Variable Name: products.1.name
|
|
Returns: "Product 2"
|
|
```
|
|
|
|
**Default Values:**
|
|
|
|
Set a fallback value when data layer variable is undefined:
|
|
|
|
```
|
|
Variable Type: Data Layer Variable
|
|
Data Layer Variable Name: userId
|
|
Set Default Value: ✓
|
|
Default Value: not-logged-in
|
|
```
|
|
|
|
### Custom JavaScript Variable
|
|
|
|
Executes JavaScript code to compute and return a value.
|
|
|
|
**IMPORTANT:** Must use ES5 JavaScript syntax (see section above).
|
|
|
|
**Purpose:**
|
|
- Perform calculations
|
|
- Transform data
|
|
- Combine multiple variables
|
|
- Conditional logic
|
|
- Access DOM elements
|
|
- Parse strings
|
|
|
|
**Configuration:**
|
|
|
|
```
|
|
Variable Type: Custom JavaScript
|
|
Custom JavaScript:
|
|
function() {
|
|
// ES5 JavaScript only
|
|
var result = 'computed value';
|
|
return result;
|
|
}
|
|
```
|
|
|
|
**Examples:**
|
|
|
|
**Simple Transformation:**
|
|
|
|
```javascript
|
|
function() {
|
|
var pagePath = {{Page Path}};
|
|
return pagePath.toLowerCase();
|
|
}
|
|
```
|
|
|
|
**Calculation:**
|
|
|
|
```javascript
|
|
function() {
|
|
var price = {{DLV - Product Price}};
|
|
var quantity = {{DLV - Quantity}};
|
|
return price * quantity;
|
|
}
|
|
```
|
|
|
|
**Conditional Logic:**
|
|
|
|
```javascript
|
|
function() {
|
|
var userType = {{DLV - User Type}};
|
|
|
|
if (userType === 'premium') {
|
|
return 'high-value';
|
|
} else if (userType === 'standard') {
|
|
return 'medium-value';
|
|
} else {
|
|
return 'low-value';
|
|
}
|
|
}
|
|
```
|
|
|
|
**String Manipulation:**
|
|
|
|
```javascript
|
|
function() {
|
|
var pageUrl = {{Page URL}};
|
|
|
|
// Extract query parameter
|
|
var match = pageUrl.match(/[?&]utm_source=([^&]+)/);
|
|
|
|
if (match && match[1]) {
|
|
return decodeURIComponent(match[1]);
|
|
}
|
|
|
|
return 'direct';
|
|
}
|
|
```
|
|
|
|
**Array Operations:**
|
|
|
|
```javascript
|
|
function() {
|
|
var products = {{DLV - Products}};
|
|
|
|
if (!products || !products.length) {
|
|
return 0;
|
|
}
|
|
|
|
var total = 0;
|
|
for (var i = 0; i < products.length; i++) {
|
|
total += products[i].price * products[i].quantity;
|
|
}
|
|
|
|
return total.toFixed(2);
|
|
}
|
|
```
|
|
|
|
**Date/Time:**
|
|
|
|
```javascript
|
|
function() {
|
|
var now = new Date();
|
|
|
|
// Format: YYYY-MM-DD
|
|
var year = now.getFullYear();
|
|
var month = ('0' + (now.getMonth() + 1)).slice(-2);
|
|
var day = ('0' + now.getDate()).slice(-2);
|
|
|
|
return year + '-' + month + '-' + day;
|
|
}
|
|
```
|
|
|
|
**DOM Access:**
|
|
|
|
```javascript
|
|
function() {
|
|
var element = document.querySelector('.product-sku');
|
|
|
|
if (element) {
|
|
return element.textContent.trim();
|
|
}
|
|
|
|
return 'not-found';
|
|
}
|
|
```
|
|
|
|
**Combining Variables:**
|
|
|
|
```javascript
|
|
function() {
|
|
var category = {{DLV - Category}};
|
|
var subcategory = {{DLV - Subcategory}};
|
|
|
|
return category + ' > ' + subcategory;
|
|
}
|
|
```
|
|
|
|
**Error Handling:**
|
|
|
|
```javascript
|
|
function() {
|
|
try {
|
|
var data = {{DLV - Complex Data}};
|
|
return data.property.nestedProperty;
|
|
} catch (e) {
|
|
return 'error';
|
|
}
|
|
}
|
|
```
|
|
|
|
**Best Practices:**
|
|
- Always return a value
|
|
- Handle undefined/null cases
|
|
- Use try/catch for risky operations
|
|
- Keep code simple and readable
|
|
- Test thoroughly in Preview mode
|
|
- Use ES5 syntax only
|
|
|
|
### First-Party Cookie
|
|
|
|
Reads value from a first-party cookie.
|
|
|
|
**Purpose:**
|
|
- Access cookie values
|
|
- Read user preferences
|
|
- Get session data
|
|
- Retrieve stored identifiers
|
|
|
|
**Configuration:**
|
|
|
|
```
|
|
Variable Type: First-Party Cookie
|
|
Cookie Name: user_id
|
|
(case-sensitive, exact cookie name)
|
|
|
|
URI-decode cookie: ✓ (recommended)
|
|
Format Value: Text / Lowercase / Uppercase / None
|
|
```
|
|
|
|
**Examples:**
|
|
|
|
```
|
|
Name: 1P Cookie - User ID
|
|
Cookie Name: user_id
|
|
Returns: Value of user_id cookie
|
|
|
|
Name: 1P Cookie - Session ID
|
|
Cookie Name: _session_id
|
|
Returns: Session identifier
|
|
|
|
Name: 1P Cookie - Consent
|
|
Cookie Name: cookie_consent
|
|
Returns: "accepted" or "denied"
|
|
```
|
|
|
|
**Cookie Path and Domain:**
|
|
|
|
GTM reads cookies accessible to the current page based on:
|
|
- Cookie domain (`.example.com` vs `www.example.com`)
|
|
- Cookie path (`/` vs `/products/`)
|
|
|
|
**URI Decoding:**
|
|
|
|
Enable "URI-decode cookie" to decode URL-encoded values:
|
|
|
|
```
|
|
Cookie Value: hello%20world
|
|
With URI-decode: hello world
|
|
Without URI-decode: hello%20world
|
|
```
|
|
|
|
**Use Cases:**
|
|
|
|
```javascript
|
|
// Check if user is logged in
|
|
Trigger Condition: {{1P Cookie - user_logged_in}} equals true
|
|
|
|
// Segment by user type
|
|
Tag Parameter: user_segment = {{1P Cookie - user_segment}}
|
|
|
|
// Exclude internal traffic
|
|
Blocking Trigger: {{1P Cookie - internal_user}} equals true
|
|
```
|
|
|
|
### JavaScript Variable
|
|
|
|
Reads value from a global JavaScript variable.
|
|
|
|
**Purpose:**
|
|
- Access window-level variables
|
|
- Read values from other scripts
|
|
- Get application state
|
|
- Access third-party SDKs
|
|
|
|
**Configuration:**
|
|
|
|
```
|
|
Variable Type: JavaScript Variable
|
|
Global Variable Name: myGlobalVar
|
|
(reads from window.myGlobalVar)
|
|
```
|
|
|
|
**Examples:**
|
|
|
|
```
|
|
Name: JS Var - Google Analytics ID
|
|
Global Variable Name: ga.q
|
|
Returns: GA queue
|
|
|
|
Name: JS Var - App Version
|
|
Global Variable Name: app.version
|
|
Returns: Application version number
|
|
|
|
Name: JS Var - User Object
|
|
Global Variable Name: currentUser
|
|
Returns: User object from application
|
|
```
|
|
|
|
**Nested Properties:**
|
|
|
|
Access nested object properties:
|
|
|
|
```javascript
|
|
// Global object:
|
|
window.appConfig = {
|
|
environment: 'production',
|
|
features: {
|
|
chatEnabled: true
|
|
}
|
|
};
|
|
|
|
// Variable Configuration:
|
|
Global Variable Name: appConfig.environment
|
|
Returns: "production"
|
|
|
|
Global Variable Name: appConfig.features.chatEnabled
|
|
Returns: true
|
|
```
|
|
|
|
**Difference from Custom JavaScript:**
|
|
|
|
| Feature | JavaScript Variable | Custom JavaScript |
|
|
|---------|---------------------|-------------------|
|
|
| Purpose | Read existing global variable | Execute code to compute value |
|
|
| Syntax | Variable name only | Full function |
|
|
| Code execution | No | Yes |
|
|
| Use when | Variable already exists | Need to process/calculate |
|
|
|
|
### URL Variable
|
|
|
|
Extracts components from a URL.
|
|
|
|
**Purpose:**
|
|
- Parse URL components
|
|
- Extract query parameters
|
|
- Get specific URL parts
|
|
- Clean URLs for reporting
|
|
|
|
**Configuration:**
|
|
|
|
```
|
|
Variable Type: URL
|
|
Component Type: URL / Protocol / Hostname / Path / Query / Fragment / Port
|
|
Query Key: (if Component Type = Query)
|
|
```
|
|
|
|
**Component Types:**
|
|
|
|
**URL** - Full URL
|
|
```
|
|
Input: https://example.com/products?id=123#reviews
|
|
Output: https://example.com/products?id=123#reviews
|
|
```
|
|
|
|
**Protocol**
|
|
```
|
|
Input: https://example.com/page
|
|
Output: https:
|
|
```
|
|
|
|
**Hostname**
|
|
```
|
|
Input: https://www.example.com/page
|
|
Output: www.example.com
|
|
```
|
|
|
|
**Port**
|
|
```
|
|
Input: https://example.com:8080/page
|
|
Output: 8080
|
|
```
|
|
|
|
**Path**
|
|
```
|
|
Input: https://example.com/products/category
|
|
Output: /products/category
|
|
```
|
|
|
|
**Query**
|
|
```
|
|
Input: https://example.com/page?utm_source=google&utm_medium=cpc
|
|
Component: Query
|
|
Output: utm_source=google&utm_medium=cpc
|
|
```
|
|
|
|
**Query (Specific Key)**
|
|
```
|
|
Input: https://example.com/page?utm_source=google&id=123
|
|
Component: Query
|
|
Query Key: utm_source
|
|
Output: google
|
|
```
|
|
|
|
**Fragment**
|
|
```
|
|
Input: https://example.com/page#section-2
|
|
Output: section-2
|
|
```
|
|
|
|
**Examples:**
|
|
|
|
```
|
|
Name: URL - UTM Source
|
|
Component Type: Query
|
|
Query Key: utm_source
|
|
Returns: Value of utm_source parameter
|
|
|
|
Name: URL - Product ID
|
|
Component Type: Query
|
|
Query Key: product_id
|
|
Returns: Product ID from query string
|
|
|
|
Name: URL - Current Path
|
|
Component Type: Path
|
|
Returns: /category/products
|
|
|
|
Name: URL - Referrer Hostname
|
|
Component Type: Hostname
|
|
Returns: Hostname of referrer
|
|
```
|
|
|
|
### Regex Table Variable
|
|
|
|
Maps input values to output values using regular expressions.
|
|
|
|
**IMPORTANT:** Uses RE2 regex format (see section above).
|
|
|
|
**Purpose:**
|
|
- Pattern matching and transformation
|
|
- Map URLs to page types
|
|
- Categorize pages
|
|
- Clean/normalize data
|
|
|
|
**Configuration:**
|
|
|
|
```
|
|
Variable Type: Regex Table
|
|
Input Variable: {{Page Path}}
|
|
Set Default Value: (optional)
|
|
Default Value: other
|
|
|
|
Pattern | Output
|
|
-----------------|--------
|
|
^/products/ | product
|
|
^/category/ | category
|
|
^/blog/ | blog
|
|
^/$ | home
|
|
```
|
|
|
|
**Pattern Matching:**
|
|
|
|
Patterns are evaluated in order, first match wins.
|
|
|
|
**Examples:**
|
|
|
|
**Page Type Classification:**
|
|
|
|
```
|
|
Input Variable: {{Page Path}}
|
|
|
|
Pattern | Output
|
|
-------------------------|------------
|
|
^/$ | home
|
|
^/products/[^/]+$ | product_detail
|
|
^/products/ | product_list
|
|
^/category/ | category
|
|
^/checkout/ | checkout
|
|
^/cart | cart
|
|
^/blog/\d{4}/ | blog_post
|
|
^/about | about
|
|
```
|
|
|
|
**URL Cleaning:**
|
|
|
|
```
|
|
Input Variable: {{Page URL}}
|
|
|
|
Pattern | Output
|
|
-----------------------------|---------------------------
|
|
\?.*$ | (removes query string)
|
|
#.*$ | (removes fragment)
|
|
```
|
|
|
|
**Campaign Source Mapping:**
|
|
|
|
```
|
|
Input Variable: {{URL - UTM Source}}
|
|
|
|
Pattern | Output
|
|
-----------------|--------
|
|
^google$ | paid_search
|
|
^facebook$ | social
|
|
^email | email
|
|
^newsletter | email
|
|
.* | other
|
|
```
|
|
|
|
**RE2 Regex Examples:**
|
|
|
|
```regex
|
|
# Exact match
|
|
^/checkout$
|
|
|
|
# Starts with
|
|
^/products/
|
|
|
|
# Contains
|
|
blog
|
|
|
|
# Ends with
|
|
\.pdf$
|
|
|
|
# Digits
|
|
\d+
|
|
|
|
# Word characters
|
|
[\w-]+
|
|
|
|
# Optional group
|
|
(/subcategory)?
|
|
|
|
# Multiple options
|
|
^/(checkout|cart|payment)
|
|
|
|
# Case-insensitive
|
|
(?i)pdf
|
|
```
|
|
|
|
**Default Value:**
|
|
|
|
Set a fallback when no pattern matches:
|
|
|
|
```
|
|
Set Default Value: ✓
|
|
Default Value: uncategorized
|
|
```
|
|
|
|
### Lookup Table Variable
|
|
|
|
Maps exact input values to output values.
|
|
|
|
**Purpose:**
|
|
- Simple key-value mapping
|
|
- Exact match transformation
|
|
- No regex needed
|
|
|
|
**Configuration:**
|
|
|
|
```
|
|
Variable Type: Lookup Table
|
|
Input Variable: {{DLV - User Type}}
|
|
Set Default Value: (optional)
|
|
Default Value: unknown
|
|
|
|
Input | Output
|
|
-----------|----------
|
|
premium | high
|
|
standard | medium
|
|
basic | low
|
|
trial | trial
|
|
```
|
|
|
|
**Examples:**
|
|
|
|
**User Tier Mapping:**
|
|
|
|
```
|
|
Input Variable: {{DLV - User Type}}
|
|
|
|
Input | Output
|
|
---------------|------------
|
|
enterprise | tier_1
|
|
business | tier_2
|
|
professional | tier_3
|
|
starter | tier_4
|
|
Default Value: tier_5
|
|
```
|
|
|
|
**Currency Symbol:**
|
|
|
|
```
|
|
Input Variable: {{DLV - Currency}}
|
|
|
|
Input | Output
|
|
-------|--------
|
|
USD | $
|
|
EUR | €
|
|
GBP | £
|
|
JPY | ¥
|
|
Default Value: $
|
|
```
|
|
|
|
**Page Type Mapping:**
|
|
|
|
```
|
|
Input Variable: {{Page Hostname}}
|
|
|
|
Input | Output
|
|
-----------------------|--------
|
|
www.example.com | main_site
|
|
shop.example.com | shop
|
|
blog.example.com | blog
|
|
support.example.com | support
|
|
Default Value: unknown
|
|
```
|
|
|
|
**When to Use:**
|
|
|
|
- **Lookup Table** - Exact string matches, simple mapping
|
|
- **Regex Table** - Pattern matching, complex rules, RE2 regex
|
|
|
|
### Constant Variable
|
|
|
|
Stores a fixed value.
|
|
|
|
**Purpose:**
|
|
- Store IDs and tokens
|
|
- Reusable configuration values
|
|
- Easy updates across container
|
|
|
|
**Configuration:**
|
|
|
|
```
|
|
Variable Type: Constant
|
|
Value: G-XXXXXXXXXX
|
|
```
|
|
|
|
**Examples:**
|
|
|
|
```
|
|
Name: Constant - GA4 Measurement ID
|
|
Value: G-XXXXXXXXXX
|
|
Use: In GA4 Configuration Tag
|
|
|
|
Name: Constant - Google Ads Conversion ID
|
|
Value: AW-123456789
|
|
Use: In Google Ads tags
|
|
|
|
Name: Constant - Environment
|
|
Value: production
|
|
Use: Conditional logic
|
|
|
|
Name: Constant - Tracking Enabled
|
|
Value: true
|
|
Use: Enable/disable tracking
|
|
```
|
|
|
|
**Benefits:**
|
|
|
|
- **Single source of truth** - Update once, applies everywhere
|
|
- **Easy migration** - Change IDs in one place
|
|
- **Clarity** - Descriptive variable names vs hardcoded IDs
|
|
|
|
**Example Usage:**
|
|
|
|
```
|
|
Instead of:
|
|
Measurement ID: G-XXXXXXXXXX (hardcoded in 10 tags)
|
|
|
|
Use:
|
|
Measurement ID: {{Constant - GA4 Measurement ID}}
|
|
(update constant once, affects all tags)
|
|
```
|
|
|
|
### Custom Event Variable
|
|
|
|
Returns the name of the current event.
|
|
|
|
**Purpose:**
|
|
- Get event name in tags
|
|
- Conditional logic based on event
|
|
- Debug event tracking
|
|
|
|
**Configuration:**
|
|
|
|
```
|
|
Variable Type: Custom Event
|
|
(no additional configuration)
|
|
```
|
|
|
|
**Returns:**
|
|
|
|
Current event name from data layer or GTM:
|
|
|
|
```javascript
|
|
dataLayer.push({'event': 'purchase'});
|
|
// {{Event}} returns: "purchase"
|
|
|
|
// Page load
|
|
// {{Event}} returns: "gtm.js"
|
|
|
|
// DOM Ready
|
|
// {{Event}} returns: "gtm.dom"
|
|
|
|
// Click
|
|
// {{Event}} returns: "gtm.click"
|
|
```
|
|
|
|
**Use Cases:**
|
|
|
|
```
|
|
Tag Configuration:
|
|
Event Name: {{Event}}
|
|
(sends current event name as parameter)
|
|
|
|
Custom JavaScript:
|
|
var event = {{Event}};
|
|
if (event === 'purchase') {
|
|
return 'conversion';
|
|
}
|
|
|
|
Trigger Condition:
|
|
{{Event}} equals virtualPageview
|
|
```
|
|
|
|
### Element Visibility Variable
|
|
|
|
Stores visibility information for elements.
|
|
|
|
**Purpose:**
|
|
- Access visibility metrics
|
|
- Track how visible elements are
|
|
- Measure engagement
|
|
|
|
**Configuration:**
|
|
|
|
```
|
|
Variable Type: Element Visibility
|
|
(automatically available with Element Visibility trigger)
|
|
```
|
|
|
|
**Available Variables:**
|
|
|
|
- `{{Percent Visible}}` - Percentage of element visible (0-100)
|
|
- `{{On-Screen Duration}}` - Time visible in milliseconds
|
|
|
|
**Use with Element Visibility Trigger:**
|
|
|
|
```
|
|
Trigger: Element Visibility
|
|
Element ID: featured-product
|
|
Minimum Percent Visible: 50%
|
|
|
|
Tag fires with variables:
|
|
{{Percent Visible}} = 75 (example)
|
|
{{On-Screen Duration}} = 2500 (example)
|
|
```
|
|
|
|
### Auto-Event Variable
|
|
|
|
Returns values from auto-event triggers.
|
|
|
|
**Purpose:**
|
|
- Access event-specific data
|
|
- Get click, form, scroll data
|
|
- Reference auto-event values
|
|
|
|
**Examples:**
|
|
|
|
**Click Variables:**
|
|
- `{{Click Element}}`
|
|
- `{{Click ID}}`
|
|
- `{{Click Classes}}`
|
|
- `{{Click URL}}`
|
|
- `{{Click Text}}`
|
|
|
|
**Form Variables:**
|
|
- `{{Form Element}}`
|
|
- `{{Form ID}}`
|
|
- `{{Form Classes}}`
|
|
- `{{Form URL}}`
|
|
|
|
**Scroll Variables:**
|
|
- `{{Scroll Depth Threshold}}`
|
|
- `{{Scroll Depth Units}}`
|
|
|
|
**Video Variables:**
|
|
- `{{Video Status}}`
|
|
- `{{Video URL}}`
|
|
- `{{Video Percent}}`
|
|
|
|
Enable in Variables → Configure Built-In Variables
|
|
|
|
### HTTP Referrer Variable
|
|
|
|
Extracts components from the referrer URL.
|
|
|
|
**Purpose:**
|
|
- Parse referrer URL
|
|
- Extract referrer domain
|
|
- Get referrer query parameters
|
|
- Track traffic sources
|
|
|
|
**Configuration:**
|
|
|
|
```
|
|
Variable Type: HTTP Referrer
|
|
Component Type: URL / Protocol / Hostname / Path / Query / Fragment / Port
|
|
Query Key: (if Component Type = Query)
|
|
```
|
|
|
|
**Examples:**
|
|
|
|
```
|
|
Name: HTTP Referrer - Hostname
|
|
Component Type: Hostname
|
|
Returns: google.com
|
|
|
|
Name: HTTP Referrer - Search Query
|
|
Component Type: Query
|
|
Query Key: q
|
|
Returns: Search query from Google
|
|
```
|
|
|
|
**Use Cases:**
|
|
|
|
```
|
|
Trigger Condition:
|
|
{{HTTP Referrer - Hostname}} contains google
|
|
(fire on traffic from Google)
|
|
|
|
Tag Parameter:
|
|
referrer_domain = {{HTTP Referrer - Hostname}}
|
|
(send referrer domain to analytics)
|
|
```
|
|
|
|
### DOM Element Variable
|
|
|
|
Extracts data from DOM elements using CSS selectors.
|
|
|
|
**Purpose:**
|
|
- Read text from page elements
|
|
- Get attribute values
|
|
- Access dynamic page content
|
|
- Extract structured data
|
|
|
|
**Configuration:**
|
|
|
|
```
|
|
Variable Type: DOM Element
|
|
Selection Method: CSS Selector / ID
|
|
Element Selector: .product-price
|
|
OR
|
|
Element ID: product-sku
|
|
|
|
Attribute Name: (optional)
|
|
data-product-id
|
|
href
|
|
src
|
|
etc.
|
|
```
|
|
|
|
**Examples:**
|
|
|
|
**Extract Text Content:**
|
|
|
|
```
|
|
Name: DOM - Product Price
|
|
Selection Method: CSS Selector
|
|
Element Selector: .product-price
|
|
Returns: "$99.99"
|
|
```
|
|
|
|
**Extract Attribute:**
|
|
|
|
```
|
|
Name: DOM - Product SKU
|
|
Selection Method: ID
|
|
Element ID: product-info
|
|
Attribute Name: data-sku
|
|
Returns: "PROD-12345"
|
|
```
|
|
|
|
**Extract href:**
|
|
|
|
```
|
|
Name: DOM - Canonical URL
|
|
Selection Method: CSS Selector
|
|
Element Selector: link[rel="canonical"]
|
|
Attribute Name: href
|
|
Returns: Canonical URL
|
|
```
|
|
|
|
**Use Cases:**
|
|
|
|
```javascript
|
|
// Product page tracking
|
|
dataLayer.push({
|
|
'event': 'product_view',
|
|
'productSku': {{DOM - Product SKU}},
|
|
'productPrice': {{DOM - Product Price}}
|
|
});
|
|
|
|
// Dynamic content
|
|
Trigger Condition:
|
|
{{DOM - Element Text}} contains "In Stock"
|
|
```
|
|
|
|
**Important:**
|
|
- Element must exist when variable evaluates
|
|
- Returns first matching element
|
|
- Returns empty if element not found
|
|
|
|
## Variable Configuration
|
|
|
|
### Creating Variables
|
|
|
|
1. **Variables → New**
|
|
2. **Click variable configuration area**
|
|
3. **Choose variable type**
|
|
4. **Configure settings**
|
|
5. **Name variable** (use consistent naming convention)
|
|
6. **Save**
|
|
|
|
### Variable Formatting
|
|
|
|
Some variables offer formatting options:
|
|
|
|
**Text Transformations:**
|
|
- Lowercase
|
|
- Uppercase
|
|
- No formatting
|
|
|
|
**URI Decoding:**
|
|
- Decode URI-encoded values
|
|
- Useful for cookies and URLs
|
|
|
|
**Strip www:**
|
|
- Remove "www." from hostnames
|
|
|
|
### Variable Default Values
|
|
|
|
Set fallback values when variable is undefined:
|
|
|
|
```
|
|
Data Layer Variable:
|
|
Set Default Value: ✓
|
|
Default Value: not-set
|
|
```
|
|
|
|
**When to use:**
|
|
- Prevent undefined values in tags
|
|
- Ensure clean data
|
|
- Avoid empty parameters
|
|
|
|
### Variable Version History
|
|
|
|
GTM tracks variable changes:
|
|
|
|
**View History:**
|
|
Variables → Select Variable → Versions tab
|
|
|
|
**Compare Versions:**
|
|
- See what changed
|
|
- Restore previous version
|
|
- Audit trail
|
|
|
|
## Advanced Variable Concepts
|
|
|
|
### Variable Macros
|
|
|
|
Variables can reference other variables:
|
|
|
|
```
|
|
Custom JavaScript Variable:
|
|
function() {
|
|
var path = {{Page Path}};
|
|
var category = {{DLV - Category}};
|
|
|
|
return path + ' | ' + category;
|
|
}
|
|
|
|
Returns: "/products/item | electronics"
|
|
```
|
|
|
|
### Nested Variables
|
|
|
|
Variables within variables:
|
|
|
|
```
|
|
Lookup Table:
|
|
Input Variable: {{DLV - User Type}}
|
|
|
|
Input | Output
|
|
-----------|---------------------------
|
|
premium | {{Constant - Premium ID}}
|
|
standard | {{Constant - Standard ID}}
|
|
```
|
|
|
|
### Variable Precedence
|
|
|
|
When multiple data layer pushes contain the same key:
|
|
|
|
```javascript
|
|
// Initial push
|
|
dataLayer.push({'category': 'electronics'});
|
|
|
|
// Later push
|
|
dataLayer.push({'category': 'computers'});
|
|
|
|
// {{DLV - Category}} returns: "computers" (latest value)
|
|
```
|
|
|
|
**Data Layer Version 2** merges objects:
|
|
|
|
```javascript
|
|
dataLayer.push({
|
|
'user': {
|
|
'id': '123',
|
|
'type': 'premium'
|
|
}
|
|
});
|
|
|
|
dataLayer.push({
|
|
'user': {
|
|
'name': 'John'
|
|
}
|
|
});
|
|
|
|
// Result (merged):
|
|
user: {
|
|
id: '123',
|
|
type: 'premium',
|
|
name: 'John'
|
|
}
|
|
```
|
|
|
|
### Undefined Variable Handling
|
|
|
|
When a variable is undefined:
|
|
|
|
**In Tags:**
|
|
- GTM may send empty string ""
|
|
- Or literal "undefined"
|
|
- Set default values to control behavior
|
|
|
|
**In Triggers:**
|
|
- Undefined ≠ empty string
|
|
- Use "is defined" / "is not defined" operators
|
|
- Check existence before comparing values
|
|
|
|
**Best Practice:**
|
|
|
|
```
|
|
Trigger Condition:
|
|
{{DLV - User ID}} is defined
|
|
AND
|
|
{{DLV - User ID}} does not equal ""
|
|
```
|
|
|
|
### Variable Caching
|
|
|
|
GTM caches variable values during tag firing:
|
|
|
|
**Within single event:**
|
|
- Variable evaluates once
|
|
- Same value used across all tags for that event
|
|
|
|
**Across events:**
|
|
- Variables re-evaluate for each new event
|
|
|
|
**Example:**
|
|
|
|
```javascript
|
|
// Event 1
|
|
dataLayer.push({'event': 'pageview', 'value': 100});
|
|
// {{DLV - Value}} = 100 for all tags firing on this event
|
|
|
|
// Event 2
|
|
dataLayer.push({'event': 'click', 'value': 200});
|
|
// {{DLV - Value}} = 200 for all tags firing on this event
|
|
```
|
|
|
|
## Best Practices
|
|
|
|
### Variable Naming Conventions
|
|
|
|
Use consistent, descriptive naming:
|
|
|
|
```
|
|
[Type Prefix] - [Purpose]
|
|
```
|
|
|
|
**Examples:**
|
|
|
|
- `DLV - User ID` (Data Layer Variable)
|
|
- `JS - Page Category` (Custom JavaScript)
|
|
- `Constant - GA4 Measurement ID`
|
|
- `1P Cookie - Session ID` (First Party Cookie)
|
|
- `URL - UTM Source` (URL Variable)
|
|
- `Regex Table - Page Type`
|
|
- `Lookup - User Tier`
|
|
|
|
**Type Prefixes:**
|
|
|
|
```
|
|
DLV - Data Layer Variable
|
|
JS - Custom JavaScript
|
|
Constant - Constant
|
|
1P Cookie - First Party Cookie
|
|
URL - URL Variable
|
|
HTTP Ref - HTTP Referrer
|
|
DOM - DOM Element
|
|
```
|
|
|
|
### When to Use Constants vs Variables
|
|
|
|
**Use Constant when:**
|
|
- Value never changes (IDs, tokens)
|
|
- Same value across all instances
|
|
- Easy updates needed
|
|
|
|
**Use Data Layer Variable when:**
|
|
- Value changes per page/event
|
|
- Dynamic user data
|
|
- Custom event data
|
|
|
|
**Use Custom JavaScript when:**
|
|
- Need to compute value
|
|
- Transform or combine data
|
|
- Complex logic required
|
|
|
|
### Performance Optimization
|
|
|
|
**Minimize Custom JavaScript:**
|
|
- Use built-in variables when possible
|
|
- Keep code simple and fast
|
|
- Avoid heavy DOM manipulation
|
|
- Cache results when appropriate
|
|
|
|
**Data Layer Best Practices:**
|
|
- Push data before GTM container loads
|
|
- Use consistent naming
|
|
- Structure data logically
|
|
- Don't push PII
|
|
|
|
**Variable Efficiency:**
|
|
- Reuse constants across container
|
|
- Don't create duplicate variables
|
|
- Regular cleanup of unused variables
|
|
|
|
### Debugging Variables
|
|
|
|
**Preview Mode:**
|
|
|
|
1. Enable Preview
|
|
2. Navigate to page
|
|
3. Select event in debug panel
|
|
4. Click "Variables" tab
|
|
5. See all variable values for that event
|
|
|
|
**Console Debugging:**
|
|
|
|
```javascript
|
|
// Check data layer
|
|
console.log(dataLayer);
|
|
|
|
// Check specific variable in GTM object
|
|
console.log(google_tag_manager['GTM-XXXXXX'].dataLayer.get('variableName'));
|
|
```
|
|
|
|
**Common Issues:**
|
|
|
|
**Variable is undefined:**
|
|
- Data not in data layer yet
|
|
- Typo in variable name
|
|
- Data layer push after GTM evaluated
|
|
|
|
**Variable has wrong value:**
|
|
- Data layer structure mismatch
|
|
- Timing issue (evaluated too early/late)
|
|
- Cached old value
|
|
|
|
**Variable not updating:**
|
|
- Data layer not pushing new value
|
|
- Variable caching within event
|
|
- Need to use Custom Event to re-evaluate
|
|
|
|
## Resources
|
|
|
|
### Official Documentation
|
|
|
|
- [GTM Variables Guide](https://support.google.com/tagmanager/topic/7182737)
|
|
- [Built-in Variables Reference](https://support.google.com/tagmanager/answer/7182738)
|
|
- [Data Layer Variables](https://developers.google.com/tag-platform/tag-manager/web/datalayer)
|
|
- [Custom JavaScript Variables](https://support.google.com/tagmanager/answer/7683362)
|
|
|
|
### Related GTM Skills
|
|
|
|
- [GTM Tags](./tags.md) - Comprehensive tag documentation
|
|
- [GTM Triggers](./triggers.md) - Trigger types and configuration
|
|
- [GTM Data Layer](../../gtm-datalayer/gtm-datalayer/references/datalayer-fundamentals.md) - Data layer implementation
|
|
- [GTM Best Practices](./best-practices.md) - Naming, ES5, RE2 regex
|
|
|
|
### Tools
|
|
|
|
- [Babel REPL](https://babeljs.io/repl) - ES6 to ES5 transpilation
|
|
- [Regex101](https://regex101.com/) - Test regex (select "Golang" for RE2)
|
|
- [GTM Preview Mode](https://support.google.com/tagmanager/answer/6107056)
|
|
- [Data Layer Inspector Chrome Extension](https://chrome.google.com/webstore/detail/datalayer-checker/ffljdddodmkedhkcjhpmdajhjdbkogke)
|
|
|
|
### Community
|
|
|
|
- [GTM Community Forum](https://support.google.com/tagmanager/community)
|
|
- [Simo Ahava's Blog](https://www.simoahava.com/)
|
|
- [Analytics Mania](https://www.analyticsmania.com/)
|
|
- [MeasureSchool](https://measureschool.com/)
|