Laravel Form Analytics: Completion, Step Drop-Off, and Privacy | FilaForms                                 [ ![Filaforms Logo](https://filaforms.app/logo.svg)FilaForms

 ](https://filaforms.app)  [ Features ](https://filaforms.app#features) [ Pricing ](https://filaforms.app/pricing) [ Blog ](https://filaforms.app/blog) [ Documentation ](https://docs.filaforms.app)  [ Try Demo ](https://filaforms.app/login) [ Get Started ](https://filaforms.app/pricing#plans) 

 [ Features ](https://filaforms.app#features) [ Pricing ](https://filaforms.app/pricing) [ Blog ](https://filaforms.app/blog) [ Documentation ](https://docs.filaforms.app) [ Try Demo ](https://filaforms.app/login) [ Get Started ](https://filaforms.app/pricing#plans) 

   ![FilaForms](https://filaforms.app/logo.svg) FilaForms 

 TutorialsLaravel Form Analytics: Completion, Step Drop-Off, and Privacy
==============================================================

 filaforms.app/blog

  [    Back to blog ](https://filaforms.app/blog) [ Tutorials ](https://filaforms.app/blog/category/tutorials) 

Laravel Form Analytics: Completion, Step Drop-Off, and Privacy
==============================================================

 Manuk Minasyan ·  March 20, 2025  · 5 min read 

 Useful form analytics answers three questions: did visitors see the form, where did engaged visitors stop, and did the server accept the submission? You can answer those inside Laravel without recording answers or sending visitor behavior to a third-party analytics platform.

The difficult part is not drawing a funnel. It is defining events precisely enough that refreshes, multiple tabs, failed validation, background tabs, and network loss do not turn the dashboard into fiction.

Start with a versioned event contract
-------------------------------------

Use stable event names and stable identifiers:

```text
form.viewed
form.started
form.step_viewed
form.step_completed
form.validation_failed
form.submitted

```

Store `form_id`, `form_version_id`, a stable step or field code where relevant, an event-schema version, server receive time, and a scoped session token. Allowlist attributes. Do not capture answers, free text, filenames, email addresses, or raw validation input in analytics.

Dynamic values belong in attributes, not names. `form.step_completed` with `step_code=employment` is queryable; `employment_step_completed` fragments the contract.

Define every denominator
------------------------

These ratios answer different questions:

- **View-to-submit conversion:** accepted submissions divided by unique views.
- **Start completion:** accepted submissions divided by unique starts.
- **Step continuation:** visitors reaching the next step divided by visitors reaching the current step.
- **Validation failure rate:** sessions with a categorized validation failure divided by sessions attempting that field or step.

Do not call all of them “completion rate.” Do not publish a universal good/bad threshold. Traffic source, device mix, form purpose, length, and audience intent can move a baseline dramatically. Compare the same form version over time and evaluate controlled changes.

Make the server authoritative
-----------------------------

A click on Submit is not a completed submission. Record `form.submitted` only after server validation succeeds and the submission transaction commits.

Client events are useful for view, start, step, and timing context, but they are best effort. Browsers can be offline, block requests, restore pages from back/forward cache, or close before sending the final beacon.

For a small final timing event, `navigator.sendBeacon()` is appropriate during `visibilitychange`. The [W3C Beacon specification](https://www.w3.org/TR/beacon/) is explicit that a successful call means the browser queued the data, not that your server received it. Analytics must never block the actual form submission.

Use race-safe deduplication
---------------------------

An application-level `firstOrCreate()` is not sufficient by itself: two concurrent requests can both observe that no event exists. Put the intended event cardinality in the database.

For example, if a view should occur once per form version and session window, create a unique index covering that tuple. Then use an atomic insert-or-ignore or catch the unique-key conflict. A start event may have a different uniqueness contract from a validation-failure event, so avoid one generic constraint that erases useful data.

The session token should be scoped and short-lived. A keyed HMAC over a rotating identifier can reduce raw identifier exposure, but it is usually **pseudonymous**, not automatically anonymous. Hashes can still allow singling out and linking. Include analytics in the privacy notice, retain it for a documented period, and assess applicable cookie or storage rules.

Measure step drop-off without collecting answers
------------------------------------------------

A multi-step form needs two separate events:

- `form.step_viewed`: the step became available to the visitor;
- `form.step_completed`: its validation passed and navigation advanced.

The gap between viewed and completed points to friction. A categorized `form.validation_failed` event can identify a field code and rule category such as `required`, `email`, or `max`—never the rejected value.

Abandonment is inferred after a time window. The browser cannot know that a person will never return. Label it accordingly in the dashboard.

For implementation details of the wizard itself, see the [multi-step Filament form guide](/blog/multi-step-forms-in-filament-a-complete-guide).

Report active time, not one misleading average
----------------------------------------------

Elapsed time between first input and submit can include lunch, a sleeping laptop, or a background tab. If timing matters:

1. accumulate time only while the document is visible;
2. pause after a defined inactivity window;
3. report median and p75/p90, not only the mean;
4. segment by form version and device class only when groups are large enough for privacy.

Performance and completion are related but distinct. A slow interaction can cause drop-off, while a confusing question can be fast and still fail. Use the [Laravel form performance guide](/blog/form-performance-laravel-loading-validation-submission-speed) to diagnose timing separately.

A minimal storage design
------------------------

A compact event table can contain:

```text
id
form_id
form_version_id
event_name
event_version
session_token
step_code (nullable)
field_code (nullable)
error_category (nullable)
occurred_at_client (nullable, untrusted)
received_at_server

```

Index common funnel dimensions such as `(form_id, form_version_id, event_name, received_at_server)`. Add separate unique indexes for events whose definition requires deduplication. Avoid a single JSON dump of arbitrary browser properties; it is harder to govern and easy to turn into accidental surveillance.

Test the data, not just the chart
---------------------------------

A credible analytics feature needs failure cases:

- refresh and multiple tabs follow the documented view rule;
- two concurrent start requests deduplicate through the database;
- failed validation records a category but no value;
- a rejected submission never increments completed submissions;
- session/token rotation limits long-term linking;
- background time is excluded or clearly labeled;
- beacon loss does not affect form submission;
- retention removes or aggregates old events as designed.

Also test bots, a submit with no captured start, back/forward cache restoration, offline browsing, and a deployment that changes steps mid-session.

Privacy is a design constraint, not a badge
-------------------------------------------

Self-hosting removes a third-party recipient, but it does not automatically make analytics anonymous or compliant. Document the purpose, fields, retention, access, and deletion behavior. Keep low-volume segments out of dashboards that could single out a person, and do not reuse the session token across unrelated contexts.

The [GDPR form checklist](/blog/gdpr-compliant-forms-laravel-checklist) covers the broader data lifecycle. Legal requirements vary by purpose and jurisdiction, so treat this implementation as engineering guidance rather than legal advice.

The payoff for precision is practical: when a metric moves, you know whether the form changed—not merely whether the event collector changed its mind about what “started” or “submitted” means.

 Related posts
-------------

 [  Tutorials   Aug 18, 2026  

 Dynamic Form Validation in Laravel: Safely Storing Rules in the Database 
--------------------------------------------------------------------------

Compile database-stored Laravel form rules safely with allowlists, typed parameters, nested validation, tenant scopes, and adversarial tests.

 ](https://filaforms.app/blog/dynamic-form-validation-in-laravel-safely-storing-rules-in-the-database) [  Tutorials   Jul 28, 2026  

 Form Performance in Laravel: Loading, Validation, and Submission Speed 
------------------------------------------------------------------------

Form page loads in 2.8 seconds. INP is 380 ms. Submit lags. Conversion drops and you feel it but can't see why. Here's the five-number checklist that finds the leak.

 ](https://filaforms.app/blog/form-performance-laravel-loading-validation-submission-speed) [  Tutorials   Jul 14, 2026  

 Signature Fields in Laravel Forms: When You Need a Real Signature, Not a Checkbox 
-----------------------------------------------------------------------------------

Checkbox-as-signature doesn't fly for NDAs, waivers, or parental consent. DocuSign is $40/user. Here's how the signature field in FilaForms works — and when it's enough.

 ](https://filaforms.app/blog/signature-fields-in-laravel-forms) 

    ![FilaForms Logo](/logo.svg) FilaForms 

 Laravel form infrastructure for Filament. Stop rebuilding forms on every project.

 ### Product

 [ Features ](https://filaforms.app#features) [ Documentation ](https://docs.filaforms.app) [ Blog ](https://filaforms.app/blog) [ Pricing ](https://filaforms.app/pricing) [ About ](https://filaforms.app/about) [ Contact ](mailto:hello@filaforms.app) 

 ### Legal

 [ Terms of Service ](https://filaforms.app/terms-of-service) [ Privacy Policy ](https://filaforms.app/privacy-policy) 

  © 2025-2026 FilaForms. All rights reserved.

 [    ](mailto:hello@filaforms.app) [    ](https://x.com/MinasyanManuk)
