RESOURCES/WEBFLOW LISTENER
Webflow form tracking listener for Google Tag Manager
Webflow forms submit natively, so GTM can see the submit event, but it often misses the success confirmation and the form context. This listener pushes both webflow_form_submit (with the form ID, name, action and field data) and webflow_form_success (after Webflow confirms the submission) to the dataLayer, so you can fire GA4, Meta or Google Ads tags on real conversions without double counting.
webflow-listener.html
<script>
/*
* Form Submission Listener for Webflow
* ------------------------------------
* Developed by: Ahmed Ehsan
* Company: Growth Conversion
* Website: https://growthconversion.com
* Email: info@growthconversion.com
* LinkedIn: https://www.linkedin.com/in/ahmedehsanur/
*
* Version: 1.0.0
* Last Updated: July 2026
*
* Description:
* Listens for all Webflow form submissions and pushes form data
* to the dataLayer for Google Tag Manager (GTM), GA4, Google Ads,
* Meta Pixel, and other analytics platforms.
*
* © 2026 Ahmed Ehsan | Growth Conversion
* https://growthconversion.com
*/
(function() {
'use strict';
window.dataLayer = window.dataLayer || [];
function pushFormEvent(form, eventName, extraData) {
var formId = form.id || '';
var formName = form.getAttribute('name') || form.getAttribute('data-name') || '';
var formAction = form.getAttribute('action') || '';
var formMethod = form.getAttribute('method') || 'POST';
var payload = {
event: eventName,
formId: formId,
formName: formName,
formAction: formAction,
formMethod: formMethod.toUpperCase()
};
for (var key in extraData) {
if (extraData.hasOwnProperty(key)) {
payload[key] = extraData[key];
}
}
window.dataLayer.push(payload);
}
function getFormData(form) {
var fields = {};
var inputs = form.querySelectorAll('input, select, textarea');
for (var i = 0; i < inputs.length; i++) {
var input = inputs[i];
var name = input.getAttribute('name') || input.id || ('field_' + i);
var type = input.type || 'text';
if (type === 'password' || type === 'file') continue;
if (input.type === 'checkbox' || input.type === 'radio') {
if (input.checked) {
fields[name] = input.value;
}
} else if (input.tagName === 'SELECT') {
fields[name] = input.value;
} else {
fields[name] = input.value;
}
}
return fields;
}
function onFormSubmit(event) {
var form = event.target;
if (!form || form.tagName !== 'FORM') return;
pushFormEvent(form, 'webflow_form_submit', {
formData: getFormData(form)
});
}
function onFormSuccess(event) {
var form = event.target;
if (!form || form.tagName !== 'FORM') return;
pushFormEvent(form, 'webflow_form_success', {
formData: getFormData(form)
});
}
document.addEventListener('submit', onFormSubmit, true);
document.addEventListener('w-form-submit', onFormSubmit, true);
document.addEventListener('w-form-success', onFormSuccess, true);
document.addEventListener('DOMContentLoaded', function() {
var forms = document.querySelectorAll('form');
for (var i = 0; i < forms.length; i++) {
forms[i].addEventListener('submit', onFormSubmit, true);
}
});
})();
</script>Install in 3 steps
- 01
In GTM, create a Custom HTML tag and paste this code.
- 02
Set the trigger to All Pages, or only the pages where the form is embedded.
- 03
Open GTM Preview, submit a test form, and confirm the event appears in the dataLayer. Then use that event as the trigger for your GA4, Meta, or Google Ads tags.
Common problems
More free listeners:Typeform · Calendly · HubSpot · GoHighLevel