# 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.

- Author: Dil Ahdan (https://dil.dev/)
- Published: 2026-09-30
- Updated: 2026-09-30
- Tags: netlify, analytics, forms, conversion
- Canonical: https://dil.dev/notes/thank-you-page-is-not-a-lead/

## Key takeaways

- A thank-you page visit can happen without a form submission, so it is a vanity metric at best.
- Netlify Forms returns a real server acknowledgement on POST, and that is the correct moment to fire conversion events.
- GA4 sign_up and Meta CompleteRegistration should both gate on the Netlify acknowledgement, not on a URL change.
- The project-application form on dil.dev uses action /thank-you.html with data-netlify=true, and tracking fires only after the network round-trip completes.
- Mixing page-visit and submission signals in the same report makes optimisation impossible.

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](/notes/netlify-config-path-vs-redirect/) 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.

## Quick answers

**Why is a thank-you page visit unreliable as a conversion signal?**

Anyone can navigate directly to /thank-you.html without ever submitting a form. Bots, link-preview crawlers and your own QA visits all land on that URL. Counting the page view means your conversion rate is always higher than reality.

**When exactly should I fire a GA4 or Meta pixel event for a Netlify form?**

Fire it inside the success callback you get after the fetch or XHR to the Netlify endpoint returns a 200. That response means Netlify has accepted and stored the submission. Anything earlier is speculation.

**Does Netlify Forms work without JavaScript?**

Yes. With a plain HTML form and action pointing to a thank-you page, Netlify handles the POST server-side and redirects the browser. In that no-JS flow you cannot fire a client-side event, so you need a server-side conversion import or accept the gap.

**What is data-netlify=true actually doing?**

It tells the Netlify build bot to register the form during the deploy so submissions are captured in the Netlify dashboard. Without it the POST goes nowhere useful, even if the action URL looks correct.

**How do I avoid double-counting if I have both a redirect and a JS event?**

Pick one signal and stick to it. If you redirect to /thank-you.html and also fire a JS event in a success callback, you will count the same submission twice in any tool that tracks both. On dil.dev the JS callback fires the event and the redirect is purely for user experience.

**Should the notes subscribe form use the same pattern?**

Yes. GA4 sign_up and Meta CompleteRegistration for the notes subscribe form fire only after Netlify acknowledges the submission, matching exactly the same rule as the project-application form.
