Tracking & Analytics

How to Track Elementor Form Submissions in GA4 and Google Ads with GTM

Track Elementor form submissions in GA4 and Google Ads with GTM: a success-only dataLayer event, generate_lead, Ads conversions and UTM/GCLID capture.

Tony Helmy · Senior MarTech Specialistupdated · 9 min read
On this page · 10 sections
  1. Why the usual Elementor tracking methods miscount
  2. What you need before you start
  3. Step 1: Give every form a stable name and ID
  4. Step 2: Push generate_lead to the dataLayer only on success
  5. Step 3: Build the GTM trigger and the GA4 event tag
  6. Step 4: Mark generate_lead as a key event in GA4
  7. Step 5: Count the lead in Google Ads
  8. Step 6: Store UTM parameters and the GCLID on the lead
  9. Test it before you trust it
  10. Common problems and how to fix them

The reliable way to track Elementor form submissions with Google Tag Manager is to listen for the event Elementor Pro fires only after a form is accepted, submit_success, and push a generate_lead event to the dataLayer at that moment. In GTM, a Custom Event trigger on generate_lead then fires your GA4 event tag and your Google Ads conversion. Button-click and generic form-submit triggers count failed and spam attempts, so they don’t give you lead numbers you can trust.

The short version:

  1. Give each Elementor form a stable Form name and Form ID.
  2. Add a small listener that pushes generate_lead to the dataLayer on submit_success.
  3. In GTM, fire a GA4 event tag from a Custom Event trigger, then mark generate_lead as a key event in GA4.
  4. Count the same lead in Google Ads, either by importing the GA4 key event or with a Google Ads conversion tag.
  5. Save UTM parameters and the GCLID in hidden fields, so each lead record shows where it came from.

This is one check from the tracking part of a MarTech audit, and on Elementor sites it’s the one I find broken most often. Below is the setup I use, step by step, with the reasons behind each choice.

Why the usual Elementor tracking methods miscount

Elementor Pro’s Form widget doesn’t submit the page the way a plain HTML form does. When a visitor clicks the button, Elementor cancels the browser’s normal submit, sends the data in the background (AJAX) and waits for the server’s reply. Only if the server accepts the submission does it show the success message and trigger a jQuery event called submit_success on the form. If validation fails, it triggers error instead. I checked this against the Elementor Pro 4.3 front-end code in October 2026.

That’s why most quick setups count the wrong thing:

MethodWhat it actually countsVerdict
GTM click trigger on the submit buttonEvery click, including empty fields, validation errors and double clicksInflated lead numbers
GTM Form Submission triggerThe browser’s submit event, which Elementor overrides. With “Check Validation” on, it often doesn’t fire at all. With it off, it fires on attempts, not successesUnreliable
GA4 enhanced measurement form_submitForm submit attempts. It has no idea whether Elementor accepted the dataFine for engagement, not for leads
Thank-you page viewPage views of the thank-you URL, including refreshes and direct visits. Only works if you use the Redirect actionWorkable, but noisy
submit_success listener → dataLayerSubmissions Elementor acceptedUse this

Google’s own documentation for the GTM Custom Event trigger describes this exact case: tracking a form whose default submit behaviour has been overridden.

What you need before you start

  • Elementor Pro with the classic Form widget. This guide was checked against Elementor Pro 4.3 (October 2026).
  • A Google Tag Manager container installed on every page, with your Google tag (GA4 measurement ID) firing on all pages.
  • A GA4 property and Editor (or higher) access to it.
  • For Google Ads: your Ads account linked to GA4, with auto-tagging turned on. Auto-tagging adds the GCLID to your ad clicks.

A note on Elementor’s newer editor: Editor 4 includes a separate Atomic Form element, built from individual input “atoms”. Elementor doesn’t document which front-end events it fires, so don’t assume the listener below works with it. If you build forms with the Atomic Form, test in GTM Preview before relying on it, or keep lead forms on the classic Form widget for now.

Step 1: Give every form a stable name and ID

In the Elementor editor, open the Form widget. Set a clear Form name (for example, “Free MarTech audit”) and, under Additional Options, a unique Form ID (for example, free_audit). Elementor outputs these on the page as the form’s name and id attributes:

<form class="elementor-form" id="free_audit" name="Free MarTech audit">

Without them you can’t tell your contact form from your demo form in GA4. Use the same naming pattern on every site you manage. Clean, stable names are what make the reports readable a year later.

Step 2: Push generate_lead to the dataLayer only on success

In GTM, create a Custom HTML tag with the code below and fire it on a DOM Ready trigger for all pages. DOM Ready makes sure jQuery, which Elementor Pro loads, is available. You can also add the same script to the site footer with a code-snippets plugin. Use one place only, or every lead will be counted twice.

<script>
(function () {
  if (!window.jQuery) return;
  window.dataLayer = window.dataLayer || [];

  // Elementor Pro triggers "submit_success" (a jQuery event) on the form
  // only after the server accepts the submission.
  jQuery(document).on('submit_success', '.elementor-form', function (event) {
    var form = event.currentTarget;
    window.dataLayer.push({
      event: 'generate_lead',
      form_id: form.getAttribute('id') || '',
      form_name: form.getAttribute('name') || ''
    });
  });
})();
</script>

Three details matter here:

  • It’s a jQuery event. submit_success is triggered with jQuery, so a native addEventListener won’t hear it. Listen with jQuery, as above.
  • The listener is delegated to the document, so it also catches forms inside Elementor popups that load after the page.
  • No personal data goes into the dataLayer. Don’t push names, emails or phone numbers into GA4. Google’s policies don’t allow personally identifiable information in Analytics.

Step 3: Build the GTM trigger and the GA4 event tag

  1. Variables. Create two Data Layer Variables: form_id and form_name.
  2. Trigger. Create a Custom Event trigger with the event name generate_lead, firing on all custom events.
  3. Tag. Create a Google Analytics: GA4 Event tag. Enter your Measurement ID, set the event name to generate_lead, and add the event parameters form_id and form_name using the two variables. Attach the Custom Event trigger.

generate_lead is one of Google’s recommended events, defined as a lead generated, for example through a form. It also accepts value and currency. If you know roughly what a lead is worth, send both (the currency as a three-letter code such as SAR or USD). Google requires currency whenever a value is sent.

Step 4: Mark generate_lead as a key event in GA4

GA4 now calls conversions “key events”. As of October 2026, go to Admin → Data display → Events and click the star next to generate_lead to mark it as a key event. If the event hasn’t arrived yet, you can create it there ahead of time with the “Mark as key event” toggle on. Allow up to 24 hours for it to appear in standard reports. Realtime shows it within minutes.

To break leads down by form, register form_id and form_name as event-scoped custom dimensions. Until you do, GA4 collects the parameters but you can’t use them in reports.

Step 5: Count the lead in Google Ads

You have two good options. Pick one as the conversion Google Ads bids on.

Option A: Import the GA4 key event

With GA4 and Google Ads linked and auto-tagging on, you can create a Google Ads conversion from the GA4 key event. As of October 2026 you can do this in GA4 under Advertising → Conversion management → New conversion, or from the Google Ads side. It needs no extra tags, and GA4 and Ads report from the same event.

Option B: Google Ads conversion tag in GTM

In Google Ads, create a manual website conversion action and choose to set it up with Google Tag Manager. Copy the Conversion ID and Conversion Label. In GTM, add a Google Ads Conversion Tracking tag with those values and the same generate_lead trigger. Make sure click data is stored on landing pages: a Google tag on every page covers this, otherwise add a Conversion Linker tag. This route sends the conversion straight to Ads and is the usual starting point for enhanced conversions.

Whichever you choose, avoid counting one lead twice. If you set up both, make one the primary action (used for bidding) and the other secondary (reporting only). Not every lead arrives through a form, so once forms work, track WhatsApp leads the same way.

Step 6: Store UTM parameters and the GCLID on the lead

GA4 tells you how many leads a campaign produced. Your CRM needs to know which lead came from which campaign. The simplest way is to save the campaign parameters into hidden form fields, so they travel with the submission. To route this data on, you can also send the same submission to your CRM or n8n.

In the Form widget, add fields of type Hidden and set each field’s ID (on the field’s Advanced tab) to utm_source, utm_medium, utm_campaign, utm_term, utm_content and gclid. Elementor names them form_fields[utm_source] and so on. Then add this script to every page, in the same GTM container or footer as before:

<script>
(function () {
  var keys = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'gclid'];
  var params = new URLSearchParams(window.location.search);
  var stored = {};
  try { stored = JSON.parse(sessionStorage.getItem('lead_attribution') || '{}'); } catch (e) {}

  // A new campaign visit replaces the stored values.
  if (keys.some(function (k) { return params.get(k); })) {
    stored = {};
    keys.forEach(function (k) { if (params.get(k)) stored[k] = params.get(k); });
    try { sessionStorage.setItem('lead_attribution', JSON.stringify(stored)); } catch (e) {}
  }

  function fillHiddenFields() {
    keys.forEach(function (k) {
      if (!stored[k]) return;
      document.querySelectorAll('input[name="form_fields[' + k + ']"]').forEach(function (input) {
        input.value = stored[k];
      });
    });
  }

  fillHiddenFields();
  // Forms inside Elementor popups are added when the popup opens.
  window.addEventListener('elementor/popup/show', fillHiddenFields);
})();
</script>

Why a script rather than Elementor’s Request Parameter dynamic tag? The dynamic tag fills the field on the server from the current URL. It works when the visitor submits on the landing page, but the values are lost once they click through to another page. It can also return stale values if your page cache serves the same HTML to every URL variant. The script keeps the values for the browser session and fills them in the browser. Session storage ends when the tab closes. If you need longer attribution windows, that’s a decision to make with your privacy and consent setup.

The GCLID only appears on ad clicks when auto-tagging is on. Storing it on the lead is what later lets you import offline conversions or use enhanced conversions for leads, so Google Ads learns which leads turned into customers, not just which ones filled in a form.

Test it before you trust it

  1. In GTM, click Preview, connect Tag Assistant to the page with your form, and open it with test parameters, for example ?utm_source=test&utm_medium=cpc&gclid=TEST123.
  2. Submit the form with a required field empty. No generate_lead should appear. If it does, something other than this listener is firing.
  3. Submit it properly. You should see exactly one generate_lead event with the right form_id, and your GA4 (and Ads) tags under “Tags Fired”.
  4. Open the submission in Elementor → Submissions (or your email/CRM) and check that the hidden fields hold your test values.
  5. In GA4, check Realtime (or DebugView) for generate_lead.

If your form uses Elementor’s Redirect action, test that case specifically. Elementor redirects straight after the success event, which leaves your tags very little time to send. If the GA4 or Ads hit doesn’t arrive in testing, track the thank-you page as a backup or show an inline success message instead of redirecting. If you’d rather have someone else check all of this, my free GTM and GA4 health check covers form events, key events and Ads conversions.

Common problems and how to fix them

SymptomLikely causeFix
Two generate_lead events per submitThe listener is installed twice (GTM and a plugin or footer snippet), or an old click trigger is still liveKeep one listener. Remove old click/form triggers from the lead tags
No event at allThe listener runs before jQuery loads, or the form is an Atomic Form or another plugin’s formFire the Custom HTML tag on DOM Ready. Confirm the form has the elementor-form class
Event fires in Preview, not in GA4Wrong Measurement ID, consent blocking the tag, or you’re looking at standard reports too earlyCheck the tag’s ID, check your consent setup, use Realtime/DebugView
GA4 has leads, Google Ads shows noneAccounts not linked, auto-tagging off, or the conversion was never created from the key eventLink the accounts, turn on auto-tagging, create the conversion (Step 5)
Ads leads ≈ double GA4 leadsBoth the imported key event and the Ads tag are primaryMake one primary, the other secondary
Hidden fields emptyField IDs don’t match the script’s keys, or the visitor arrived without parametersMatch the IDs exactly. Test with parameters in the URL

Why this much care over one event? Because every optimisation decision rests on it. One of the results I’m proudest of is +30% lead submissions (after optimisation), and a number like that only means something if every accepted submission is counted once, and failed attempts aren’t counted at all. When I wire up tracking for clients, this event is the first thing I build and the last thing I re-test after any change to the site.

The submit event is only the start. Once leads reach your CRM, you can go further by reporting lead quality back to Meta.

Part of
MarTech audit checklistSpeed, tracking, CRM lead flow and automation, in one checklist.

More in Tracking & Analytics