Home › How-tos › The Secret Setups › dataLayer
How to track any form submission with the dataLayer
Live guide · Checked 28 October 2026 · Updated 28 October 2026 · Checked every week against dataLayer's own help pages
One small script that pushes generate_lead for every successful form on your site, including forms that send without reloading the page.
- Time
- 20 minutes
- You will need
- Google Tag Manager on your site
- The dataLayer and generate_lead trigger from the first Secret Setup
- Stuck?
- Troubleshooting or ask us a question
Step by step
Know which kind of form you have
There are two kinds. Reload forms go to a thank-you page after sending. AJAX forms show a message on the same page. Send a test and watch the address bar: if it changes, it's a reload form.
Reload forms: push on the thank-you page
Add this to the thank-you page only (or as a Tag Manager Custom HTML tag on a Page View trigger where Page Path equals your thank-you path):
<script> window.dataLayer = window.dataLayer || []; window.dataLayer.push({ event: 'generate_lead', form_id: 'contact-form', lead_type: 'enquiry', value: 50, currency: 'GBP', lead_id: 'L-' + Date.now() }); </script>People who refresh the thank-you page would count twice, so mark it once per visit with the tip below.
AJAX forms: listen for the success
Most form tools say when a send worked. If yours doesn't, this script watches for the success message appearing. Change the selector to your form's success message:
<script> (function () { var SUCCESS = '.form-success'; // the element that appears after a good send var sent = false; new MutationObserver(function () { var el = document.querySelector(SUCCESS); if (!sent && el && el.offsetParent !== null) { sent = true; window.dataLayer = window.dataLayer || []; window.dataLayer.push({ event: 'generate_lead', form_id: (el.closest('form') || {}).id || 'ajax-form', lead_type: 'enquiry', value: 50, currency: 'GBP', lead_id: 'L-' + Date.now() }); } }).observe(document.body, { childList: true, subtree: true, attributes: true }); })(); </script>Add it through Tag Manager
In Tag Manager: Tags > New > Custom HTML. Paste the script, tick Support document.write off (leave it off), and set the trigger to All Pages (or only the pages with the form). Save.
Stop double counts on refresh
For thank-you pages, wrap the push so it only runs once per visit:
if (!sessionStorage.getItem('lead_sent')) { sessionStorage.setItem('lead_sent', '1'); window.dataLayer.push({ event: 'generate_lead', form_id: 'contact-form', lead_type: 'enquiry', value: 50, currency: 'GBP', lead_id: 'L-' + Date.now() }); }Test with a real send
Open Preview, send the form properly, and check
generate_leadappears once in Tag Assistant with the rightform_id. Send it with a mistake too: nothing should fire.Publish
Submit and Publish. Every tag already on the
CE - generate_leadtrigger now counts this form.
Tips from people who set these up every week
- Tag Manager's built-in Form Submission trigger often misses AJAX forms and counts failed sends: the dataLayer push is more reliable.
- Use the real form id from your page's code as form_id, so reports show which form made each lead.
Troubleshooting: questions and answers
Nothing fires on my AJAX form.
Check the success selector: right-click the success message, choose Inspect and copy its class. Some tools put it inside an iframe: then use that tool's own event (see the HubSpot and Calendly Secret Setups).
It fires twice.
You probably have both the thank-you page push and the success listener. Keep one.
Official help pages
Let Claude fix the rest of your funnel
Lead Focus is 12 Claude Skills that find the stage of your funnel that's costing you leads, then fix it: ads, landing pages, follow-ups and tracking. One payment, 12 months of updates, and a 14-day refund.
Get Lead Focus · $29.99Still stuck, or have a question?
Tell us where you got to and what you see. We read every message and reply by email, usually the same working day.