Most content appears only after JS: fix it
If most of a page's content shows up only after JavaScript renders, crawlers may miss it. Find these pages and learn how to serve content upfront.
What it means
The page's HTML source is missing content that only appears after JavaScript executes. Googlebot sees the raw HTML first, then runs a second render pass, but the initial HTML it indexes lacks the content you expect to find.
Why it matters
If content is absent from the raw HTML, Googlebot may index a thinner page or skip rendering altogether when it sees noindex in the original source. Client-side analytics also undercount Googlebot, so you may not realize the gap exists. For AI agents and crawlers that read the initial HTML, missing content means missing context, weaker internal-link signals, and reduced chance of being cited in AI-generated answers.
How to fix it
- Check the raw HTML response (not the rendered DOM) and confirm headings, body copy, canonical, and meta tags are present in the initial HTML.
- Switch to SSR or SSG output so content, landmarks, and alt text exist in the initial HTML rather than waiting for JS hydration.
- Ensure routing uses the History API (
window.history.pushState) with real<a href>links; avoidhref="#"oronclick-only navigation. - Test with URL Inspection → Rendered HTML, or run Puppeteer with a tall viewport to verify content appears in the DOM.
Example
<!-- raw HTML the crawler receives: ~40 words, an empty shell -->
<body>
<div id="root"></div>
<script src="/bundle.js"></script>
</body>
<!-- 1,300 words appear only after JS runs --><!-- server-rendered / prerendered: content is in the HTML -->
<body>
<div id="root">
<h1>...</h1><article>...1,300 words of real content...</article>
</div>
<script src="/bundle.js"></script>
</body>Server-render (SSR) or prerender the primary content so it's in the first HTML response. Client-side hydration on top is fine once the content is already there.
When it's not a problem
This is a false alarm if your framework still ships content in the initial HTML (SSR/SSG) and the render pass simply hydrates interactivity. It's also acceptable when lazy-loaded images or below-the-fold content use native loading="lazy" or IntersectionObserver, since Googlebot does not scroll but does accept these approved patterns.
How Crawlinx detects it
We compare the raw HTTP HTML against the JS-rendered DOM. When the rendered word count is more than double the raw count and the absolute gap exceeds 200 words, most of the content is JS-only and the page is flagged.
How common is it?
Not yet observed in our audit sample. We publish this explainer because the check runs on every crawl; once an audited site trips it, this page will break the issue down by platform, gatekeeper, vertical and country.
FAQ
- Doesn't Google render JavaScript?
- Yes, but in a deferred second wave that can lag hours to days, and it's compute-limited. Content only in the JS render is indexed slower and less reliably than server-rendered HTML — and most AI crawlers don't render JS at all.
- How do I fix JS-only content?
- Use server-side rendering or static prerendering (Next.js, Nuxt, Astro, or a prerender service) so the primary text is in the initial HTML. Hydrate the interactive layer afterward.
- Is client-side rendering always bad for SEO?
- Not always, but it's fragile. If rankings matter, put the content in the HTML. Reserve pure client rendering for logged-in app views that don't need to be indexed.
Related guides
Audit your own site — free
157 checks, internal PageRank, render-diff. No signup, results in ~30s.