Back to News & Insights
SEO September 7, 2026 · 5 min read

Our site served every URL the same 3,780 bytes, and Google believed it

Checked with a Googlebot user agent one morning: every single URL on my site returned the same...

Our site served every URL the same 3,780 bytes, and Google believed it

Checked with a Googlebot user agent one morning: every single URL on our site returned the same 3,780-byte shell. Same , zero , zero body text. The homepage, a blog post and a product page were byte-identical before JavaScript ran.

Search Console agreed with the crawler rather than with us. Of 741 URLs, 116 had earned a single impression in 28 days, and a landing page that had been live for five months was still reported as "URL is unknown to Google".

Here is what I actually learned fixing it, including the two things that cost us the most time.

The standard reply to this problem is "Googlebot executes JS now, you are fine." It does. Several of our pages were indexed, so rendering clearly happened.

But rendering is a separate, budgeted queue. A domain with little authority does not get much of that budget. So the practical question is not "can Google render our page", it is "will Google spend its budget rendering this page, today, before it decides what the page is about".

There is a second problem that has nothing to do with rendering: 741 URLs that are byte-identical before render look like duplicates. You are handing a duplicate-content signal to the crawler and hoping the render queue fixes your first impression.

We wrote a post-build script that injects a real into each generated HTML file: title, description, canonical, robots, Open Graph, Twitter.

Head only. The body stayed exactly as the SPA served it. That was deliberate: No hydration flash. No risk of a static copy drifting out of sync with what users see. Nothing that could be read as cloaking, because the static markup is a subset of the rendered markup, not a different page.

Every value is read from the same source the React page reads. Where a title is a literal inside a component, the script extracts it from that component's source rather than having anyone retype it. A number retyped in two places is a number that will disagree with itself eventually.

Our shell had static in index.html. Helmet sets its own on mount. The assumption was that the later one wins.

What actually happens: on its first commit, Helmet removes every tag carrying data-rh and re-inserts its own. Tags without that attribute survive. So the static tag stayed, Helmet's tag was added, and the page went out with two descriptions, with the static one first in the head, which is the one scrapers and crawlers read.

With one sharp edge: only mark tags Helmet will re-add. A data-rh tag that Helmet does not re-insert gets deleted on mount and never comes back. We marked og:image and lost our share image everywhere until we worked out why.

The matching bug in our own script: the replace was written as a regex keyed on attribute order, . The shell writes . It silently matched nothing. Match on a tag containing the key, never on attribute order.

The prerender script takes its URL list from sitemap.xml. Reasonable: one source of truth for what exists.

But npm run build did not include the sitemap generator. It ran vite, then redirects, then the crawl index, then prerender. The sitemap was generated by a separate command somebody had to remember to run.

So we added a new route, built, deployed, and the page was live and completely absent from the prerendered set. No error. No warning. The build exited 0. The route simply was not in the list, so it was never processed, and it went out with the generic shell head.

We burned two builds assuming the code was wrong before checking whether the input was stale.

If a build step consumes a generated artifact, that artifact's generator belongs in the same build command. Otherwise you have an ordering dependency that lives only in somebody's memory, and it fails silently rather than loudly.

Want to discuss this further?

Book a free strategy call with our team to see how these insights apply to your specific business goals.

Book a consultation