This case study is an anonymised, illustrative example of a technical SEO recovery. The client name is withheld and figures are representative of typical results rather than a single published account, so we can share the full process openly.
Snapshot
| Client type | Ecommerce store selling outdoor and camping gear, ~11,000 product URLs on WooCommerce with a heavily customised theme |
| Starting point | Organic traffic down 47% over five months, 62,000 URLs in Google’s “Crawled – currently not indexed” report, Core Web Vitals failing on mobile |
| Timeframe | 4 months of fixes, results measured at month 6 |
| Outcome | Organic traffic recovered and grew to 128% of the pre-drop level, indexed product pages up from 4,100 to 9,700, organic revenue +61% year on year |
The challenge
The client came to us after a site redesign and a migration to a new theme. Traffic had fallen steadily since launch. Their developer insisted nothing was broken because the site “looked fine” and there were no server errors. Search Console told a different story: Google was crawling 60,000+ URLs but choosing not to index most of them, and the number of indexed product pages had dropped by more than half.
Revenue from organic search was down roughly £38,000 a month against the previous year. The client’s first instinct was to buy links. We asked for two weeks to diagnose the site first, because a site that Google will not index does not benefit from more authority.
Week 1–2: The technical audit
We ran a full crawl with Screaming Frog (JavaScript rendering enabled), compared it against server log files for 30 days, and cross-checked with Search Console’s Pages and Crawl Stats reports. The audit found seven issues, four of which were causing most of the damage.
Issue 1: Faceted navigation generating 50,000+ crawlable URLs
The new theme’s filters (size, colour, brand, price, rating) created a unique URL for every combination, all internally linked and all returning 200 status codes. Google was spending roughly 80% of its crawl budget on filter pages like /tents/?colour=green&size=4-person&brand=x&orderby=price, and most were near-duplicates of the category page. Log files showed Googlebot hitting 41,000 filter URLs in a month versus only 3,200 product pages.
Issue 2: Product pages rendered client-side with blocked JavaScript
The theme loaded product descriptions, prices and reviews through JavaScript after page load. That alone is manageable, but the theme’s JS bundle lived in a directory blocked by robots.txt (a leftover rule from staging). Googlebot saw product pages with a title, an image and almost no text. Thin, near-identical pages were being crawled and dropped.
Issue 3: Canonical tags pointing to the wrong URLs
Variable products (a jacket in six colours) each had their own URL, but the canonical tag on every variation pointed to itself rather than to the parent product. Combined with issue 2, Google saw thousands of near-empty duplicate pages with conflicting canonical signals.
Issue 4: Redirect chains and legacy URLs from the migration
The old site used /product/item-name and the new one used /shop/category/item-name. The migration redirects were in place, but 1,800 of them went through two or three hops (old URL → http → https → trailing slash → final). Around 600 old URLs with backlinks returned 404 because the product slug had changed during the redesign.
Issues 5–7: Performance, sitemaps and internal linking
Mobile Largest Contentful Paint was 5.8 seconds on category pages, driven by unoptimised hero images and four render-blocking scripts. The XML sitemap still listed 2,900 discontinued product URLs that now returned 404. And the redesign had removed the “related products” and breadcrumb modules, so many products were only reachable through paginated category pages, some at depth 7 or deeper.
Weeks 3–12: The fixes, in priority order
We worked with the client’s developer rather than replacing them, and staged every change on a copy of the site before deployment.
Fix 1: Control faceted navigation (week 3)
- Filter combinations with two or more parameters set to
noindexand links to them changed torel="nofollow"with a JavaScript-driven filter UI, so the URLs remained usable for shoppers but stopped consuming crawl budget. - Single-filter pages with real search demand (for example “4 person tents”) were converted into proper static category pages with unique copy, indexable and included in the sitemap. We identified 34 of these from keyword research.
- Sort-order and pagination parameters were canonicalised to the base category URL.
Fix 2: Unblock JavaScript and server-render key content (week 4)
The robots.txt rule blocking the theme’s JS directory was removed the same day it was found. We then had the developer move product titles, descriptions, prices and structured data into the server-rendered HTML so that page content did not depend on JavaScript at all. Reviews remained client-side but were also exposed through Product schema with aggregateRating.
Fix 3: Correct canonicals (week 5)
Colour and size variations were set to canonicalise to the parent product URL. For the 140 variations that had their own search demand (a specific colour that people searched for by name), we kept them self-canonical and gave them unique descriptions.
Fix 4: Flatten redirects and recover lost URLs (weeks 5–6)
All 1,800 chains were rewritten as single-hop 301s directly to the final URL. The 600 dead legacy URLs with backlinks were mapped to their nearest live equivalent, recovering links from 210 referring domains that had been pointing at 404 pages for five months.
Fix 5: Core Web Vitals (weeks 7–9)
Hero and category images were converted to WebP and served with correct dimensions, lazy loading was applied below the fold, three third-party scripts were deferred and one unused live-chat script was removed entirely. LiteSpeed Cache was configured with page caching, CSS minification and critical CSS generation. Mobile LCP dropped from 5.8s to 2.1s and the site passed all three Core Web Vitals in field data by month five.
Fix 6: Sitemaps and internal linking (weeks 10–12)
The XML sitemap was regenerated to exclude 404s, noindexed pages and out-of-stock discontinued items, then split into product, category and content sitemaps for clearer reporting. Breadcrumbs and a “related products” module were restored, and we added a curated “popular in this category” block to every category page to bring deep products within three clicks of the homepage. Maximum crawl depth fell from 9 to 4.
Results
| Metric | Before | Month 6 | Change |
|---|---|---|---|
| Product pages indexed (Search Console) | 4,100 | 9,700 | +137% |
| “Crawled – currently not indexed” URLs | 62,000 | 3,400 | −95% |
| Googlebot requests to filter URLs per month | 41,000 | 2,600 | −94% |
| Googlebot requests to product URLs per month | 3,200 | 19,800 | +519% |
| Mobile LCP (field data, p75) | 5.8s | 2.1s | −64% |
| Organic sessions per month | 46,000 (down from 87,000) | 111,000 | +141% vs low point |
| Organic revenue, year on year | −44% | +61% | — |
| Referring domains recovered from 404 URLs | 0 | 210 | — |
Indexing began to recover within three weeks of the robots.txt and canonical fixes. Traffic passed its pre-drop level in month four, once crawl budget was flowing to product pages and the recovered redirects had been reprocessed. The 34 new static filter category pages alone brought in 14,000 sessions a month by month six, most for keywords the site had never ranked for.
What made the difference
Log files, not assumptions. The crawl budget problem was invisible in a normal site crawl. Only server logs showed where Googlebot was actually spending its time.
Order of operations. Unblocking JavaScript and fixing canonicals came before performance work, because indexing was the bottleneck. A fast page that Google will not index earns nothing.
Turning a problem into an opportunity. The faceted navigation that was wasting crawl budget contained 34 genuine keyword opportunities. Killing every filter page would have thrown those away.
No new links required. The site had enough authority all along. The recovery came entirely from letting Google reach and understand the pages that already existed.
Lessons you can apply
- After any redesign or migration, check Search Console’s Pages report weekly for the first three months. A rising “Crawled – currently not indexed” count is an early warning.
- Test how Googlebot sees your pages with the URL Inspection tool. If the rendered HTML is missing your main content, fix that before anything else.
- Audit robots.txt after every deployment. Staging rules have a habit of going live.
- Faceted navigation needs a deliberate indexing strategy: block the noise, but promote the combinations people actually search for.
- Redirect chains and lost legacy URLs quietly bleed authority. Map them properly, once.
If your traffic dropped after a redesign, migration or theme change, our technical SEO services start with the same crawl, log file and index audit described here. For a self-serve starting point, see our technical SEO audit checklist, or contact us for a free indexing review.