Skip to content
VERQEN — home

Case study · Ecommerce

Twelve thousand product pages that could not rank for their own model names

A canonical rule added during a duplicate-content cleanup pointed every product URL at its parent category. The catalogue was invisible for its highest-intent queries and nobody had connected the two facts.
Industry
Ecommerce
Published
12 June 2026
Reading time
6 min
Type
Worked example
  • 11,902

    Product URLs canonicalised away

    of 12,480 crawled

  • 0

    Indexed product URLs at baseline

  • 94

    Days from release to detection

    nobody owned coverage reporting

  • 1 sprint

    Effort to fix the rule

This is a worked example, not a client result

It shows the investigation order, the finding format and the reasoning we use on real projects, built from a pattern we encounter repeatedly. The figures are illustrative. We publish client numbers only when they are real, measured, and the client has agreed to them being published.

This is a worked example. It shows the finding format, the investigation order and the reasoning we use on real projects, built from a pattern we encounter repeatedly. The figures are illustrative. We publish client numbers only when they are real, measured and the client has agreed to them being published.

Executive summary

A mid-market retailer with roughly 12,500 products had flat organic performance for three quarters. Total impressions looked stable, so nothing triggered an escalation. Underneath that stable total, one entire class of demand — searches for specific product model names, the highest-intent queries in the catalogue — had collapsed to almost nothing.

The cause was a single template-level canonical rule, added during a duplicate-content cleanup, that pointed every product URL at its parent category. It was a correct fix applied to the wrong scope.

Business problem

The company sells a catalogue where buyers frequently search by exact model name. Those searches convert several times better than category searches because the buyer has already decided what they want.

The symptom presented to us was not "we lost traffic". It was "we keep investing in SEO and nothing moves". Total impressions had not fallen, so the internal read was that the market had softened.

Baseline

Before analysing anything we established what the site was actually worth, per URL:

  • Full crawl with rendering enabled: 12,480 product URLs discovered.
  • 16 months of Search Console data, exported at page and query level.
  • GA4 landing pages and revenue by URL for the same period.
  • Query set classified by intent: brand, category, model-specific, informational.

Segmenting by query class was the step that made the problem visible. Site totals hide class-level collapse, which is exactly why the problem survived three quarters of reporting.

Investigation

The order matters, because each step eliminates a category of cause.

  1. Segment by page type and query class. Category impressions were stable. Model-specific impressions had fallen off a cliff. That immediately ruled out a site-wide cause.
  2. Check indexation, not position. No product URL appeared in the index. This is a completely different problem from ranking poorly, and it points at technical causes rather than content or authority ones.
  3. Read the coverage report by category. The product URLs sat under "Alternate page with proper canonical tag" — Search Console was reporting the cause plainly, but nobody was reading coverage by page type.
  4. Crawl and diff. 11,902 of 12,480 product URLs declared a canonical pointing at the parent category. The remaining 578 were newer products on a template variant that had not yet been migrated.
  5. Find the date. The crawl diff and the release log agreed: the rule shipped on 14 March, in a ticket titled "fix duplicate variant URLs".
  6. Confirm the mechanism. Category pages were receiving impressions for model-specific queries at position 20+ — they were being offered as the answer and rejected, because a category page is not the right answer to a model query.

Evidence

Check Finding
Product URLs crawled 12,480
Declaring a category canonical 11,902 (95.4%)
Indexed product URLs 0
Coverage category Alternate page with proper canonical tag
Model-query impressions, pre-release ~4,300/month
Model-query impressions, post-release ~380/month
Release date in change log 14 March, "fix duplicate variant URLs"

Every one of those rows is checkable. That is the standard: a finding that cannot be verified by the client is not finished.

Root cause

The original problem was real. Colour and size variants were generating duplicate URLs, and something needed to consolidate them.

The fix was implemented at the product template level rather than at the variant level. Because variants render through the same template as base products, the rule caught both. The ticket was tested by confirming that variant duplicates had disappeared from the index — which they had. Nobody tested whether base products were still there.

This is the most common shape of a self-inflicted technical SEO problem: a correct fix, applied one level too broadly, validated against the symptom it was written for rather than against the system.

Actions

Written as exact changes, with acceptance criteria, because a recommendation a developer has to interpret is not a recommendation.

  1. Scope the canonical rule to variant parameters only. Base product URLs self-canonicalise. Acceptance: a crawl of 500 sampled base product URLs shows a self-referencing canonical; a crawl of their variant URLs shows a canonical pointing at the base product, not the category.
  2. Remove product URLs from the category sitemap; publish a dedicated product sitemap. Acceptance: sitemap index lists a product sitemap containing only canonical, indexable, in-stock product URLs.
  3. Add internal links from category pages to the top 200 products by revenue. Acceptance: crawl shows each of those 200 URLs receiving at least one in-body internal link from its category.
  4. Request validation in Search Console for the affected coverage category after release.
  5. Add a release check: any change touching canonical, robots or status-code logic requires a staging crawl diff against production before merge.

Implementation

One sprint. The rule change itself was a few lines; the sitemap and internal linking work was the larger part. It shipped to staging first, and we ran the acceptance crawls there before release — which caught a second issue, where out-of-stock products were being excluded from the new sitemap but still linked internally.

Priority was P0, because the affected pages carried the catalogue's highest commercial intent and the fix was cheap. High impact plus low effort is the "do first" quadrant, and it does not need a debate.

Result

The honest answer, for a worked example, is what we measure and when we expect to see it:

  • Indexed product URLs — target above 90% of in-stock products within 60 days of release. This is the primary signal and it moves first.
  • Non-brand impressions on model-specific queries — measured against the 28 days before release, on the affected URL cohort only. Recovery of an indexation problem is usually visible within two to six weeks of recrawl.
  • Revenue per landing page on product templates, against the pre-release baseline.

We report the cohort, not the site total. A site total is what hid this problem in the first place.

What we learned

Three things worth carrying to the next project:

  • Site totals hide class-level failures. If reporting is not segmented by page type and query class, an entire demand class can disappear without moving the headline number.
  • Validate a fix against the system, not the symptom. The variant ticket was tested correctly and still caused this. The missing check was "what else does this rule now apply to?"
  • Coverage reports are diagnostic, not decorative. The cause was named explicitly in Search Console for 94 days. Someone had to be looking at it by page type.

What happens next

For a site in this position, the sequence after the fix is: confirm indexation recovery on the cohort, then look at whether the product template actually answers a model-specific query well enough to rank once it can. Indexation removes the barrier. It does not create the demand or win the position.

The data behind it

Impressions on model-specific queries against total site impressions

Indexed illustrative values. The site total masked a complete loss on one query class.

020K40K60KJanMarMayJulAug14 Mar release350Model-specific queries39.8KAll site impressions
  • Model-specific queries
  • All site impressions
View the data as a table
Impressions on model-specific queries against total site impressions
PeriodModel-specific queriesAll site impressions
Jan4,20041,000
Feb4,38042,500
Mar3,10041,800
Apr61039,900
May42040,100
Jun38039,600
Jul36040,300
Aug35039,800

Source: Illustrative reconstruction of the pattern this investigation follows