How to Track Form Conversions in WordPress with GA4

Most WordPress sites can tell you how many people visited last month. Far fewer can tell you which of those visits turned into an actual enquiry — and that second number is the one that pays the bills. If your contact form is the main way people reach you, “how many submissions came from organic search versus that newsletter versus the ad you’re paying for?” is the most useful question your analytics can answer.
Google Analytics 4 can answer it, but the setup is fiddly on WordPress and the “easy” option quietly under-reports on most sites. Here’s how form conversion tracking actually works in GA4 as it stands in 2026, three ways to implement it, and the pitfalls that make people’s numbers wrong without them noticing.
First, the vocabulary changed
If you’re following an older tutorial, one thing trips you up immediately: GA4 no longer calls them conversions. In March 2024 Google renamed conversions to key events across the entire interface — every toggle, report column, and API field. “Conversion” now means specifically a key event imported into Google Ads. The mechanics didn’t change: you send an event, then flag it as important. But when a guide says “mark the event as a conversion,” the toggle you’re hunting for reads Mark as key event.
Why bother tracking form conversions at all
- Which pages produce enquiries. Not which get traffic — which get results. Frequently different pages, and the gap is where your content strategy lives.
- Which channels are worth money. GA4 attributes key events to acquisition sources, so you stop guessing which effort is doing the work.
- Whether your changes helped. Trimmed the form from nine fields to four? Without tracking you’re relying on vibes; with it you have a before and after.
- Better ad spend. Importing the key event into Google Ads lets bidding optimise for enquiries rather than clicks.
None of that works if the underlying event is unreliable, which brings us to the three ways of firing it.
Method 1: GA4 Enhanced Measurement (easiest, least reliable)
GA4 ships with Enhanced Measurement, toggled per web data stream in Admin > Data streams. Alongside scroll depth and outbound clicks it includes form interactions, collecting two events automatically: form_start when a visitor first touches a field, and form_submit on submission. No code, no tag manager. So why isn’t this the end of the article?
Why it misses most WordPress forms
The listener hooks into the browser’s native form submission — a standard HTML <form> doing a standard submit. Most WordPress form plugins don’t do that. They intercept the submit, send data over AJAX, and swap in a success message without reloading, so the event GA4 waits for either never fires or gets cancelled first. Two more wrinkles:
- It doesn’t distinguish forms. When it does fire, it fires for every form it detects — search box, newsletter signup, comment form. Counting all of those as enquiries makes your conversion rate look great and means nothing.
- Caching plugins break it. Aggressive JS minification, script combining, and “delay JavaScript execution” disturb the initialisation order, so events fire inconsistently or stop entirely. A common cause of “it worked last month.”
Our honest take: leave form interactions on — form_start is genuinely useful for spotting forms people begin and abandon — but don’t build your reporting on form_submit without verifying it fires on your specific form.
Method 2: the thank-you page (most reliable, small trade-off)
The oldest trick in the book is still the sturdiest. Configure your form to redirect to a dedicated confirmation page after a successful submission — something like /thank-you/ — and count views of that page as the conversion. It doesn’t depend on JavaScript listeners or plugin internals; a page_view on a URL is about the most robustly tracked thing in analytics. And because the redirect only happens after server-side validation passes, you’re counting successes rather than attempts. To set it up:
- Create the thank-you page and set it to
noindex, so strangers can’t find it in search and inflate your numbers. - In your form plugin, set the after-submit action to redirect there. Give each form its own page if you want to tell them apart.
- In GA4, go to
Admin > Events > Create eventand build a custom event — call itgenerate_lead— that fires whenevent_nameequalspage_viewandpage_locationcontains/thank-you/. - Mark that new event as a key event.
The trade-off is UX: you lose the smooth inline success message, and some plugins make redirect-after-submit awkward for multi-step or popup forms. Usually worth it, and a thank-you page is prime real estate anyway — we cover what to put on it in our guide to contact page best practices.
Method 3: a custom event on the success hook (most flexible)
If you want inline success messages and reliable tracking, fire your own event at the exact moment the plugin says the submission succeeded. Nearly every WordPress form plugin exposes a JavaScript event or callback for this — Contact Form 7 has wpcf7mailsent, others emit custom DOM events.
Push a named event with a little context — which form, which page — so you can segment later instead of staring at one undifferentiated number.
If you use Google Tag Manager, push to the data layer and let a Custom Event trigger fire your GA4 tag. An illustrative snippet, using Contact Form 7’s success event:
document.addEventListener('wpcf7mailsent', function (e) { window.dataLayer = window.dataLayer || []; window.dataLayer.push({ event: 'form_success', form_name: 'contact-main', form_id: e.detail.contactFormId }); });
Then in GTM: a Custom Event trigger matching form_success, attached to a GA4 Event tag sending generate_lead with form_name as a parameter. Without GTM, if gtag.js is on the page, skip the data layer and call gtag('event', 'generate_lead', { form_name: 'contact-main' }) in the same listener.
Two details that save pain later: register form_name as a custom dimension under Admin > Custom definitions or the parameter never shows up in reports, and prefer a recommended event name like generate_lead over an invented one, since Google’s reporting and Ads integrations understand it.
Comparing the three
| Method | Setup effort | Reliability on WordPress | Can tell forms apart | Best for |
|---|---|---|---|---|
| Enhanced Measurement | One toggle, no code | Poor for AJAX forms; breaks with caching plugins | No — fires for all forms | A rough signal, and form_start abandonment data |
| Thank-you page | Low — a page, a redirect, one GA4 rule | High — just a page view | Yes, with one page per form | Most small business sites |
| Custom event / dataLayer | Medium — a snippet plus GTM | High, if the hook is correct | Yes, via event parameters | Inline success messages, multi-step and popup forms |
Marking it as a key event
Sending the event isn’t enough — GA4 treats it as ordinary until you say otherwise. Once you’ve seen it arrive, go to Admin > Events, find the name, and switch on Mark as key event. (You can pre-register a name that hasn’t fired yet under Admin > Key events.) It then appears in the Key events report, can define audiences, and can be imported into Google Ads. The flag isn’t retroactive, so do this early.
Verifying it actually works
Do not skip this. Assume it’s broken until you’ve watched it fire.
- DebugView. Install the Google Analytics Debugger Chrome extension (or use GTM’s Preview mode), then open
Admin > DebugView. Submit your form and watch the event stream live — the only place you can confirm parameters are arriving correctly. - Realtime report. A coarser check that the event registers at all; less detail, no setup.
- Wait 24–48 hours. Standard GA4 reports lag. If the event shows in DebugView but not in reports an hour later, that’s normal.
Pitfalls that quietly corrupt your numbers
- Double counting. The classic: a custom event and Enhanced Measurement both firing, or a GTM tag duplicating a plugin’s built-in event. Pick one source per form and confirm in DebugView that exactly one event arrives per submission.
- Spam and bots inflating everything. Every junk submission reaching your success handler is a fake conversion. Fix the cause, not the report — our guide on stopping WordPress form spam covers honeypots and time-based checks that block bots without adding friction.
- Consent mode gating your events. With Google Consent Mode, events are withheld or sent as cookieless modelled data until the visitor accepts analytics storage. Correct behaviour, but reported conversions land below reality by a margin that varies with your audience’s region.
- Testing from your own IP. Your own test submissions count. Define internal traffic filters under
Admin > Data streams > Configure tag settingsand set the filter to Active — it defaults to Testing mode, which does nothing to live data. - Counting attempts, not successes. An event fired on button click rather than the plugin’s success callback counts validation failures too.
- Ad blockers. A meaningful slice of visitors block GA entirely, so GA4 always under-reports against a server-side record.
Analytics counts submissions; it doesn’t keep them
Worth naming a limit of this whole exercise: GA4 tells you that a submission happened, on which page, from which channel. It deliberately doesn’t tell you what the person said, and you shouldn’t send names or email addresses into it — that breaches Google’s terms on personal data. Analytics is your measurement layer, not your record of leads, so you still want every entry stored on your own site.
Plenty of plugins do this; to be upfront, we build one — our free Trinity Forms stores every entry natively in your WordPress database rather than trusting a notification email to survive the trip. Whatever you use, make sure something keeps the entries and can export them to CSV when you need to reconcile the two.
The bottom line
Start with a thank-you page if you can live with the redirect — best reliability for the least work, and it survives caching plugins and plugin updates. Move to a data layer push on the success hook when you need inline confirmations or want to distinguish several forms. Treat form_submit as a bonus signal rather than a source of truth, verify in DebugView before believing a number, and expect GA4’s count to sit below your entries table. That gap is normal; not knowing which page or channel produced the enquiry is the thing worth fixing.
Frequently asked questions
Why is GA4’s form_submit event not firing on my WordPress form?
Almost always because your form submits over AJAX. Enhanced Measurement listens for a browser’s native form submission, and most modern WordPress form plugins intercept that and send data in the background instead, so the event GA4 is waiting for never arrives. Caching plugins that minify, combine, or delay JavaScript can break it too. Use a thank-you page redirect or a custom event on the plugin’s success hook instead.
Are conversions and key events the same thing in GA4?
Effectively, yes. Google renamed conversions to key events across GA4 in March 2024, so the admin toggle you’re looking for now reads “Mark as key event.” The word conversion is now reserved for a key event that has been imported into Google Ads. The mechanics of sending and flagging the event are unchanged.
Why does GA4 show fewer form conversions than I have entries?
Several reasons stack up: ad blockers stop GA4 loading for some visitors, consent banners withhold events until someone accepts analytics storage, and any submission that bypasses the tracked path won’t be counted. A gap between GA4 and your stored entries is normal and expected — treat your entries table as the true count and GA4 as the source of attribution insight.