Skip to content

Click Triggers

Click triggers are one of the most-used trigger types in GTM — and one of the most commonly misconfigured. The two varieties — All Clicks and Just Links — seem straightforward but have behavioral nuances that bite you when you least expect it. This article covers both trigger types, their variables, and the CSS selector patterns that make them actually useful.

GTM offers two click trigger subtypes. The distinction matters.

All Clicks (gtm.click) fires on every click event that bubbles up to the document level. It is completely indiscriminate — a click on a button, a div, an image, a paragraph, or anything else will fire this trigger. The Click variables tell you which element was clicked.

Just Links (gtm.linkClick) fires only when the click target is an <a> element or a descendant of one. It provides the same Click variables but also adds link-specific behavior: a “Check Validation” option that verifies the link is a valid URL, and a “Wait for Tags” option that briefly delays navigation to allow tags to fire before the browser navigates away.

Use Just Links for anchor-based navigation tracking (outbound links, download tracking, email/phone links). Use All Clicks for everything else — buttons, interactive UI elements, custom components.

GTM uses event delegation: a single event listener attached to document captures all click events that bubble up. When a click occurs, GTM inspects the event target and its closest ancestor <a> element (for Just Links) to determine what was clicked.

This has an important implication: GTM sees the actual element that received the click, not necessarily the element you intended to track. If a user clicks the icon inside a button, GTM’s Click Element will be the icon (<svg> or <img>), not the button (<button>). This is the number one source of click trigger confusion.

<!-- User clicks the icon inside the button -->
<button data-track="cta-purchase">
<svg class="icon">...</svg> <!-- ← GTM sees THIS as Click Element -->
Buy Now
</button>

The fix is to target the parent element in your trigger conditions using the descendant wildcard pattern, covered below.

Enable these built-in variables in GTM under Variables → Built-In Variables → Clicks. Enable all of them from day one — they are useful for debugging even if you are not currently using them in triggers.

VariableValueExample
Click ElementThe DOM element that received the click<button class="btn-primary">
Click ClassesSpace-separated class names of the clicked elementbtn btn-primary cta
Click IDThe id attribute of the clicked elementpurchase-button
Click TargetThe target attribute_blank
Click URLThe href attribute (for links)https://checkout.example.com
Click TextThe visible text content of the clicked elementBuy Now

Targeting specific elements with CSS selectors

Section titled “Targeting specific elements with CSS selectors”

The “matches CSS selector” condition is the most precise way to target click triggers. It lets you use standard CSS selectors to identify the element — the same selectors you use in stylesheets and document.querySelector() calls.

/* Any button with a specific data attribute */
button[data-track="cta-purchase"]
/* Anchor links to PDF files */
a[href$=".pdf"]
/* External links (not starting with your domain) */
a[href^="http"]:not([href*="yourdomain.com"])
/* Links to specific domains */
a[href*="amazon.com"]
/* Phone links */
a[href^="tel:"]
/* Email links */
a[href^="mailto:"]

The descendant wildcard — the pattern that fixes child element clicks

Section titled “The descendant wildcard — the pattern that fixes child element clicks”

Because GTM sees the innermost clicked element (not the container), your CSS selector condition might fail when users click icons or text inside your target element. The fix: include both the element and its descendants:

/* This matches the button AND anything clicked inside it */
button[data-track], button[data-track] *

The button[data-track] * part means “any element that is a descendant of a button with data-track.” When a user clicks the <svg> inside the button, the Click Element is the <svg>, which matches button[data-track] *.

Testing selectors before configuring triggers

Section titled “Testing selectors before configuring triggers”

Always test your CSS selector in the browser console before building a trigger around it:

// Open DevTools console and run:
document.querySelectorAll('button[data-track], button[data-track] *')
// Should return all buttons with data-track and their children

If the selector returns the elements you expect, it will work in your GTM trigger condition. If it returns zero elements, something is wrong with the selector.

The Just Links trigger has two options that do not exist on All Clicks:

When enabled, GTM verifies that the clicked link is a valid URL before firing tags. Links with href="#", href="javascript:void(0)", or fragment-only identifiers fail validation and do not fire the trigger. This prevents false positives from decorative anchor elements and in-page navigation links.

Recommendation: leave Check Validation on unless you specifically need to track links with non-URL href values.

When enabled, GTM briefly delays the browser’s navigation after a link click to allow tags time to fire. Without this, the browser might navigate away before your tag’s network request completes — particularly for outbound links where the current page unloads.

The default maximum wait is 2000ms, but GTM typically releases navigation as soon as tags finish firing — the maximum is only reached if tags are slow.

Recommendation: enable Wait for Tags for any link trigger where the link navigates to a different domain. Do not enable it for internal navigation — it adds unnecessary delay and is not needed for same-domain links where GA4 is present on both pages.

Tag Configuration

GA4 - Event - Outbound Link Click

Type
Google Analytics: GA4 Event
Trigger
JL - Outbound Links
Variables
Click URLClick Text
Trigger type: All Clicks
Fires on: Some Clicks
Condition: Click Element matches CSS selector
Selector: [data-cta], [data-cta] *

This assumes your development team adds data-cta attributes to all primary call-to-action buttons. This is the correct pattern: developers annotate elements with semantic data attributes, GTM reads those attributes. It is more stable than tracking by class name (classes change during redesigns) and more specific than tracking by element type (buttons appear everywhere).

Trigger type: Just Links
Fires on: Some Link Clicks
Condition: Click URL ends with .pdf
Wait for Tags: enabled
Trigger type: Just Links
Fires on: Some Link Clicks
Condition: Click URL does not contain yourdomain.com
Check Validation: enabled
Wait for Tags: enabled

Track tab navigation — use a dataLayer event instead

Section titled “Track tab navigation — use a dataLayer event instead”
// Better approach: push to dataLayer instead of using click triggers
document.querySelectorAll('[role="tab"]').forEach(function(tab) {
tab.addEventListener('click', function() {
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
event: 'tab_click',
tab_label: this.textContent.trim(),
tab_id: this.id
});
});
});

Use a Custom Event trigger on tab_click instead. For interactive UI components with state, dataLayer events are more reliable and data-rich than click triggers.

GTM Preview mode shows every click event with its associated variable values. This is the fastest way to verify what GTM is actually seeing when a user clicks something.

  1. Enter GTM Preview mode and navigate to your page
  2. Click the element you want to track
  3. In the Preview pane, click the gtm.click event in the event list
  4. Expand “Variables” in the detail view
  5. Check what values GTM captured for Click Element, Click Classes, Click ID, etc.

The most useful thing to check: does Click Element show the element you expected, or a child element inside it? If it shows a child, you need the element, element * selector pattern or a more specific CSS selector.

Targeting by class name instead of data attributes

Section titled “Targeting by class name instead of data attributes”

Class names are visual styling concerns and change with redesigns. btn-primary becomes button--primary during a CSS refactor, and your click trigger silently stops working. Data attributes are semantic and stable — data-cta="purchase" is a deliberate annotation that communicates intent. Work with your development team to establish data-track or data-gtm attributes for elements you need to track.

Not enabling “matches CSS selector” as the operator

Section titled “Not enabling “matches CSS selector” as the operator”

GTM’s default condition operator for Click Classes is “contains.” Using Click Classes contains btn will match any button with “btn” anywhere in its class string — btn, btn-primary, btn-secondary, newsletter-btn. This is usually too broad. Switch to “matches CSS selector” for precise targeting.

Tested your trigger in Preview, it fires when you click the button text but not when you click the icon inside? Missing the descendant wildcard. Add , button[your-selector] * to your CSS selector condition.

Section titled “Using All Clicks when Just Links is appropriate”

If you are tracking link clicks, always use Just Links. It scopes the trigger to anchor elements and provides the “Wait for Tags” option, which is essential for outbound links. All Clicks on every click is noisy and slower to evaluate.

Over-relying on click triggers for application interactions

Section titled “Over-relying on click triggers for application interactions”

For anything more sophisticated than “user clicked this button,” consider dataLayer events instead. Click triggers cannot tell you whether the click led to a successful state change (did the form submit? Did the cart update?). A dataLayer event pushed after the action is confirmed is always more accurate.