DIL.DEV
LOADING0%
DIL.DEV
← ALL NOTES

A Thank-You Page Visit Is Not a Lead

Counting a thank-you page visit as a conversion inflates your lead numbers. Fire tracking only after Netlify acknowledges a real submission.

netlifyanalyticsformsconversion

A browser network tab showing a Netlify form POST response alongside a GA4 event firing in the console.

The conversion event should fire when Netlify says the submission landed, not when the browser changes URL. That distinction sounds obvious until you look at how most setups actually work, and realise the thank-you page is doing double duty as both a user-facing confirmation and a tracking trigger. Those two jobs need to be separated.

The Problem With Redirecting to /thank-you.html

A redirect-based thank-you page is a user-experience tool. It tells the person they are done. It is not evidence that a form submission occurred.

  • Direct navigation is always possible. Any URL you can redirect to, a human or a bot can visit without touching the form.
  • QA visits inflate the count. Every time you check that the redirect still works, you add a conversion to the report.
  • Crawlers follow redirects. Link-preview services, social cards and monitoring tools can all land on /thank-you.html without submitting anything.

The result is a conversion number that is always optimistic. You cannot tell from the page-view alone whether a real human filled in the form.

How the Project-Application Form Is Wired

The form lives in site/lib/chrome.mjs as applicationForm. The relevant attributes are:

  • name="project-application" so Netlify registers it at deploy time.
  • action="/thank-you.html" for the no-JavaScript redirect path.
  • data-netlify="true" so the Netlify build bot picks it up and routes submissions to the dashboard.

The data-netlify="true" attribute is load-bearing. Without it the POST has nowhere to go on Netlify's side, regardless of what the action URL says. The build bot reads the HTML during deploy and registers the form endpoint. Skip that attribute and you have a form that looks like it works but silently drops every submission.

What Netlify Actually Returns

When JavaScript is available, the form is submitted via fetch rather than a native browser POST. Netlify returns a 200 response when it has accepted and stored the submission. That response is the earliest moment you have evidence of a real lead.

  • Before the 200: the user has typed something and clicked submit. That is intent, not a lead.
  • On the 200: Netlify has the data. This is when the conversion event fires.
  • After the redirect: the user sees /thank-you.html. This is UX, not tracking.

Firing the event inside the fetch success callback, keyed on that 200, means every event in GA4 or Meta corresponds to a submission Netlify actually received.

GA4 and Meta Events Gate on the Acknowledgement

For the notes subscribe form, GA4 sign_up and Meta CompleteRegistration fire only after Netlify acknowledges a real submission. The same rule applies to the project-application form. Both forms follow the same pattern because the failure mode is identical: fire too early and you count noise, fire on the page view and you count bots.

The practical wiring looks like this:

  • Submit via fetch to the Netlify form endpoint.
  • In the .then() or await success branch, fire gtag('event', 'sign_up', ...) and the Meta pixel event.
  • Then redirect the browser to /thank-you.html or update the UI.

The order matters. If you redirect first and rely on a page-view event on the thank-you page, you have already lost control of what gets counted.

The No-JavaScript Edge Case

With data-netlify="true" and a plain action attribute, Netlify handles the POST server-side and redirects the browser. No JavaScript runs. You cannot fire a client-side event in that flow.

Your options are:

  • Accept the gap. No-JS submissions go untracked client-side. For most audiences this is a small percentage.
  • Server-side conversion import. Pull the Netlify submissions API and import conversions into GA4 or Meta after the fact.
  • Netlify Functions. Intercept the submission in a function, fire a server-side event, then redirect.

On dil.dev the JS path is the primary path. The no-JS redirect exists as a fallback for accessibility and resilience, not as the main tracking surface.

Why Mixing Signals Breaks Optimisation

If your report contains both page-view conversions from /thank-you.html and submission-acknowledgement events from the fetch callback, you have two numbers that do not agree and no clean way to reconcile them.

  • Attribution breaks. The page-view conversion might attribute to a different session or source than the fetch event, depending on timing and how the redirect is handled.
  • Rates become meaningless. A 4% conversion rate calculated on page views and a 2.8% rate calculated on acknowledgements are not two measurements of the same thing.
  • Optimisation targets the wrong signal. If you optimise ad spend toward the higher number, you are chasing noise.

Pick one signal. Make it the acknowledgement. Delete the page-view trigger.

Checking Your Own Setup

A quick audit takes about ten minutes:

  • Open the network tab. Submit the form. Look for the POST to the Netlify endpoint and confirm it returns 200.
  • Check the GA4 DebugView. The conversion event should appear after the 200, not before, and not on page load of /thank-you.html.
  • Check Meta Events Manager. Same timing check. If CompleteRegistration fires on the page view, the pixel is wired to the wrong trigger.
  • Visit /thank-you.html directly. No conversion event should fire. If one does, you have a page-view trigger that needs removing.
  • Check Netlify config path handling if the redirect itself is misbehaving. A misconfigured redirect can send the browser somewhere unexpected and make the timing analysis harder.

What I'd do differently

The no-JS fallback is the part I would revisit. Right now a submission via the native browser POST goes untracked client-side, and that gap is accepted rather than solved. A lightweight Netlify Function sitting in front of the form endpoint could fire a server-side event to GA4's Measurement Protocol before redirecting, closing the gap without requiring JavaScript on the client. The added complexity is real, but so is the blind spot. For a contact form where every submission has meaningful value, the Measurement Protocol route is worth the extra wiring.

NOTES BY EMAIL

Get the next note in your inbox.

One email per note. No spam. Reply “stop” any time and you are off the list.