Short answer
GA4 conversion tracking through Google Tag Manager works by pushing custom data layer events on real user actions, configuring matching GA4 event tags in GTM, marking the meaningful ones as key events inside GA4 (not GTM), and verifying everything through Preview mode and DebugView before importing key events into Google Ads as conversions.
GA4 punishes vague implementation. Its event model is flexible enough that two sites can measure "the same" outcome in completely different ways, and one of them will be wrong — usually the one built by copying a tutorial without a documented event taxonomy first.
This is a clean GA4 conversion tracking setup through Google Tag Manager for a lead-generation site, covering the data layer, the GA4 event and configuration tags, key events, cross-domain measurement, consent mode and the debugging sequence I run on every build.
GA4 vs GTM: what each one actually does
Google Analytics 4 is the measurement platform — it stores events, builds reports, and (via key events) tells Google Ads which actions matter. Google Tag Manager is the delivery mechanism — it decides when to fire a GA4 event tag based on triggers, and what parameters to attach based on variables.
Confusing the two is common: people try to "track a conversion in GTM" when GTM's only job is firing the event; the conversion designation itself happens inside GA4's Admin settings as a key event marker. Get this separation clear before building anything.
Design the event taxonomy first
Write down your events and parameters before touching GTM: `generate_lead`, `contact_form_submit`, `phone_call_click`, `booking_confirmed`. Use consistent snake_case naming and define exactly which parameters each event carries — form_id, page_path, lead_value, service_type.
Half an hour of naming discipline saves a year of reports nobody trusts. It also matters for GA4 conversion tracking specifically because key events are matched by exact event name; a typo between the data layer push and the GTM trigger means the event fires but never gets marked as a key event, and no error appears anywhere.
Push real events to the data layer
Ask your developer to push a data layer event on genuine form success, confirmed by the server response, rather than relying on a thank-you page view. Page-based triggers count refreshes, direct visits, back-button returns and bookmarked confirmation URLs as conversions — all of which are noise, not leads.
Where a developer is unavailable, GTM's native Form Submission trigger with an added check on a visible success element (a class that only appears after a successful AJAX submission) is the next best option, though it's more fragile against JavaScript-heavy multi-step forms and third-party booking widgets embedded via iframe.
Example data layer push
`dataLayer.push({event: 'generate_lead', form_id: 'contact-page', lead_value: 150});` — this fires once, carries a value GA4 and Google Ads can both use, and is independent of whatever URL the user lands on next.
Configure GA4 tags in GTM
Start with one GA4 Configuration tag firing on All Pages, then add a GA4 Event tag for each meaningful action, each triggered by its own custom event trigger matching the data layer event name exactly. Pass parameters as event parameters rather than hardcoding them, so reporting reflects real variation (form type, lead value, service selected).
Mark the meaningful ones as key events inside GA4's Admin > Events settings, not in GTM — GTM has no concept of a key event. Keep the number of key events small and deliberate; if every micro-interaction is marked as a key event, Smart Bidding downstream in Google Ads has no signal about what actually matters.
- GA4 Configuration tag: fires on All Pages, sets the measurement ID once.
- GA4 Event tag per action: `generate_lead`, `phone_call_click`, `booking_confirmed`, each with its own custom event trigger.
- Key events marked in GA4 Admin: only outcomes a salesperson would recognise as pipeline.
- Google Ads link: GA4 property linked, key events imported as conversion actions.
Linking GA4 to Google Ads without double-counting
Link GA4 to Google Ads inside GA4's Admin settings so key events can be imported as Google Ads conversion actions. This gives Smart Bidding a second measurement path independent of native Google Ads tags — useful, but only if you decide deliberately which path you're bidding on.
Using both a native Google Ads conversion tag and a GA4-imported key event for the same physical action double-counts the outcome and confuses attribution. Pick one per action: native tracking for anything measured only through paid clicks, GA4-imported key events where you want a single cross-channel view of the same action. For the native side of this build, see Google Ads conversion tracking setup.
Cross-domain and subdomain tracking
If your booking tool, checkout, or lead form lives on another domain — a Calendly link, a separate booking.yoursite.com subdomain, or a third-party quote tool — configure cross-domain measurement inside the GA4 Configuration tag's fields settings, listing every domain in the user journey.
Without it, the session breaks at the handoff between domains and the conversion gets attributed to Direct traffic rather than the paid campaign that actually drove it. This single misconfiguration is behind most "why is Direct our best-performing channel" conversations I have with clients — it isn't; it's broken attribution.
Consent mode without losing your data
Implement Consent Mode v2 so tags adjust behaviour rather than disappear entirely when a user declines consent. Set default consent states before the banner loads (`ad_storage`, `analytics_storage`, `ad_user_data`, `ad_personalization`), update them on the user's actual choice, and enable modelling in GA4's data settings to estimate the gap statistically.
A consent banner installed without Consent Mode configured typically drops reported conversions 20% to 40% overnight, and the drop usually gets blamed on the media team or a broken campaign rather than the actual cause — a missing few lines of consent configuration.
Debugging checklist
Run through the same sequence on every build: GTM Preview to confirm the trigger fires on the correct event with the correct parameters, GA4 DebugView to confirm the event arrives server-side with those parameters intact, the GA4 Realtime report to see the key event appear, and — a week later, once volume builds — the standard Reports section to confirm it's behaving as expected over time.
Test the same journey on mobile and with a content/ad blocker enabled; a meaningful share of real users browse this way, and if the event doesn't fire under those conditions your reported numbers will always undercount reality.
- GTM Preview: trigger fires once, correct event name, correct parameters attached.
- GA4 DebugView: event appears within seconds, parameters visible and correctly typed.
- GA4 Realtime report: key event count matches test submissions.
- Cross-check on mobile and with an ad blocker active.
- Reconcile GA4, Google Ads and CRM monthly — do not average disagreements away.
When the numbers still don't agree
If GA4, Google Ads and your CRM disagree by more than 10% after everything above is verified, don't average them and move on — find the specific cause. It's almost always one of: a duplicated tag, a missed cross-domain configuration, a consent default set incorrectly, or a key event still counting page views rather than a real success signal.
That reconciliation exercise is the core of the analytics and measurement work I do with clients, and it's also worth running as part of a broader Google Ads account audit since tracking issues tend to surface alongside structural ones.
Build it once, correctly
A properly built GA4 conversion tracking setup through GTM takes a day or two of focused implementation and debugging, and it underpins every reporting and bidding decision made afterwards. If you'd rather this was built, documented and stress-tested by someone who does it as their core work, book a 30-minute call or explore conversion tracking setup directly.
Frequently asked questions
- What is the difference between a GA4 event and a GA4 key event?
- Every user interaction you track is a GA4 event — page views, clicks, form starts. A key event (formerly "conversion" in GA4's older terminology) is a specific event you've deliberately marked in Admin settings as representing a meaningful business outcome, which can then be imported into Google Ads as a conversion action.
- Can I set up GA4 conversion tracking without a developer?
- Partially. GTM's built-in triggers (clicks, form submissions, page views) cover basic cases without code, but reliable lead tracking — confirming a form actually succeeded server-side — usually needs a small data layer push from a developer. Relying purely on GTM's automatic form trigger risks false positives from failed submissions.
- Why do my GA4 numbers not match Google Ads conversions?
- The two platforms use different attribution models and counting logic by default, and if you're running both native Google Ads tags and GA4-imported key events for the same action, you're likely double-counting one and under-reporting the other. Reconcile them explicitly rather than assuming either is automatically correct.
- Does consent mode reduce my actual GA4 data?
- It reduces the observed (unconsented) data, which is expected and legally required, but GA4's modelling can estimate the gap statistically if Consent Mode v2 is implemented correctly with proper default states. Skipping Consent Mode entirely, rather than just having lower consent rates, is what causes the bigger reporting gaps.
- How do I track cross-domain bookings in GA4?
- Add every domain involved in the user journey to the cross-domain measurement field inside the GA4 Configuration tag in GTM. Without this, GA4 treats the handoff between domains as two separate sessions and typically misattributes the resulting conversion to Direct traffic.
- What's the fastest way to debug a GA4 event that isn't firing?
- Open GTM Preview mode alongside GA4 DebugView in two tabs, trigger the action manually, and check whether the tag fires in GTM first. If it fires in GTM but doesn't appear in DebugView, the issue is usually a blocked request, an incorrect measurement ID, or a consent state blocking the hit.
