Eleven thousand four hundred URLs returned 200 with near-identical titles, the retired catalogue still resolved through a four-hop redirect, and Googlebot spent most of its crawl on faceted junk while the money templates sat in Discovered - currently not indexed.

That was the site. Not a content gap. Not a thin-blog problem. Crawl debt had blocked indexation of the templates that actually needed to rank, and every new article we published sat on top of the same mess.

This is the technical SEO case study we walk technical marketers through when Search Console looks busy and organic still will not move.

What the crawl log actually showed

The log was the honest document. Googlebot hit parameter URLs, leftover pagination, and old host variants far more often than it hit the current category and product templates.

Sitemap XML listed URLs that 404ed. The live nav pointed at a different host than the canonical tag. Internal links still used the pre-migration path.

URL Inspection on a money template returned a rendered DOM with the H1 and the main copy. The raw HTML snapshot was a shell. That split is how JS rendering hides a page from the first pass even when the app looks fine in Chrome.

We pulled 14 days of log lines, Search Console coverage, and a full site crawl on the same date window. The three sources disagreed with each other. That disagreement is the debt.

When organic sessions stall after a template or host change, the first pass is the same sequence Google documents for Google debugging search traffic drops: pin the date, isolate the URL set, then fetch and render before anyone rewrites copy.

Indexation that never reached the money templates

Coverage looked “healthy” if you only read the total indexed count. The indexed set was the wrong set.

Faceted collection URLs, sort orders, and session IDs had crept into the index. The real category templates were either canonicalised away or stuck in Crawled - currently not indexed.

Google does not owe a site a recrawl of the clean URL if the dirty URL still 200s, still links internally, and still appears in the sitemap. Indexation follows the signals we leave in the HTML, the links, and the log.

We mapped every money template to one of four states: indexed and canonical to self, indexed but canonical to a weaker URL, discovered not indexed, or crawled not indexed. Only the first state is useful. The other three are debt.

That map is the start of any serious technical SEO case study. Without it, content work is guesswork on top of a blocked crawl.

JS rendering that left Google with a shell

The front end was a client-rendered app. First paint in a normal browser looked complete. The HTML Google fetched on the first hop did not contain the H1, the product grid, or the internal links in the footer.

We compared raw HTML, the rendered DOM, and the screenshot from URL Inspection on the same URL. Three different documents. That is the JS rendering failure.

Prerender and SSR were both on the table. The constraint was the release window, not the theory. We shipped server-rendered shells for the templates that needed indexation, left the app behaviour in place for users, and stopped asking Googlebot to execute a full client bundle before it could see a link.

If the rendered DOM and the raw HTML do not share the same H1, the same main copy, and the same internal links, rankings will not recover from copy tweaks. The crawler never received a stable document.

Duplicate clusters that burned crawl budget

Near-duplicate titles were the visible symptom. The real cluster was worse.

HTTP and HTTPS, www and non-www, trailing slash and no slash, uppercase path segments, and print view URLs all 200ed. Canonical tags pointed at a mix of those variants. Some pages canonicalised to a URL that then redirected.

Each cluster spent crawl budget on copies Google had no reason to keep. Duplicates do not just dilute signals. They delay the recrawl of the URL we actually want in the index.

We collapsed each cluster to one host, one protocol, one path shape, and one canonical that resolved 200 to itself. Then we removed the losers from the sitemap and from internal links. Canonicals alone do not fix a site that still links to four variants from the header.

Parameter handling came next. Color, sort, and page parameters that did not change the primary content were noindexed and unlinked from crawl paths. Facets that did change content got a clean, indexable URL with a self-canonical - not a query string bolted onto the category.

Redirect chains nobody had finished

The migration was two years old. The redirect map was not.

Old product paths hopped through a campaign URL, then a trailing-slash variant, then the current PDP. Four hops. Some chains ended on a 404. Some ended on a canonical that pointed back at hop two.

Redirects that hop cost crawl budget and drop link equity on the floor. A chain is unfinished work, not a clever fallback.

We flattened every chain we could prove from logs and the crawl to a single 301 from the oldest public URL to the current canonical. We dropped hops that only existed because a plugin had been left on. We stopped 302ing URLs that had been “temporary” since the last rebrand.

Where a redirect pointed at a URL that then noindexed, we treated that as a dead end and either indexed the destination or removed the source from internal links. A 301 into a noindex is a quiet way to throw a URL away.

Robots, parameters and canonicals that fought each other

robots.txt disallowed a path the sitemap still listed. The CMS added a noindex on paginated collections while rel=next pointed at those same URLs. Parameter URLs were allowed in robots, linked in filters, and canonicalised to the clean category - three different instructions.

Google will pick one. It will not reconcile a fight we left in the templates.

We wrote one rule per URL class. Indexable templates: 200, self-canonical, in the sitemap, linked from nav or breadcrumbs, raw HTML that matches the render. Non-indexable filters: noindex or blocked from crawl, not in the sitemap, not linked as crawl paths. Retired URLs: single 301 to the replacement, then removed from the sitemap.

hreflang was a side fight on this property. EN and PH URLs pointed at each other with the wrong host, so the return tags never validated. We fixed return tags only after the host and protocol were stable. hreflang on top of duplicate hosts is more debt.

How we sequenced the debt

We did not start with content. We did not start with a new blog calendar. We sequenced crawl, render, then indexation, then internal links.

First, stop the bleed: block or noindex the parameter junk, flatten redirect chains, pick one host. Second, make the money templates render a complete document in raw HTML. Third, put only those templates in the sitemap and request a recrawl on the template pattern, not on thousands of leftover URLs.

That order is the core of our technical SEO services Philippines work on properties like this: crawl, render, index, then only then copy. Swapping the order is how teams spend a quarter writing articles Google never fetches as a clean document.

We tracked three numbers weekly, not rankings. Share of Googlebot hits on money templates. Count of URLs in Discovered - currently not indexed on those templates. Match rate between raw HTML H1 and rendered H1.

When those three move, indexation can move. When they do not, more content is more debt.

What changed once the crawl was clean

Crawl waste on parameter and variant URLs fell. Googlebot’s share of hits on category and product templates rose in the same log window.

Coverage shifted. The Crawled - currently not indexed pile on money templates started to clear after the render and canonical fixes, not after a title rewrite. Sitemap errors dropped once 404s and redirected URLs were removed from the feed.

Impressions on the template queries that had been stuck began to appear against the canonical URLs instead of against the faceted copies. That is the signal we wanted. It is not a ranking promise. It is indexation landing on the document we actually maintain.

Internal links were the last mechanical pass. Breadcrumbs, related modules, and the footer were pointing at leftover paths. We pointed them at the live canonicals so the next crawl reinforced the same graph we had cleaned in robots and redirects.

None of this required a new content model. It required the site to stop arguing with itself.

How to decide the next useful cut

If Search Console shows a large indexed count and the money templates are not in that count, stop commissioning articles. Open the log. Open URL Inspection. Compare raw HTML to the rendered DOM on one category and one product URL.

If those two documents disagree, the next cut is JS rendering, not a brief. If they agree and the URL is still Crawled - currently not indexed, the next cut is duplicates, canonicals, and sitemap hygiene. If the URL 301s through more than one hop, flatten the chain before you touch copy.

If robots.txt, the sitemap, and the on-page canonical name three different URLs for the same template, pick one and make the other two stop talking. That decision is the work. Tools only show the fight.

A technical marketer recognising crawl debt does not need another dashboard. You need a ordered list of URL classes and a rule for each class. Index, noindex, or redirect. One status. One canonical. One sitemap state.

Write that list before anyone opens a content spreadsheet. The list is the debt register.

Request a scoped audit if this is the shape

If the failure looks like this - log waste on junk URLs, money templates unindexed, JS rendering that leaves a shell, duplicate clusters, unfinished redirects - the useful next step is not a retainer pitch and not a blog plan.

It is a scoped pass against Search Console, the crawl, and the render, limited to the templates that have to rank. That is what our SEO audit services are for: evidence, a debt register, and a sequence, not a slide deck of generic recommendations.

Bring the property, the date the traffic or indexation stalled, and access to Search Console and logs if you have them. We will tell you whether the block is crawl debt or something else. If it is crawl debt, the next useful thing is the first cut on that register, in order.

If the site already renders a complete document, already canonicalises to one host, and already keeps Googlebot on the money templates, this case does not apply. Go write the pages. If it does not, do not add more URLs to a crawl that is already lost.