A Case Study by Yuval Greenberg , Growth & Ecommerce SEO Lead Cut Inside.
TL;DR
A developer followed best practices. An SEO lost thousands of indexed pages. Both were doing their jobs correctly. The problem wasn’t competence – it was a gap in how two disciplines think about URLs. Here’s the story of how a “clean code” fix quietly killed our highest-converting pages, and what we do differently now.
Two People Doing Their Jobs Right
Here’s a sentence that should terrify you:
“We cleaned up some legacy code during the server move.”
A global enterprise client was migrating from on-premise to cloud. Standard infrastructure project. The dev team handled it well – same design, same URLs, same content. Nothing user-facing changed.
Except traffic to filtered category pages dropped to zero.
These weren’t random pages, they were money pages.
Users filtering for “50TB Hard Drives” or “Enterprise SSDs” – high intent, high conversion. The kind of pages that justify an SEO budget.
Gone.
What “Clean” Means to a Developer
When a developer looks at a URL like this:
domain.com/products?capacity=50tb&type=enterprise
They mostly see parameters. Messy, potentially duplicative. A source of crawl bloat.
The instinct is to normalize. Point everything to the clean parent:
domain.com/products
So during the cloud migration, someone added a canonical tag that did exactly that. Every filtered page now told Google: “I’m not the real page. Go index the parent instead.”
From a code hygiene perspective, this is correct. From an SEO perspective, this is a disaster.
What “Clean” Means to an SEO
That filtered URL isn’t a duplicate. It’s a landing page.
Someone searching “50TB enterprise hard drives” has a specific need. A page filtered to exactly that spec is the answer. It should rank, and it should convert.
Canonicalizing it to the parent is like telling a user “We have what you want, but let me show you everything else first – That’s a horrible customer experience.
Google got the signal: these pages don’t matter. So Google stopped showing them.
The Actual Code
What launched:
<link rel=”canonical” href=”domain.com/products”/>
What we needed:
<link rel=”canonical” href=”domain.com/products?capacity=50tb”/>
One line. Thousands of pages de-indexed.

The Recovery
We caught the drop, audited the headers, pushed a fix to restore self-referencing canonicals.
Recovery was fast. The moment Google saw the corrected tags, pages came back.
The fix took minutes, finding it took longer.
And the weeks of lost traffic don’t come back.
The Deeper Problem
This wasn’t a mistake. It was a translation failure.
The developer applied a legitimate pattern – consolidate canonicals to avoid duplicate content. In many contexts, that’s right. But filtered category pages aren’t duplicates. They’re distinct answers to distinct queries.
Nobody was wrong. The teams just didn’t have a shared understanding of what “clean” means.
This is why SEO can’t sit outside the dev process. By the time you see the traffic drop, the damage is done. The conversation needs to happen before the code ships.
What We Do Now
SEO reviews every infrastructure change. Not just redesigns. Not just URL changes. Server moves, platform migrations, CMS updates – all of it. “Nothing user-facing is changing” doesn’t mean nothing SEO-facing is changing.
Canonical logic is documented and agreed on. Which pages self-reference? Which consolidate? This isn’t a developer decision or an SEO decision. It’s a joint decision, made explicitly, before launch.
Filtered pages get tested in staging. Pull a sample of high-value parameterized URLs. Check the canonical tags. Check the indexability. Don’t assume the logic carried over.
We treat parameters as intent signals. The whole team understands: a URL parameter isn’t clutter. It’s a user telling you exactly what they want. Handle it like the revenue opportunity it is.
The scariest bugs aren’t the ones that throw errors. They’re the ones where everyone thinks everything is fine.
A developer followed best practices. An SEO lost thousands of pages. Both were right in their own context. The problem was the gap between them.
Close the gap before you ship.
Ever had a “clean code” fix break something unexpected? What’s your process for catching this stuff before launch?

