Universal Form Tracking Framework
A battle-tested client-side JavaScript library that reliably detects and instruments every type of web form into clean, standardized DataLayer events.
Core Code Architecture:
Universal Form Observer Engine (function(window, document) {
'use strict';
window.dataLayer = window.dataLayer || [];
function pushFormEvent(action, formElement, extraData) {
var formId = formElement.id || formElement.getAttribute('name') || 'unnamed_form';
window.dataLayer.push({
event: 'form_' + action,
form_id: formId,
form_name: formElement.getAttribute('data-form-name') || formId,
form_method: formElement.method || 'ajax',
form_fields_count: formElement.elements ? formElement.elements.length : 0,
timestamp: Date.now(),
...extraData
});
}
// Intercept standard form submissions
document.addEventListener('submit', function(e) {
if (e.target && e.target.tagName === 'FORM') {
pushFormEvent('submit', e.target);
}
}, true);
})(window, document);
The Challenge of Modern Form Tracking
Form conversion is the most critical lead-generation KPI. Yet, modern web applications employ diverse architectures: HubSpot embedded iframes, Typeform widgets, custom React/Next.js multi-step wizards, and AJAX forms that submit asynchronously without reloading the page. Native GTM Form Submission triggers fail on AJAX forms and fire false positives on client-side validation errors. This framework provides a single, deterministic solution.
- Detect native submit events while intercepting AJAX fetch/XHR completions
- Eliminate false positives when required fields fail client-side HTML5 validation
- Track multi-step funnel progression (form_start ➔ form_step_complete ➔ form_submit)
Framework Architecture & Event Pipeline
The framework attaches non-intrusive listeners, validates success states, and dispatches standardized DataLayer payloads.
DataLayer Payload Contract Specification
Standardized payload schema pushed on every valid submission.
| Parameter | Type | Example Value | Purpose |
|---|---|---|---|
| event | String | "form_submit" | GTM custom event trigger identifier |
| form_id | String | "demo_request_v2" | Unique DOM or logical form ID |
| form_name | String | "Enterprise Demo Request" | Human-readable form description |
| form_step | Number | 3 | Current step in multi-stage wizards |
| form_destination | String | "/api/leads" | Endpoint where payload was routed |