Skip to main content

Google Ads

The GA4 conversion in Google Ads fired on a /thank-you/ page that returned 200 to curl

7 min read

Run this against your own site:

curl -I https://yoursite.com/thank-you/

If it comes back HTTP/1.1 200 OK (no redirect, no token in the URL, no session check), then anyone can load that page. Anyone. A bot. A colleague clicking a link in a CRM note. The person who just submitted the form, hitting refresh. And whatever tag fires on that pageview fires for all of them.

That is the whole mechanism. Everything below is what it looked like in one account, and what it did to the numbers.

What we found

The site was WordPress on a LiteSpeed server. Forms were Contact Form 7. A redirect plugin sent every successful submission to /thank-you/. Google Tag Manager loaded on every page, including that one, and fired a GA4 event on the thank-you pageview. That GA4 event was imported into Google Ads as a conversion action.

Layer

Component

What it did

Form

Contact Form 7

Collected the enquiry

Redirect

CF7 redirect plugin

Sent the browser to /thank-you/ on success

Tag container

GTM (one container ID, no hardcoded tags anywhere else)

Loaded on /thank-you/

Event

GA4 custom event on thank-you pageview

Fired once per pageview

Conversion

GA4 event imported into Google Ads

Counted as a conversion

Counting

"Every" (MANY_PER_CLICK)

One click could produce several conversions

Each layer is a reasonable choice on its own. Stacked, they produce a conversion that fires whenever a URL loads, with no check on how the URL was reached.

The query-string multiplier

One detail made it worse. The redirect plugin appended every submitted form field to the destination URL:

/thank-you/?your_name=Jane&your_email=jane%40example.com&your_phone=..

That's a common plugin behaviour, usually so the thank-you page can personalise itself. But it means every submission produces a unique URL. To GA4, /thank-you/?your_name=Jane and /thank-you/?your_name=Jim are different pages. To a counting rule set to "every", they're different conversions even from the same click if the person goes back and resubmits.

Scenario

Pageviews of /thank-you/*

Conversions counted

One submission

1

1

Submit, refresh

2

2

Submit, back, resubmit with a typo fixed

2 (different query strings)

2

Submit, bookmark, revisit next day

2

1 per session, or 2 if "every"

Support agent opens the URL from a ticket

1

1

How much it inflated

We compared the GA4 web-form action against a second action on the same form, a Google Ads tag configured to count once per click. Same page, same submissions, different counting rules.

Period

GA4 action

Ads-tag action

Ratio

15–31 Aug

137.4

22.0

6.25×

2–4 Sep (after GA4 counting changed)

31.4

14.0

2.24×

The Ads-tag action under-fires for its own reasons (enhanced conversions matching), so the ratio isn't a clean inflation factor. But the drop from 6.25× to 2.24× after the counting rule changed is the size of the effect. The GA4 action had been reporting something like three to six times the unique submissions for as long as it had existed.

Smart bidding was optimising to that number.

The page that had six forms on it

While inspecting the site we pulled the main panel landing page and counted the forms.

Page

Page weight

Load time

Contact Form 7 instances

Existing panel page

245 KB

0.62 s

6 (f26565, f29632, f29638, f30111, f30838, f3183)

Rebuilt panel page

45 KB

0.26 s

1 (f26565)

Six separate form IDs on one page. Nobody designed that; it accreted over rebuilds. Beyond the speed cost, it raised a question the tracking couldn't answer: did all six redirect to /thank-you/? Did all six fire the event? If two of the six didn't, part of the measured conversion rate was a measurement gap, not a page problem. Consolidating to one form removed the question.

The fix, in four layers

Each layer closes a hole the previous one leaves open.

Layer

Change

What it stops

What it doesn't

1

GA4 key event counting: once per session

Refresh, back button, resubmit in the same session

A return visit tomorrow

2

GTM trigger: fire only if a query parameter the redirect sets is present

Bare /thank-you/ visits, bookmarks, shared links

A crafted URL with the parameter

3

Fire on the form submit event, not the destination pageview

Every pageview-based inflation

Nothing significant. This is the correct design

4

Redirect carries a one-time token the server validates

Everything, including crafted URLs

Needs server-side work

Layer 1 is a dropdown in GA4 and was applied in this account within a day. Layer 2 is a GTM trigger condition, five minutes with container access. Layer 3 is the right long-term design and is what the rebuilt page should use. Layer 4 is belt-and-braces for high-value forms.

The trap after you fix it

Having changed the GA4 counting method to once-per-session, we checked the Google Ads side to confirm. It still read:

Field

Value

conversion_action.counting_type

MANY_PER_CLICK

Days later, unchanged. The natural conclusion is that the fix hadn't propagated. It had. For GA4-imported conversion actions, the Ads-side counting field does not reflect the GA4 setting. GA4 does the counting and exports the result; the Ads label stays at whatever it was. Do not use that field to verify a GA4 counting change. Use volume, compare the action against a one-per-click control over a week and watch the ratio.

The archaeology in the conversion list

Inspecting the account's conversion actions turned up the previous attempts to solve this:

Action name

Status

What it was

Thank_You_GA4

Archived

First version of the thank-you pageview event

Thank_You_GA4_once_per_session

Archived

Someone tried fixing the counting with a second event instead of a setting

Thank_You_GA4_All_Events

Archived

A third variant

cf7_form_submission

Archived

The form plugin's own submit event, layer 3 above, built and then abandoned

Form_Enquiry_Thank_You_GA4

Live

The current one, still on pageview

Someone had built the correct solution, cf7_form_submission, and then it was archived in favour of the pageview version. Which is the pattern: the pageview event is easier to verify in the interface because you can load the page and watch it fire. That ease is exactly the problem.

How to check your own site

  1. curl -I the thank-you URL. If 200, keep going.

  2. Open it in a private window. If it loads cleanly, so does it for everyone.

  3. Open GTM, find the trigger on your conversion tag. If it's "Page View: Page Path contains /thank-you", you have this.

  4. Check the counting type on the conversion action in Google Ads. If it's "Every" on a lead form, it's inflated.

  5. Segment conversions by action over the last 30 days. If two actions are within a factor of two of each other and both fire on the form, they're probably the same event.

Symptom

Likely cause

Conversion rate looks too good

Pageview trigger + "every" counting

Conversions arrive in clusters on the same click

Refresh or resubmit

Conversions with no matching lead in the CRM

Non-submission visits to the URL

Two form actions with different totals

Different counting rules on the same event

Which event to fix, when five look the same

Once the counting problem was identified, the fix was a dropdown in GA4: change the key event's counting method from "Once per event" to "Once per session." The hard part turned out to be knowing which event.

The GA4 property carried five events with nearly identical names, four of which had at one point been imported into Google Ads and later archived:

GA4 event name

Imported into Ads?

Status

Form_Enquiry_Thank_You_GA4

Yes

Live. This is the one

Thank_You_GA4

Yes

Archived

Thank_You_GA4_once_per_session

Yes

Archived

Thank_You_GA4_All_Events

Yes

Archived

cf7_form_submission

Yes

Archived

Change the counting method on Thank_You_GA4 and nothing happens to the live conversion. The name that matters is the one the live Ads conversion action points to: visible on the conversion action's detail page in Ads, or via conversion_action.google_analytics_4_settings.event_name in the API. Check that before you change anything in GA4.

Everything went through GTM, which is the control point

One structural detail from the server inspection is worth stating plainly. The site's source contained no hardcoded tag IDs at all: no gtag() calls, no AW- conversion IDs, no G- measurement IDs. Everything fired through a single GTM container.

What this means

Consequence

All conversion logic lives in GTM

GTM access is the only place the trigger can be fixed

No tag fires without GTM

If GTM is blocked (consent, ad blocker), no conversion is recorded, a separate under-counting problem

One container to audit

The full picture is in one place, which is the good news

If you're auditing a site and find the same thing, get GTM access before anything else. Without it you can diagnose the problem but not fix it, and every recommendation stays hypothetical.

The principle

A conversion should fire on the thing you're paying for (a submission, a call, a purchase), not on a page that usually follows it. The moment the trigger is a URL, you're counting visits to a URL, and a URL is something people can visit for any reason at all.

Thirty seconds with curl tells you whether that's your setup. If it is, every downstream number in the account is built on it.

Related services

Filed under

google-adsconversion-trackinggtmga4wordpresscontact-form-7thank-you-page

Keep reading

More from Insights