Your Content Is in the HTML or It Is Not

If a page needs JavaScript to show its content, most AI retrievers see an empty frame. Here is how to check what your server actually sends, and what to do when the answer is nothing.

If your content only appears after JavaScript runs, most AI retrievers never see it. They read the raw HTML response, and if that response is a mount element and a script bundle, that is the entire page as far as they are concerned. This is the single most expensive finding QuickRankAI reports, and it is the one that cannot be fixed by writing anything.

How to check it in ten seconds

Open a terminal and ask the server directly:

curl -s https://example.com/your-page/ | wc -c

Then look at what actually came back:

curl -s https://example.com/your-page/ | grep -o '<p>' | wc -l

If the document is 40 KB and contains two paragraph tags, you have your answer. The 40 KB is script.

The browser view-source trick works too, and it catches people out for a good reason: Chrome's devtools Elements panel shows the DOM after JavaScript has run, which is not what the server sent. View-source shows the actual response. Those two views disagreeing is exactly the problem.

What the retriever sees

A page like this returns something close to:

<div id="root"></div>
<script src="/static/js/main.a4f19c.js"></script>

There is nothing wrong with that document. It is valid, it loads fast, and in a browser it produces a complete page. It just contains no information about what the page is for.

Google will often render it eventually, on a second pass, when it feels like it. Most AI crawlers will not. They fetch, parse, and move on, because rendering every page in a browser engine is expensive and they are fetching a great many pages.

Why this is structural and not a quick fix

Every other finding on a client-rendered page is downstream of this one. No H1, because the H1 is in a component. No structured data, because it is injected by a head manager after mount. No internal links, because the navigation is a React component. Twelve findings, one cause.

That is why QuickRankAI reports the rendering finding as structural and does not bury you in the twelve consequences. Fixing the cause clears most of them at once.

The three repairs, in order of effort

Static generation

Build the pages at deploy time and serve real HTML files. This is the best outcome and the least ongoing work. If your content changes on a schedule rather than per request, this is almost certainly what you want. Next.js, Nuxt, Astro, Gatsby, Hugo, Eleventy, and every static generator in between do this.

Server-side rendering

Render the component tree on the server for each request and send the resulting HTML. The browser then takes over. Slightly more infrastructure, necessary when content is genuinely per-request. Every major framework supports it and has for years.

Pre-rendering for crawlers only

A service detects crawler requests and serves them a rendered snapshot. It works, and it is the option to reach for when the first two are genuinely blocked by something. It also means maintaining a second delivery route that only machines see, which is a thing that quietly breaks and nobody notices for a month.

What is not a repair

Adding a head manager so the title and meta description are set correctly. Those tags will now be right, on a document that still contains no content. It is a genuine improvement to a page nobody can read.

Also not a repair: adding a noscript block with a summary. It is better than nothing and it is not what anybody is retrieving.

How to confirm the repair landed

Re-run the curl check above. The word count in the response should now roughly match what you see in the browser. Then re-run the inspection, which reports the number of words it actually read, so you can compare directly rather than trusting that the deploy did what you expected.

Run this against your own page. The inspection reports whether the repair described here is actually needed, and what else is sitting next to it.

Run a Quick Inspection