# Google Tag Manager - Triggers ## Overview Triggers define when tags should fire in Google Tag Manager. They are the "when" component of the Tag-Trigger-Variable system that powers GTM implementations. **What Triggers Do:** - Control when tags execute - Evaluate conditions based on page events and user interactions - Filter tag firing using conditions and variables - Support multiple events types (page views, clicks, form submissions, custom events) ## Regular Expressions in Triggers (RE2 Format) **CRITICAL:** Google Tag Manager uses **RE2 (GoLang regex)** format, NOT standard JavaScript/PCRE regex. ### RE2 vs Standard Regex **NOT Supported in RE2:** - ❌ Backreferences: `\1`, `\2`, `\g{name}` - ❌ Lookahead assertions: `(?=...)`, `(?!...)` - ❌ Lookbehind assertions: `(?<=...)`, `(?...)` - ✅ Alternation: `|` - ✅ Case-insensitive flag: `(?i)` ### Common RE2 Patterns for Triggers **Match Page URLs:** ```regex # Exact match ^https://example\.com/page$ # Contains specific path /checkout/ # Query parameter present \?utm_source= # Multiple domains ^https://(www\.)?example\.(com|net) # Product pages (ends with digits) /product/\d+$ # Any subdomain ^https://[^.]+\.example\.com/ ``` **Match Click URLs:** ```regex # PDF downloads \.pdf$ # External links (not your domain) ^https?://(?!example\.com) # Telephone links ^tel: # Email links ^mailto: # File downloads \.(pdf|docx?|xlsx?|zip)$ ``` **Match Form IDs and Classes:** ```regex # Form ID starts with "contact" ^contact # Form class contains "newsletter" newsletter # Multiple form IDs ^(contact-form|signup-form|subscribe)$ ``` **Case-Insensitive Matching:** ```regex # Case-insensitive flag at start (?i)^/checkout # Matches: /checkout, /Checkout, /CHECKOUT (?i)\.pdf$ # Matches: .pdf, .PDF, .Pdf ``` **Path Matching:** ```regex # Blog posts with year/month/day structure ^/blog/\d{4}/\d{2}/\d{2}/ # Category pages with optional subcategory ^/category/[\w-]+(/[\w-]+)?$ # User profile pages ^/user/[^/]+$ # API endpoints ^/api/v\d+/ ``` **See Also:** - [Best Practices - Regular Expressions in GTM](./best-practices.md#regular-expressions-in-google-tag-manager-re2-format) for RE2 guidelines - Complete RE2 syntax: `.claude/skills/gtm-core/gtm-core/references/google-rew-regular-expressions-syntax.txt` ## Trigger Basics ### How Triggers Work 1. **Event occurs** - User action or page state change 2. **Trigger evaluates** - GTM checks trigger conditions 3. **Conditions match** - All filters evaluate to true 4. **Tag fires** - Associated tag executes ### Trigger Components - **Trigger Type** - Defines the event (Page View, Click, Custom Event, etc.) - **Trigger Conditions** - Filters that must match for trigger to fire - **Operator** - How to compare values (equals, contains, matches regex, etc.) - **Value** - The expected value to match against ### Trigger Evaluation Triggers evaluate on each GTM event: ``` Event: gtm.dom → Check all triggers for event type "DOM Ready" → Evaluate each trigger's conditions → Fire matching tags ``` ### Multiple Conditions (AND Logic) When a trigger has multiple conditions, ALL must be true: ``` Condition 1: Page Path contains /checkout AND Condition 2: Referrer contains google.com AND Condition 3: Cookie - user_type - equals - premium All three conditions must match for trigger to fire ``` ### Some/All Pages or Elements Many triggers offer "Some" or "All" options: **All Pages:** - Fires on every page - No additional conditions **Some Pages:** - Fires only when conditions match - Requires at least one filter condition **Example:** ``` Trigger Type: Page View This trigger fires on: Some Page Views Page Path contains /products/ AND Page Hostname equals www.example.com ``` ## Trigger Types ### Pageview Triggers #### Page View Fires when GTM container loads on a page. **Event:** `gtm.js` **Common Use Cases:** - Fire tags on all pages - Track specific page views - Initialize analytics configuration **Configuration:** ``` Trigger Type: Page View This trigger fires on: All Pages ``` or ``` Trigger Type: Page View This trigger fires on: Some Page Views Page Path contains /products/ ``` **Examples:** ``` Name: Pageview - All Pages Type: Page View Fires on: All Pages Use: Fire GA4 Config tag everywhere ``` ``` Name: Pageview - Thank You Pages Type: Page View Fires on: Some Page Views Page Path matches RegEx: /(thank-you|confirmation|success) Use: Fire conversion tags ``` ``` Name: Pageview - Product Category Type: Page View Fires on: Some Page Views Page Path starts with /category/ AND Page Path does not contain /admin/ Use: Track category page views ``` #### DOM Ready Fires when the DOM (Document Object Model) is fully constructed but before all resources load. **Event:** `gtm.dom` **Timing:** After DOM built, before images/stylesheets fully loaded **Common Use Cases:** - Access DOM elements before page fully renders - Set up event listeners - Modify page content early - Better performance than Window Loaded for tags that don't need full page load **Configuration:** ``` Trigger Type: DOM Ready This trigger fires on: All Pages ``` **Example:** ``` Name: DOM Ready - All Pages Type: DOM Ready Fires on: All Pages Use: Initialize chat widget before page fully loads ``` **Timeline:** ``` 1. GTM Container Loads → Page View (gtm.js) 2. DOM Constructed → DOM Ready (gtm.dom) 3. All Resources Loaded → Window Loaded (gtm.load) ``` #### Window Loaded Fires when the page is fully loaded, including all resources (images, scripts, stylesheets). **Event:** `gtm.load` **Timing:** After all page resources completely loaded **Common Use Cases:** - Tags that need complete page context - Performance measurements (load time) - Tags that shouldn't impact page speed - Third-party widgets that depend on full page load **Configuration:** ``` Trigger Type: Window Loaded This trigger fires on: All Pages ``` **Example:** ``` Name: Window Loaded - Home Page Type: Window Loaded Fires on: Some Page Views Page Path equals / Use: Fire non-critical tags after page fully loads ``` **When to Use Each Pageview Trigger:** | Trigger Type | Use When | Performance Impact | |-------------|----------|-------------------| | Page View | Need tag to fire immediately | Low | | DOM Ready | Need DOM access, don't need resources | Medium | | Window Loaded | Need full page context, non-critical tags | High (delayed) | ### Click Triggers #### All Elements Fires when user clicks any element on the page. **Event:** `gtm.click` **Common Use Cases:** - Track button clicks - Track link clicks - Track custom element interactions - Track clicks on dynamically generated elements **Built-in Click Variables:** - `{{Click Element}}` - The clicked DOM element - `{{Click Classes}}` - CSS classes of clicked element - `{{Click ID}}` - ID attribute of clicked element - `{{Click Target}}` - Target attribute value - `{{Click URL}}` - href attribute (for links) - `{{Click Text}}` - Text content of clicked element **Configuration:** ``` Trigger Type: All Elements This trigger fires on: Some Clicks Click Text equals Sign Up ``` **Examples:** ``` Name: Click - CTA Buttons Type: All Elements Fires on: Some Clicks Click Classes contains cta-button Use: Track call-to-action button clicks ``` ``` Name: Click - Add to Cart Type: All Elements Fires on: Some Clicks Click ID equals add-to-cart-btn Use: Track add to cart events ``` ``` Name: Click - Outbound Links Type: All Elements Fires on: Some Clicks Click URL does not contain example.com AND Click URL matches RegEx: ^https?:// Use: Track external link clicks ``` ``` Name: Click - Download PDFs Type: All Elements Fires on: Some Clicks Click URL matches RegEx: \.pdf$ Use: Track PDF downloads ``` **Enable Click Variables:** Variables → Configure Built-In Variables → Clicks #### Just Links Fires only when user clicks links (`` tags with `href` attribute). **Event:** `gtm.linkClick` **Optimized for:** Link tracking with automatic wait time for tag to fire before navigation **Wait for Tags:** GTM waits up to 2 seconds for tags to fire before following link **Common Use Cases:** - Track navigation links - Track external links - Track file downloads - Outbound link tracking **Configuration:** ``` Trigger Type: Just Links This trigger fires on: Some Link Clicks Click URL contains example.com Wait for Tags: 2000 milliseconds Check Validation: false ``` **Examples:** ``` Name: Click - External Links Type: Just Links Fires on: Some Link Clicks Click URL does not contain {{Page Hostname}} AND Click URL matches RegEx: ^https?:// Use: Track clicks to external websites ``` ``` Name: Click - Email Links Type: Just Links Fires on: Some Link Clicks Click URL starts with mailto: Use: Track email link clicks ``` ``` Name: Click - Phone Links Type: Just Links Fires on: Some Link Clicks Click URL starts with tel: Use: Track phone number clicks ``` ``` Name: Click - File Downloads Type: Just Links Fires on: Some Link Clicks Click URL matches RegEx: \.(pdf|docx?|xlsx?|zip|csv)$ Use: Track file download clicks ``` **Settings:** - **Wait for Tags:** Max time (ms) to wait before following link (default: 2000ms) - **Check Validation:** Wait for form validation before firing (default: false) - **Enable when:** Additional conditions for trigger to be active **All Elements vs Just Links:** | Feature | All Elements | Just Links | |---------|-------------|------------| | Fires on | Any element | Only `` tags | | Wait for tags | No | Yes (prevents navigation) | | Performance | Lower (all clicks) | Better (links only) | | Use for | Buttons, divs, any element | Navigation, downloads | ### User Engagement Triggers #### Element Visibility Fires when a specific element becomes visible in the viewport. **Event:** `gtm.elementVisibility` **Common Use Cases:** - Track ad impressions - Track scroll-to-content - Lazy load tracking - Measure content engagement **Configuration:** ``` Trigger Type: Element Visibility Selection Method: ID / CSS Selector Element ID: featured-product OR Element Selector: .product-card When to fire this trigger: ☑ Once per page ☐ Once per element ☐ Every time an element appears on screen Minimum Percent Visible: 50% Minimum On-Screen Duration: 1000 milliseconds This trigger fires on: All Pages ``` **Examples:** ``` Name: Visibility - Hero Banner Type: Element Visibility Element ID: hero-banner Fires when: Once per page Percent Visible: 50% On-Screen Duration: 2000ms Use: Track hero banner impressions ``` ``` Name: Visibility - Product Cards Type: Element Visibility Element Selector: .product-card Fires when: Once per element Percent Visible: 75% On-Screen Duration: 500ms Fires on: Some Pages Page Path contains /products/ Use: Track which products users view ``` **Advanced Options:** - **Observe DOM changes** - Track dynamically added elements - **Advanced matching** - Multiple selectors using CSS **Built-in Variables:** Enable Element Visibility variables: - `{{Percent Visible}}` - Percentage of element visible - `{{On-Screen Duration}}` - How long visible (ms) #### Form Submission Fires when a user submits a form. **Event:** `gtm.formSubmit` **Common Use Cases:** - Track form submissions - Track lead generation - Track newsletter signups - Fire conversion tags **Configuration:** ``` Trigger Type: Form Submission This trigger fires on: All Forms OR This trigger fires on: Some Forms Form ID equals contact-form Enable when: (optional conditions) Wait for Tags: 2000 milliseconds Check Validation: True ``` **Examples:** ``` Name: Form Submit - Contact Form Type: Form Submission Fires on: Some Forms Form ID equals contact-form OR Form Classes contains contact-form Check Validation: True Use: Track contact form submissions ``` ``` Name: Form Submit - Newsletter Signup Type: Form Submission Fires on: Some Forms Form ID matches RegEx: (newsletter|subscribe) Use: Track newsletter signups ``` ``` Name: Form Submit - All Forms Type: Form Submission Fires on: All Forms Check Validation: True Except: Form ID equals search-form (handled separately) Use: Track all form submissions except search ``` **Settings:** - **Wait for Tags:** Time to wait for tags before form submits (default: 2000ms) - **Check Validation:** Only fire if form passes HTML5 validation (recommended: true) **Built-in Form Variables:** Enable in Variables → Configure: - `{{Form ID}}` - Form's ID attribute - `{{Form Classes}}` - Form's CSS classes - `{{Form Target}}` - Form's target attribute - `{{Form URL}}` - Form's action URL - `{{Form Text}}` - Text content within form **Important:** Never capture form field values containing PII (emails, names, phone numbers). #### Scroll Depth Fires when user scrolls to specific depths on a page. **Event:** `gtm.scrollDepth` **Common Use Cases:** - Measure content engagement - Track how far users scroll - Identify drop-off points - Understand content consumption **Configuration:** ``` Trigger Type: Scroll Depth Vertical Scroll Depths: Percentages: 25, 50, 75, 90, 100 OR Pixels: 500, 1000, 2000 This trigger fires on: All Pages OR This trigger fires on: Some Pages Page Path contains /blog/ ``` **Examples:** ``` Name: Scroll Depth - Blog Posts Type: Scroll Depth Percentages: 25, 50, 75, 100 Fires on: Some Pages Page Path starts with /blog/ Use: Measure blog post engagement ``` ``` Name: Scroll Depth - Home Page Type: Scroll Depth Percentages: 10, 25, 50, 75, 90 Fires on: Some Pages Page Path equals / Use: Track homepage scroll behavior ``` ``` Name: Scroll Depth - Long Form Content Type: Scroll Depth Pixels: 1000, 2000, 3000, 4000 Fires on: Some Pages Page Path contains /guides/ Use: Track reading depth on long guides ``` **Built-in Scroll Variables:** Enable Scroll Depth variables: - `{{Scroll Depth Threshold}}` - The threshold that was reached (e.g., "75") - `{{Scroll Depth Units}}` - "percent" or "pixels" - `{{Scroll Direction}}` - "vertical" or "horizontal" **Best Practices:** - Don't track too many thresholds (max 5-7) - Use percentages for responsive design - Consider page length when setting thresholds - Combine with time on page for engagement metrics #### YouTube Video Fires when users interact with embedded YouTube videos. **Event:** `gtm.video` **Requires:** YouTube video embedded via iframe **Common Use Cases:** - Track video starts - Track video completion - Measure video engagement - Track video progress **Configuration:** ``` Trigger Type: YouTube Video Capture: Start, Complete, Pause, Seeking, Buffering, Progress Add JavaScript API support to all HTML5 videos: ☑ Progress Threshold (%): 10, 25, 50, 75, 90 This trigger fires on: Some Videos Video URL contains product-demo ``` **Examples:** ``` Name: Video - All Interactions Type: YouTube Video Capture: ☑ Start ☑ Complete ☑ Pause ☑ Progress Progress: 25, 50, 75 Fires on: All Videos Use: Track all video engagement ``` ``` Name: Video - Product Demo Complete Type: YouTube Video Capture: ☑ Complete Fires on: Some Videos Video URL contains product-demo OR Video Title contains Product Demo Use: Track product demo completion ``` **Built-in Video Variables:** Enable Video variables: - `{{Video Status}}` - start, pause, complete, progress, etc. - `{{Video URL}}` - YouTube video URL - `{{Video Title}}` - Video title from YouTube - `{{Video Duration}}` - Total video length (seconds) - `{{Video Current Time}}` - Playback position (seconds) - `{{Video Percent}}` - Percentage watched - `{{Video Provider}}` - "youtube" - `{{Video Visible}}` - true/false if video in viewport **Supported Video Events:** - **Start** - Video playback begins - **Complete** - Video finishes - **Pause** - User pauses video - **Seeking** - User scrubs to different time - **Buffering** - Video buffering - **Progress** - Reaches progress thresholds ### Other Triggers #### Custom Event Fires when a specific custom event is pushed to the data layer. **Event:** Custom event name from `dataLayer.push()` **Common Use Cases:** - Track business events (purchase, signup, login) - Track SPA (Single Page App) page views - Track custom user interactions - Integrate with custom application logic **Configuration:** ``` Trigger Type: Custom Event Event name: purchase Use regex matching: ☐ This trigger fires on: All Custom Events OR This trigger fires on: Some Custom Events {{Transaction Value}} greater than 100 ``` **Data Layer Push:** ```javascript // Push custom event to data layer dataLayer.push({ 'event': 'purchase', 'transactionId': 'T12345', 'transactionTotal': 99.99, 'transactionProducts': [ { 'sku': 'PROD-001', 'name': 'Product Name', 'price': 99.99, 'quantity': 1 } ] }); ``` **Examples:** ``` Name: Custom Event - purchase Type: Custom Event Event name: purchase Fires on: All Custom Events Use: Fire conversion tags on purchase ``` ``` Name: Custom Event - High Value Purchase Type: Custom Event Event name: purchase Fires on: Some Custom Events {{DLV - Transaction Total}} greater than 500 Use: Track high-value purchases separately ``` ``` Name: Custom Event - Virtual Pageview Type: Custom Event Event name: virtualPageview Use: Track SPA navigation ``` ``` Name: Custom Event - User Login Type: Custom Event Event name: user_login Fires on: Some Custom Events {{DLV - User Type}} equals premium Use: Track premium user logins ``` **Regex Matching:** ``` Event name: (purchase|transaction|order) Use regex matching: ☑ Matches: purchase, transaction, or order events ``` **Best Practices:** - Use consistent, descriptive event names - Use snake_case naming: `user_signup`, `add_to_cart` - Document all custom events - Push event first in data layer object #### Timer Fires at specified time intervals. **Event:** `gtm.timer` **Common Use Cases:** - Track engaged time on page - Send heartbeat events - Track video watch time - Measure time to conversion **Configuration:** ``` Trigger Type: Timer Event Name: engagement_timer (custom name for this timer) Interval: 30000 milliseconds (30 seconds) Limit: 10 times This trigger fires on: All Pages OR This trigger fires on: Some Pages Page Path contains /article/ ``` **Examples:** ``` Name: Timer - Engagement Heartbeat Type: Timer Event Name: engagement_timer Interval: 30000 (30 seconds) Limit: 20 Fires on: All Pages Use: Track engaged time on site ``` ``` Name: Timer - Article Reading Time Type: Timer Event Name: article_timer Interval: 15000 (15 seconds) Limit: 40 Fires on: Some Pages Page Path starts with /blog/ OR Page Path starts with /articles/ Use: Measure article reading time ``` **Built-in Timer Variables:** - `{{Timer Interval}}` - Configured interval (ms) - `{{Event}}` - Will equal the Event Name you configured **Calculating Elapsed Time:** Combine with Custom JavaScript variable: ```javascript function() { var interval = {{Timer Interval}}; var limit = 20; // Your configured limit // Calculate elapsed time return interval * limit / 1000; // Returns seconds } ``` **Settings:** - **Event Name** - Custom name to identify this timer - **Interval** - Time between fires (milliseconds) - **Limit** - Max number of times to fire (blank = unlimited) #### History Change Fires when the URL changes without a full page reload (Single Page Applications). **Event:** `gtm.historyChange` **Common Use Cases:** - Track SPA (Single Page App) navigation - Track AJAX page transitions - Track URL hash changes - Track pushState/replaceState events **Configuration:** ``` Trigger Type: History Change This trigger fires on: All History Changes OR This trigger fires on: Some History Changes Page Path contains /app/ ``` **Examples:** ``` Name: History Change - SPA Navigation Type: History Change Fires on: All History Changes Use: Track virtual pageviews in React/Vue/Angular apps ``` ``` Name: History Change - App Section Type: History Change Fires on: Some History Changes Page Path starts with /app/ AND Page Path does not contain /app/admin/ Use: Track navigation within app section ``` **When URLs Change:** The trigger fires when: - `history.pushState()` is called - `history.replaceState()` is called - Hash changes (`#section`) - Back/forward browser navigation (within SPA) **Common Implementation:** ```javascript // In your SPA, after route change: dataLayer.push({ 'event': 'virtualPageview', 'pagePath': '/new-page', 'pageTitle': 'New Page Title' }); ``` **Built-in Variables:** Standard page variables update automatically: - `{{Page URL}}` - `{{Page Path}}` - `{{Page Hostname}}` #### JavaScript Error Fires when JavaScript errors occur on the page. **Event:** `gtm.jsError` **Common Use Cases:** - Track JavaScript errors - Monitor site health - Debug issues in production - Send errors to error tracking tools **Configuration:** ``` Trigger Type: JavaScript Error This trigger fires on: All Errors OR This trigger fires on: Some Errors Error Message does not contain "Non-critical warning" ``` **Examples:** ``` Name: JavaScript Error - All Errors Type: JavaScript Error Fires on: All Errors Use: Track all JavaScript errors ``` ``` Name: JavaScript Error - Critical Only Type: JavaScript Error Fires on: Some Errors Error Message does not contain "Warning" AND Error URL equals {{Page URL}} Use: Track only critical errors from own code ``` **Built-in Error Variables:** Enable Error variables: - `{{Error Message}}` - The error message text - `{{Error URL}}` - URL where error occurred - `{{Error Line}}` - Line number in source file - `{{Debug Mode}}` - true/false if GTM in debug mode **Example Error Tracking Tag:** ``` Tag: GA4 - Event - JavaScript Error Event Name: javascript_error Event Parameters: error_message: {{Error Message}} error_url: {{Error URL}} error_line: {{Error Line}} page_url: {{Page URL}} Trigger: JavaScript Error - All Errors ``` **Filtering Noise:** Common errors to exclude: ``` Error Message does not contain "ResizeObserver loop limit exceeded" Error Message does not contain "Script error." Error Message does not contain "Non-Error promise rejection captured" Error URL equals {{Page URL}} (exclude third-party script errors) ``` ## Trigger Configuration ### Trigger Conditions and Filters Triggers use conditions to determine when to fire. Conditions compare a variable to a value using an operator. **Condition Structure:** ``` [Variable] [Operator] [Value] ``` **Example:** ``` {{Page Path}} contains /checkout ``` ### Filter Operators #### String Operators **equals** - Exact match (case-sensitive) - Example: `{{Click ID}} equals submit-btn` **does not equal** - Not an exact match - Example: `{{Page Hostname}} does not equal localhost` **contains** - Value contains substring - Example: `{{Page URL}} contains /product/` **does not contain** - Value doesn't contain substring - Example: `{{Click URL}} does not contain example.com` **starts with** - Value begins with string - Example: `{{Page Path}} starts with /blog/` **ends with** - Value ends with string - Example: `{{Click URL}} ends with .pdf` **matches RegEx** - Value matches RE2 regular expression - Example: `{{Page Path}} matches RegEx ^/category/\d+$` - **IMPORTANT:** Uses RE2 format (see section above) **matches RegEx (ignore case)** - Case-insensitive regex match - Example: `{{Click URL}} matches RegEx (ignore case) \.pdf$` - Matches: .pdf, .PDF, .Pdf #### Numeric Operators **equals** - Numeric equality - Example: `{{DLV - Cart Items}} equals 3` **does not equal** - Numeric inequality - Example: `{{Random Number}} does not equal 0` **less than** - Value < number - Example: `{{DLV - Transaction Value}} less than 50` **less than or equal to** - Value <= number - Example: `{{Scroll Depth Threshold}} less than or equal to 50` **greater than** - Value > number - Example: `{{DLV - Product Price}} greater than 100` **greater than or equal to** - Value >= number - Example: `{{Video Percent}} greater than or equal to 75` #### Boolean Operators **is true** - Variable evaluates to true - Example: `{{Cookie - user_logged_in}} is true` **is false** - Variable evaluates to false - Example: `{{Cookie - consent_given}} is false` #### Existence Operators **is defined** - Variable has a value (not undefined/null) - Example: `{{DLV - User ID}} is defined` **is not defined** - Variable is undefined/null/empty - Example: `{{Cookie - returning_visitor}} is not defined` ### Using RE2 Regex in Triggers Regular expressions enable powerful pattern matching in triggers. **URL Matching Examples:** ``` # Match checkout pages {{Page Path}} matches RegEx: ^/checkout # Match product pages with SKU {{Page Path}} matches RegEx: ^/product/[A-Z0-9-]+$ # Match blog posts with date structure {{Page URL}} matches RegEx: /blog/\d{4}/\d{2}/\d{2}/ # Match any subdomain {{Page Hostname}} matches RegEx: ^[^.]+\.example\.com$ # Match query parameter presence {{Page URL}} matches RegEx: [?&]utm_source= # Match multiple page types {{Page Path}} matches RegEx: ^/(checkout|cart|payment) ``` **Click URL Matching:** ``` # External links (not your domain) {{Click URL}} matches RegEx: ^https?://(?!example\.com) # File downloads {{Click URL}} matches RegEx: \.(pdf|docx?|xlsx?|zip|csv)(\?|$) # Email links {{Click URL}} matches RegEx: ^mailto:[\w.+-]+@[\w.-]+\.\w{2,}$ # Phone links {{Click URL}} matches RegEx: ^tel:\+?[\d\s\-()]+$ # Anchor links (same page) {{Click URL}} matches RegEx: ^#[^/] ``` **Element ID/Class Matching:** ``` # Button IDs starting with "btn-" {{Click ID}} matches RegEx: ^btn- # Classes containing "cta" or "call-to-action" {{Click Classes}} matches RegEx: (cta|call-to-action) # Form IDs matching pattern {{Form ID}} matches RegEx: ^(contact|signup|newsletter)-form$ ``` **Text Content Matching:** ``` # Case-insensitive "buy now" or "purchase" {{Click Text}} matches RegEx (ignore case): (buy now|purchase) # Numbers in click text {{Click Text}} matches RegEx: \d+ # Specific patterns {{Click Text}} matches RegEx: ^(Sign Up|Subscribe|Join)$ ``` **Common Regex Patterns:** ```regex # Match digits \d+ # Match word characters \w+ # Match optional whitespace \s* # Match URL path segment /[\w-]+ # Match query parameter [?&]param=([^&]+) # Match file extension \.(ext1|ext2|ext3)$ # Case-insensitive (?i)pattern # Start of string ^pattern # End of string pattern$ # Optional group (pattern)? # Multiple occurrences pattern{2,5} ``` ### Multiple Conditions (AND/OR Logic) **AND Logic (within a trigger):** All conditions must match: ``` Trigger: Pageview - Product Category Pages Type: Page View Fires on: Some Page Views {{Page Path}} starts with /category/ AND {{Page Path}} does not contain /admin/ AND {{Cookie - user_type}} equals customer ``` All three conditions must be true. **OR Logic (multiple triggers):** Create separate triggers for OR logic: ``` Tag: GA4 - Event - Conversion Firing Triggers: - Custom Event - purchase - Custom Event - transaction - Custom Event - order_complete Tag fires if ANY trigger matches (OR logic) ``` **Complex Logic:** Combine AND within triggers, OR across triggers: ``` Trigger 1: High Value Purchase {{Custom Event}} equals purchase AND {{DLV - Transaction Value}} greater than 500 Trigger 2: Premium User Purchase {{Custom Event}} equals purchase AND {{DLV - User Type}} equals premium Tag fires on: (Trigger 1) OR (Trigger 2) ``` ### Built-in Variables for Triggers Enable built-in variables in Variables → Configure: **Page Variables:** - `{{Page URL}}` - Full page URL - `{{Page Hostname}}` - example.com - `{{Page Path}}` - /category/products - `{{Referrer}}` - Previous page URL **Click Variables:** - `{{Click Element}}` - Clicked DOM element - `{{Click Classes}}` - Element CSS classes - `{{Click ID}}` - Element ID - `{{Click URL}}` - Link href - `{{Click Text}}` - Element text content **Form Variables:** - `{{Form Element}}` - Form DOM element - `{{Form Classes}}` - Form CSS classes - `{{Form ID}}` - Form ID - `{{Form URL}}` - Form action URL - `{{Form Text}}` - Form text content **Utility Variables:** - `{{Container ID}}` - GTM container ID - `{{Random Number}}` - Random 0-2147483647 - `{{Environment Name}}` - Live/Preview/Latest ## Advanced Trigger Concepts ### Trigger Groups Combine multiple triggers to create complex firing logic. **Trigger Group:** Create a trigger group in GTM interface to: - Require ALL triggers in group (AND logic across triggers) - Simplify complex conditions **Use Case:** Fire tag only when user is logged in AND on checkout page AND cart value > $50 ### Trigger Firing Limits Some triggers support limits: **Timer Trigger:** - Limit: Maximum number of times to fire **Element Visibility:** - Once per page - Once per element - Every time element appears ### Auto-Event Variables Many triggers create auto-event variables: **Click Triggers:** - Automatically populate Click variables **Form Triggers:** - Automatically populate Form variables **Video Triggers:** - Automatically populate Video variables **Scroll Triggers:** - Automatically populate Scroll variables Enable these in Variables → Configure Built-In Variables. ### Event Callbacks Execute code after tag fires using `eventCallback`: ```javascript dataLayer.push({ 'event': 'purchase', 'transactionId': 'T12345', 'eventCallback': function() { // Execute after tags fire console.log('Purchase tags fired'); // Redirect user window.location.href = '/thank-you'; }, 'eventTimeout': 2000 }); ``` ## Best Practices ### Trigger Naming Conventions Use consistent, descriptive naming: ``` [Type] - [Condition] - [Description] ``` **Examples:** - `Pageview - All Pages` - `Pageview - Product Pages` - `Click - CTA Buttons` - `Click - External Links` - `Custom Event - purchase` - `Form Submit - Contact Form` - `Scroll Depth - Blog Posts` - `Timer - Engagement Tracking` ### Testing Triggers **Preview Mode:** 1. Enable Preview in GTM 2. Navigate to test page 3. Perform action (click, scroll, etc.) 4. Check "Tags Fired" in debug panel 5. Verify trigger conditions in debug panel **Debug Checklist:** - [ ] Trigger fires at correct time - [ ] All conditions evaluate correctly - [ ] Variables populate with expected values - [ ] No false positives (unwanted firing) - [ ] No false negatives (should fire but doesn't) ### Debugging Trigger Issues **Trigger Not Firing:** 1. Check trigger conditions - are they too restrictive? 2. Verify built-in variables are enabled 3. Check data layer for custom events 4. Review trigger type matches event 5. Check for blocking triggers on tag **Trigger Firing Too Often:** 1. Add more specific conditions 2. Use "Once per page/element" for visibility triggers 3. Add filters to exclude unwanted pages 4. Check for duplicate triggers **Variables Not Populating:** 1. Enable built-in variables in Variables section 2. Check variable names match exactly (case-sensitive) 3. Verify data layer structure for DLV 4. Check timing - is data available when trigger fires? ### Performance Considerations **Minimize Click Listeners:** - Use "Just Links" for link tracking (more efficient than "All Elements") - Add specific conditions to reduce evaluation overhead - Don't track all clicks indiscriminately **Optimize Scroll Depth:** - Limit scroll thresholds (5-7 maximum) - Only enable on relevant pages - Use percentages for responsive design **Timer Triggers:** - Use reasonable intervals (not < 5 seconds) - Set limits to prevent infinite firing - Only enable on necessary pages **Element Visibility:** - Use specific selectors (ID preferred over class) - Enable "Observe DOM changes" only when needed - Limit to relevant pages ## Resources ### Official Documentation - [GTM Triggers Overview](https://support.google.com/tagmanager/topic/7679108) - [Trigger Types Reference](https://support.google.com/tagmanager/answer/7679319) - [Auto-Event Variables](https://support.google.com/tagmanager/answer/7679316) - [RE2 Syntax Reference](https://github.com/google/re2/wiki/Syntax) ### Related GTM Skills - [GTM Tags](./tags.md) - Comprehensive tag documentation - [GTM Variables](./variables.md) - Variable types and configuration - [GTM Data Layer](../../gtm-datalayer/gtm-datalayer/references/datalayer-fundamentals.md) - Data layer implementation - [GTM Best Practices](./best-practices.md) - Naming, organization, regex usage ### Tools - [Regex101](https://regex101.com/) - Test regex patterns (select "Golang" for RE2) - [GTM Preview Mode](https://support.google.com/tagmanager/answer/6107056) - [Google Tag Assistant](https://tagassistant.google.com/) ### 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/)