TagIntact
Module 2 · Lesson 3 of 4 · 10 min

Your first click event, three ways

Built-in click trigger, CSS selector, dataLayer push — and why you should reach for them in that order reversed.

Verified against Google Tag Manager web container, September 2026 interface on 2026-09-27

The sandbox home page has a button with id="cta-primary" and class cta. Let's send a GA4 event called cta_click when it's clicked — three different ways, because each one is right in a different situation.

Way 1: the built-in click trigger

  1. Variables → Configure → Clicks: enable Click Element, Click Classes, Click ID, Click Text, Click URL. (Built-ins are off until you turn them on; a trigger that references one that's off silently matches nothing.)
  2. Triggers → New → Click – All Elements. Fire on Some Clicks: Click ID equals cta-primary.
  3. Tags → New → GA4 Event, name cta_click, parameter button_text → {{Click Text}}, trigger from step 2.
  4. Preview → sandbox → click the button. gtm.click appears in the timeline and your tag fires.

When to use it: fast, no developer needed, good for a handful of important buttons that have stable ids.

Where it breaks: the click target is whatever element the mouse was actually on. If the button contains an icon <svg>, Click ID is the svg's (empty) id, not the button's. And the moment a developer renames the id, the trigger goes quiet. No error.

Way 2: CSS selector matching

Same trigger, different filter: Click Element matches CSS selector #cta-primary, #cta-primary *.

The , #cta-primary * part is the fix for the svg problem — it matches the button or anything inside it. This is the version you want for any real button with children. You can go broader: .cta, .cta * fires for every element with the cta class, and {{Click Text}} or {{Click ID}} becomes the parameter that tells them apart.

When to use it: most click tracking on a site you don't control the code of.

Where it breaks: the same place — a redesign changes the class and you find out at month-end. Also, buttons that trigger navigation may unload the page before the request leaves (GTM's Wait for Tags setting on link triggers mitigates this).

Way 3: the dataLayer push

Ask the developer to add one line to the button's handler:

window.dataLayer.push({ event: "cta_click", cta_name: "primary" });

Then: Custom Event trigger with event name cta_click, and a Data Layer Variable cta_name for the parameter.

When to use it: everything that matters — conversions, ecommerce, anything with a value. The site is now making a promise in code. Redesigns don't break it. It carries exactly the data you want, named the way you want. It's testable in the site's own test suite.

Where it breaks: you need a developer, and you need them to keep the promise on the thank-you page too.

The order to reach for them

Reverse of how they're taught. Default to the dataLayer push for anything you'd be upset to lose. Fall back to a CSS selector for the long tail of "nice to know" clicks. Use the plain built-in filter only for quick experiments.

The sandbox supports all three: the CTA buttons have stable ids and a shared class for Ways 1 and 2, and the newsletter form pushes newsletter_signup for Way 3. Build the same cta_click event each way, then compare what {{Click Text}} gives you against what the push gave you.

Prove it fired once

After each build, open the network tab, filter collect, click once. One request with en=cta_click. If you see two, you have two triggers matching the same click — usually Way 1 and Way 2 both left enabled — and you've just built the double-counting bug yourself. Delete one. That's the whole lesson of Module 2 in miniature: it's not done until you've counted the requests.

Try it in the sandbox

The sandbox store fires real ecommerce dataLayer events and loads your GTM container, so you can build the tag from this lesson against live events.

Open the sandbox
Your first click event, three ways — Tracking Foundations · TagIntact