Tutorial

Tutorial: Track CTAs and forms with GTM custom events

July 1, 2026 · Kabim Tech Analytics · 2 min read

← Back to blog
Analytics event chart for GTM custom events
Analytics event chart for GTM custom events
  • Gtm
  • Ga4
  • Analytics
  • Events

Push dataLayer events for button clicks, contact submits, and rent-a-developer intent so GA4 reports the journeys that actually matter.

Default page views are not enough. Product and marketing need events for Contact submits, Rent a developer clicks, and WhatsApp taps. This tutorial sets up a clean `dataLayer` contract and matching GTM triggers.

What you will build

  • A typed `pushDataLayerEvent` helper
  • Events for `cta_click`, `contact_submit`, and `whatsapp_click`
  • GTM Custom Event triggers + GA4 Event tags
  • A QA checklist in Preview mode

Prerequisites

  • GTM installed on the site (see our install tutorial)
  • GA4 property connected in GTM
  • Ability to edit React/Next components for key CTAs

Step-by-step

  1. Define event names and parameters in a short analytics README (source of truth).
  2. Add `lib/analytics/data-layer.ts` with a safe `window.dataLayer.push` wrapper.
  3. Fire `cta_click` when primary buttons are clicked (`location`, `label`).
  4. Fire `contact_submit` after a successful contact API response (`intent`: meeting | project | hire).
  5. In GTM, create Custom Event triggers for each event name.
  6. Attach GA4 Event tags that map parameters to GA4 event params.
  7. Publish a GTM version and validate in DebugView.

dataLayer helper

type DataLayerEvent = {
  event: string;
  [key: string]: string | number | boolean | undefined;
};

export function pushDataLayerEvent(payload: DataLayerEvent) {
  if (typeof window === "undefined") return;
  window.dataLayer = window.dataLayer || [];
  window.dataLayer.push(payload);
}

CTA example

<button
  type="button"
  onClick={() =>
    pushDataLayerEvent({
      event: "cta_click",
      cta_location: "home_hire",
      cta_label: "Rent a developer",
    })
  }
>
  Rent a developer
</button>

Contact success example

pushDataLayerEvent({
  event: "contact_submit",
  intent: "hire",
  hire_plan: "monthly",
});

GTM configuration

  1. Trigger: Custom Event → Event name equals `contact_submit`.
  2. Tag: GA4 Event → Event name `contact_submit`.
  3. Event parameters: `intent`, `hire_plan` from Data Layer Variables.
  4. Repeat for `cta_click` and `whatsapp_click`.

Verify

  • Preview mode shows the event on submit
  • GA4 DebugView receives the event within a minute
  • No PII (emails, phone numbers) in event params

Common mistakes

  • Pushing events before GTM loads (queue with dataLayer anyway; GTM reads history)
  • Reusing vague names like `click` without parameters
  • Tracking every link and drowning the property in noise

Next steps

Mark `contact_submit` as a key event (conversion) in GA4, then build an exploration for intent mix (meeting vs project vs rent).

Want to talk about your product?

Need a dedicated squad or a fixed-scope MVP? We help teams ship on time.