Back to blog

Form Submission Tracking and Analytics in Laravel — Without Third-Party Tools

Manuk Minasyan · · 7 min read

You built a form. You embedded it on your site. People are submitting it. But how many people saw the form and didn't submit? How many started filling it out and then left? You probably have no idea.

Most Laravel developers track submissions (that part is obvious, they land in your database) and ignore everything else. The form either works or it doesn't. But there's a gap between "the form works" and "the form works well," and you can't close that gap without data.

#Why form analytics matter more than you think

Here's what I mean. Say you have a contact form on your marketing site. You're getting 10 submissions a day. Is that good? You don't know. If 10,000 people are seeing the form and only 10 submit, your completion rate is 0.1% and something is very wrong. If 15 people see it and 10 submit, you're doing great but you might want more traffic.

Without tracking the full funnel (views, starts, submissions), you're just looking at an absolute number with no context. It's like checking your bank balance without knowing your income or expenses.

This is where most people reach for Google Analytics, Hotjar, Plausible, or some JavaScript snippet. And sure, those tools work. But they come with tradeoffs: external dependencies, GDPR consent banners, data leaving your server, and the overhead of mapping form events to whatever schema the third-party tool expects.

If your app already runs on Laravel, you can track all of this yourself. The data stays in your database. You query it with Eloquent. No third-party JavaScript required.

#What to actually track (and what most people skip)

When I say "form analytics," I don't mean just counting rows in a submissions table. Here's what a useful form funnel looks like:

Views are how many people loaded the page with the form on it. This is your top-of-funnel number.

Starts are when someone interacts with the form for the first time, clicking into a field, selecting an option, anything that signals intent. This is the number most people don't track, and it's the most useful one. The drop between views and starts tells you whether people even want to fill out your form.

Submissions are completed form entries. You already have these.

Completion rate is submissions divided by views (or by starts, depending on what question you're asking). Either way, it's meaningless without the other numbers.

Average time to complete tells you how long people spend on the form before submitting. If your "quick contact form" takes people 4 minutes on average, it's not quick.

The gap between starts and submissions is where you find friction. Maybe a field is confusing. Maybe the form is too long. Maybe people on mobile can't tap a dropdown properly. You won't know unless you measure both sides of the funnel.

#How FilaForms handles this automatically

If you've already set up a public-facing form with FilaForms, analytics tracking is already running. The ANALYTICS feature flag is enabled by default, so forms start collecting view, start, and submission events as soon as they're live.

Under the hood, events are stored in a form_events table with a simple structure:

Column Type Purpose
id ULID Unique event identifier
form_id Foreign key Which form this event belongs to
event type Enum view, start, or submit
session_fingerprint String Deduplicated session identifier
created_at Timestamp When the event occurred

The session fingerprinting is worth explaining. FilaForms generates an xxh64 hash based on the user ID (for authenticated users) or IP address plus user agent string (for anonymous visitors). This fingerprint is used to deduplicate events per session and per event type. If someone refreshes the page three times, that counts as one view, not three. If they start typing, leave, come back, and start again, that's still one start.

This matters more than you'd think. Without deduplication, a single impatient user can inflate your view count and make your completion rate look worse than it actually is.

#Using the data programmatically

This is where it gets practical. Say you want to pull analytics for a form in your application code, maybe for a custom dashboard, an admin notification, or a report.

$analytics = $form->getAnalytics();

This returns an array with everything you need:

[
    'views' => 1240,
    'starts' => 890,
    'submissions' => 312,
    'completion_rate' => 25.16,
    'avg_time_to_complete' => 47, // seconds
]

From this you can read the full story. 1,240 people saw the form. 890 started filling it out (71.8% of viewers, which is solid). But only 312 submitted, meaning about 65% of people who started the form abandoned it before finishing. That's your problem area. The form itself is attracting interest but losing people during completion.

For time-series data, you can pull daily analytics over a rolling window:

$trends = FormEvent::getDailyAnalytics($form->id, days: 30);

This gives you 30 days of daily breakdowns, useful for spotting changes after you modify a form. Did removing that phone number field improve completion? Compare the week before and after.

For submission-specific stats, there's a dedicated action:

$stats = app(GetFormSubmissionStatsAction::class)->execute($form);

// Returns:
// total, today, this_week, this_month, average_per_day, latest

I find average_per_day particularly useful for setting expectations. If a client asks "are we getting enough leads?" you can give them a concrete number instead of a vague answer.

#What the dashboard shows

The Filament admin panel includes a built-in dashboard for form analytics. There are two main components:

The funnel visualization shows views flowing to starts flowing to submissions, with drop-off percentages between each stage. You can see at a glance where people are falling off.

The submission stats panel shows your totals broken down by time period: today, this week, this month, all time. It also shows the latest submission timestamp and the daily average.

Submissions themselves are stored as JSON in a data column, with sequential numbering that auto-increments per form. Each submission tracks whether it came from an authenticated user or an anonymous visitor, which is useful if your form serves both logged-in customers and public visitors.

When you need to get data out, FilaForms supports CSV and Excel exports through Filament's built-in exporter. The export includes submission number, ULID, user (if authenticated), timestamp, and all field values.

#Making decisions from your form data

Data is only useful if you act on it. Here are the patterns I look for:

High views, low starts: The form is visible but people aren't engaging with it. Usually this means the form looks too long, the surrounding copy doesn't motivate action, or the form is below the fold on mobile. Consider reducing visible fields or adding context about what happens after they submit.

High starts, low submissions: People want to fill it out but something is stopping them. Check for required fields that feel invasive (phone number is the usual suspect), confusing validation messages, or fields that don't work well on mobile. If you built a contact form, go back and reconsider how many fields you actually need.

High completion rate but low volume: The form converts well but not enough people are seeing it. This is a traffic or placement problem, not a form problem.

Long average time to complete: Either the form has too many fields, the fields are confusing, or people are getting stuck somewhere. Cross-reference with the starts-to-submissions ratio. If time is high but completion is also high, people might just be thoughtful. If time is high and completion is low, there's friction.

The 30-day trends are the most actionable piece. Make a change to your form, then compare the two weeks before and after. Did completion rate go up? Did average time drop? This is basic A/B testing without any additional tooling.

#Keeping it all in-house

The whole point of running a self-hosted form builder is control. Your form data, your submission data, and your analytics data all live in the same database, queried with the same tools, protected by the same policies. No external scripts loading on your pages. No data flowing to third-party servers. No wondering whether your analytics provider is selling aggregated data about your users.

FilaForms tracks form analytics out of the box. If you haven't looked at your form funnel yet, go check the dashboard. The numbers might surprise you.

Related posts