Form Analytics & Abandonment Tracking
Form submission rate hides where things actually go wrong
Knowing that a form converts at 12% tells you nothing about *why* the other 88% don't finish. Form analytics instruments the form at the field level — tracking focus, blur, time spent per field, validation errors triggered, and the specific field where a visitor abandons — to turn a single aggregate submission rate into a field-by-field funnel that pinpoints exactly where friction lives. A form with a 12% completion rate where 60% of abandonment happens at a single field (say, a phone number field with aggressive validation) is a completely different fix than one where abandonment is evenly spread across all fields.
// Field-level instrumentation pushed to dataLayer for GTM/GA4 pickup.
// Tracks focus (field interaction started), blur with empty value
// (abandoned without completing), and validation errors per field.
document.querySelectorAll<HTMLInputElement>("form[data-track] input, form[data-track] select")
.forEach((field) => {
let focusedAt = 0;
field.addEventListener("focus", () => {
focusedAt = Date.now();
window.dataLayer.push({
event: "form_field_focus",
field_name: field.name,
form_id: field.closest("form")?.id,
});
});
field.addEventListener("blur", () => {
const timeSpentMs = Date.now() - focusedAt;
window.dataLayer.push({
event: "form_field_blur",
field_name: field.name,
form_id: field.closest("form")?.id,
field_value_empty: field.value.trim() === "",
time_spent_ms: timeSpentMs,
});
});
field.addEventListener("invalid", () => {
window.dataLayer.push({
event: "form_field_validation_error",
field_name: field.name,
validation_message: field.validationMessage,
});
});
});Building the field-level abandonment funnel
Once field focus/blur events are captured, construct a funnel of 'reached field N' → 'completed field N' → 'reached field N+1' across every field in form order. The field with the steepest drop-off between 'reached' and 'completed' is the highest-priority fix, and it's frequently not the field anyone would have guessed — an address autocomplete field that behaves unexpectedly, a password field with confusing complexity requirements shown only after submission, or a required field that doesn't visually signal it's required until the user hits a validation error.
Common form friction categories and typical symptoms
| Friction category | Field-level symptom | Typical fix |
|---|---|---|
| Unclear requirements | High validation_error rate on a specific field | Show format requirements inline before error, not after |
| Field perceived as too invasive | High blur rate with empty value, no error triggered | Make the field optional, or explain why it's needed |
| Technical friction (autofill/autocomplete conflicts) | Unusually long time_spent_ms on a simple field | Test autocomplete attributes and field type across browsers |
| Length/complexity fatigue | Drop-off accelerates in later fields regardless of which one | Progressive disclosure, reduce total field count, multi-step form |
Multi-step forms need step-level AND field-level tracking
Session replay complements field-level analytics for ambiguous cases
What's Next?
Form completion itself is often just one step toward a larger goal — recognizing it, and other partial-progress signals, as a micro-conversion in its own right is what lets a team measure and optimize funnel health well before the final macro conversion event.
I build these systems professionally.
Whether it's a RAG pipeline, analytics migration, or AI workflow — let's talk.