For seven months, anyone who reached wppoland.com through a campaign link was 301-redirected to the same URL without its tracking parameters. From 7 March 2026 to 10 October 2026 our Cloudflare Pages middleware treated utm_*, gclid, fbclid and msclkid as duplicate-content parameters and removed them before the browser ran a single script. Analytics never saw a campaign and Google Ads auto-tagging lost its gclid. From 13 July, when the contact form gained hidden lead-source fields, the form lost the source of every campaign lead as well.
We do not know how many leads this affected. There is no measurement we could count it from, so we give no number. What we do know is that campaign and lead-source data from that period is incomplete and cannot support channel conclusions.
How to test if a redirect strips UTM parameters
Start with the test, because it takes one line. A unique parameter value bypasses any cache, so the answer comes from the live logic:
curl -sI "https://wppoland.com/pl/?utm_source=t$(date +%s)"After the fix this returns HTTP/2 200, and so does the same request with ?gclid=. As a control, a parameter that is still meant to redirect:
curl -sI "https://wppoland.com/pl/?lang=en"That one returns 301. We checked all three on production on 11 October 2026.
On your own site, swap the domain and the parameter. Test utm_source, gclid, fbclid and msclkid separately, because rules often treat them differently. If you get a 301 or 302, read the Location header: the parameter has to be there. Then repeat the test on URLs that redirect for some other reason: a missing trailing slash, the other host (with and without www), an old slug. A page that answers 200 can pass the test while the redirect next to it still drops the parameters.
Why UTM parameters disappear after a redirect
A 301 is a server response with a Location header. The browser adds nothing of its own: it goes exactly to the address the server built. If the rule that builds that address drops the query string or part of it, the campaign parameters are gone before the page loads.
That matters because almost all campaign attribution happens in the browser. The analytics tag reads utm_source from location.href. A form that stores the lead source in hidden fields fills them with JavaScript from location.search. Google Ads auto-tagging appends gclid to the landing page URL and expects that identifier to reach the page. Each of these mechanisms only sees the URL the browser finally landed on.
So every redirect between an ad and a page is a place where attribution can die. Not only redirects you wrote by hand. Also host normalisation, trailing slashes, old slugs and query-parameter deduplication.
Why Cloudflare Pages middleware removes gclid and utm_source
A commit on 7 March 2026, described as improving URL handling in middleware and headers, added a list of duplicate-content parameters to functions/_middleware.ts. The function hasDuplicateContentQuery checked whether a URL carried any of them. If it did, filteredQueryString built a query string without those parameters and the middleware answered with a 301 to the result.
The list held parameters that really do create pointless variants, such as lang, amp, nonamp and s. It also held utm_source, utm_medium, utm_campaign, utm_content, utm_term, gclid, fbclid and msclkid. The goal sounded reasonable: one URL per page. The result was that a link to /en/?utm_source=newsletter ended at /en/ before any browser code saw the word “newsletter”.
Middleware in Pages Functions runs on every request, ahead of the rest of the routing. That makes it a convenient place for URL normalisation, and an equally convenient place for a bug that touches every campaign visit.
Why hidden UTM fields in a contact form come through empty
Since 13 July 2026 our contact form has hidden utm_source, utm_medium, utm_campaign and utm_term fields. Before that date it recorded no lead source at all. JavaScript fills the fields from location.search when the page loads. After the redirect location.search was empty, so the fields were too, for every visit from a campaign link between 13 July and 10 October.
The damage landed in three places:
- The form (from 13 July). Leads reached the inbox with no source. A visit from a newsletter link and a visit with no tagging at all looked identical.
- Analytics. The analytics tool never received campaign parameters, so traffic from UTM-tagged links fell into generic channels or into direct.
- Google Ads. Auto-tagging appends
gclidand our 301 removed it. Withoutgclidon the landing page, Google Ads has nothing to tie the click to a later conversion.
None of these symptoms looks like a redirect bug. It looks like a campaign that does not work, or a channel that brings nothing.
Strip UTM parameters at Cloudflare without losing attribution
SHIFT64 described the same symptom through a different path. Their article on stripping tracking parameters at Cloudflare was published on 31 August 2026 and corrected on 7 October 2026. The original version recommended a Transform Rule that rewrote the URL at the edge (no redirect), so the cache saw one URL per page. The browser kept the full address, so attribution was supposed to survive.
It survived only when the origin answered 200. When the origin answered with a redirect (apex to www, a missing trailing slash, a WordPress canonical redirect), it built the new address from what it received: the already-stripped URL. The browser followed it and gclid, fbclid and gad_source vanished from the address bar. The correction also lists a regex problem:
“Non-adjacent tracking parameters were only partly removed, because Cloudflare’s
regex_replace()replaces only the first match.”Mateusz Zadorożny, SHIFT64, Strip UTM Parameters at Cloudflare Without Losing Attribution (Corrected), correction dated 7 October 2026
And a URL like ?fbclid=x&color=red reached the server as ?&color=red, which WordPress answered with a 301. According to SHIFT64, on one store running Google Ads the bug showed in the logs as 21 paid landings over about three weeks, plus landings on the non-canonical host that the logs cannot count. They replaced the rule with a Worker that re-appends the stripped parameters to same-site redirects. SHIFT64 also advises that if the Super Page Cache plugin created a [DO NOT EDIT] rule with the same regex, you switch off its “strip tracking parameters” option. We have not tested that plugin ourselves.
The dates: SHIFT64’s correction on 7 October, our fix on 10 October. The difference is the mechanism. SHIFT64 lost the parameters through an origin redirect that followed an edge rewrite. We lost them through a deliberate deduplication redirect of our own.
Does AI chatbot traffic show up as direct in GA4
It can. Our reading of two reports published on 1 October 2026 is that a redirect like ours costs more now than it did in March.
Search Engine Journal (Roger Montti) reported that Gemini appears to add UTM parameters to some links to websites. The report rests on one Reddit user, who called the behaviour “very new, 24 hours or so”. Google has not documented it. Nobody has published which parameters or values Gemini adds, to which links, or under what conditions. John Mueller replied only “I’m happy to forward that to the team”, which is not a confirmation. The same article notes that AI chatbot traffic can show up in GA4 as direct, because direct is the fallback when a visit carries neither a referrer nor UTM data.
DemandSphere (Ray Grieselhuber) tracked the share of branded keywords that return an AI Overview: 26.12% on 1 September, a peak of 90.48% on 27 September and 82.06% on 29 September, their last data point. The numbers come from their own platform, DemandMetrics, across all markets and devices. The sample size is not published, and an AI Overview counts whether or not it cites the brand. Google has announced no change.
The link to our bug is our inference; neither source makes it. If AI assistants start tagging their links, the tags arrive in the same query string our middleware was cutting. A redirect that strips utm_* strips them too, and the visit falls back to direct. If more branded clicks pass through an AI Overview first, the clicks that still arrive tagged carry more of the attribution you have left. We have no evidence that Gemini traffic reached wppoland.com during the bug window, and we do not claim we lost any. Our own event tracking does not record the referrer, so for search we take source data from Google Search Console.
Do UTM parameters cause duplicate content
Not here, and the redirect protected against nothing. Every page on wppoland.com declares a canonical without parameters, so Google already knew which URL was the right one. From 12 April 2026, public/_headers also sent this header:
No-Vary-Search: key-order, params=("utm_source" "utm_medium" "utm_campaign" "utm_content" "utm_term" "ref" "fbclid" "gclid" "msclkid")No-Vary-Search tells the browser that the listed parameters do not change the response, so the version with them and the version without can share one cache entry. From 7 March to 11 April the canonical was the only protection, and it was enough. From 12 April there were two layers that solved duplication without touching the URL in the address bar. At no point did the redirect add protection, and the whole time it took attribution away.
The fix of 10 October 2026 lets tracking parameters through with no redirect. lang, amp, nonamp and s still get a 301, because those are the ones that create real variants. The diff left this comment in the code:
// Tracking params (utm_*, gclid, fbclid, msclkid) pass through: the page
// canonical is already clean, and stripping them killed lead attribution.Which redirect rules strip UTM parameters and gclid
The lesson is not specific to Cloudflare Pages. Any rule that “tidies” the query string and answers with a redirect has the same risk profile:
- middleware in Pages Functions or in a Worker,
- Cloudflare rules: Transform Rules, Redirect Rules, Page Rules,
rewriteandreturn 301in an nginx config,- WordPress redirect plugins that normalise URLs or drop “unnecessary” parameters,
- WordPress’s own canonical redirects, when something upstream has already cut the URL.
The rule we adopted: parameter deduplication leaves tracking parameters alone. Canonical handles duplicate content, and No-Vary-Search or a cache key without those parameters handles the cache. A redirect is not needed for either. The second piece of advice comes from SHIFT64’s own correction: test redirects, not only pages.
If your site sits behind Cloudflare and you want someone to review the edge rules with this in mind, that is part of our Cloudflare edge service.
How to treat analytics data from a period of stripped UTM parameters
Campaign data in analytics and Google Ads between 7 March and 10 October 2026 is incomplete, and so is the form lead source between 13 July and 10 October. That does not make all of it wrong: visits without campaign parameters, such as clicks from organic search results, never went through this redirect. It means that everything arriving from tagged links was credited somewhere else or nowhere.
In practice:
- we do not compare UTM-dependent channels in that period with the period after 10 October,
- we do not switch off campaigns based on zero attribution from those months,
- the first reliable campaign and lead-source data starts on 10 October 2026.
The routing layer on this site has broken something quietly before, while everything else looked healthy: Cloudflare Pages dropped _redirects rules past 100KB. The wider context of this architecture is in our write-up of twelve months migrating from WordPress to Astro on Cloudflare Pages. Clean canonicals for links that carry parameters are covered in the technical guide to affiliate SEO.







