A traditional web page arrives from the server as finished HTML. Many modern sites don’t work that way. Built with frameworks like React, Vue or Angular, they send a nearly empty HTML shell plus JavaScript, and the browser assembles the page. JavaScript SEO is about making sure search engines and other crawlers see the finished page, not the empty shell.
How Google handles JavaScript
Google processes pages in stages: it crawls the HTML, then queues the page for rendering in an up-to-date version of Chrome, then indexes what it rendered. Rendering usually happens quickly now, but it’s an extra step that can fail. Scripts can time out, be blocked by robots.txt, or depend on actions Googlebot doesn’t take, like scrolling, clicking or accepting a cookie banner.
AI crawlers are less forgiving
Tests of AI crawlers, including those used by ChatGPT, Claude and Perplexity, have found that most don’t run JavaScript. They read the raw HTML. If your service descriptions only exist after JavaScript runs, those assistants see a blank page and can’t quote or cite you.
Why it matters
Coastline Plumbing hires a developer who rebuilds the site as a single-page app. It looks great. Three months later, organic calls are down. The raw HTML for every page is identical: a title, a <div id="root"></div> and a script tag. Google renders some pages slowly, internal links built as click handlers aren’t followed, and AI assistants have nothing to read.
Fixes, from strongest to weakest
- Server-side rendering (SSR) or static generation. The server sends complete HTML, and JavaScript adds interactivity afterwards. Next.js, Nuxt, Astro and similar frameworks support this.
- Make sure key content and links are in the initial HTML, even if the rest of the page is client-rendered.
- Use real links.
<!-- Crawlers can follow this -->
<a href="/water-heater-repair/">Water heater repair</a>
<!-- Crawlers can't follow this -->
<span onclick="go('/water-heater-repair/')">Water heater repair</span>
- Don’t block JavaScript or CSS files in robots.txt.
- Put titles, meta descriptions, canonicals and structured data in the server HTML rather than injecting them later.
Common mistakes
- Changing content with URL fragments (
/#/services), which Google treats as the same page. - Returning a 200 status for every route, including ones that should be 404s.
- Lazy-loading text that only appears on scroll.
How to check
Compare View Source (raw HTML) with the Elements panel in DevTools (rendered HTML). If your main text appears only in the second, you depend on rendering. Search Console’s URL Inspection shows the HTML Google rendered. RankThat’s Site Audit flags content that depends on JavaScript to appear and links search engines can’t follow.