Home / Blog / JavaScript SEO: How to Make JS Sites Crawlable and Indexable

JavaScript SEO: How to Make JS Sites Crawlable and Indexable

JavaScript SEO is the work of making sure search engines can find, render and index content that JavaScript builds or changes. Google can run JavaScript, but it does it in a separate rendering step after crawling, and only real <a href> links, correct status codes…

JavaScript SEO: How to Make JS Sites Crawlable and Indexable

JavaScript SEO is the work of making sure search engines can find, render and index content that JavaScript builds or changes. Google can run JavaScript, but it does it in a separate rendering step after crawling, and only real <a href> links, correct status codes and content that appears without user clicks are reliably picked up. Most other crawlers, including most AI crawlers, don’t run JavaScript at all.

So the practical question isn’t “can Google read JavaScript?” It can. The question is how much of your page depends on it, and whether that’s a risk you need to take.

I’ll walk through how Google handles JS, which rendering method fits which site, and how I test what Google actually sees.

How Does Google Process JavaScript Pages?

Google’s JavaScript SEO basics guide describes three phases: crawling, rendering and indexing. Googlebot first fetches the raw HTML and reads the links in it. Then the page waits in a render queue.

Google says a page “may stay on this queue for a few seconds, but it can take longer than that.” When resources allow, a headless Chromium renders the page and runs the JavaScript. Google then parses the rendered HTML for more links and uses it for indexing.

Here’s what that means in plain terms. Anything in your raw HTML gets seen at crawl time. Anything that only exists after scripts run gets seen later, if rendering succeeds, and only by crawlers that render at all.

That same guide adds a line I quote to developers: server-side or pre-rendering “is still a great idea because it makes your website faster for users and crawlers, and not all bots can run JavaScript.”

The Condition Map

Four variables change what you should do:

  1. How the page is rendered. Server-rendered or static HTML carries little risk. Pure client-side rendering carries the most.
  2. Where the important content lives. Body copy, prices and links in the raw HTML are safe. The same content fetched by scripts after load is not.
  3. Which crawlers you care about. Google renders. Many other bots, including most AI crawlers, read only the raw HTML.
  4. How the site handles routing and errors. Single-page apps often break links, URLs and status codes without anyone noticing.

Which Rendering Method Should You Use?

The web.dev article Rendering on the Web defines the options clearly. Server-side rendering builds HTML on the server for each request. Static rendering builds HTML files at build time. Client-side rendering builds the page in the browser with JavaScript, and hydration runs client scripts on top of server-rendered HTML to make it interactive.

MethodWhat the crawler gets firstSEO riskBest fit
Static generation (SSG)Full HTMLLowestBlogs, docs, marketing pages
Server-side rendering (SSR)Full HTMLLowStores, listings, pages with changing data
SSR or SSG with hydrationFull HTML, then JS adds interactivityLow, watch content mismatchesMost modern framework sites
Prerendering at buildSnapshot HTMLLow to medium, can go staleSmall apps with few routes
Client-side rendering (CSR)Mostly an empty shellHighestLogged-in dashboards, tools behind login

My rule is short. If a page should rank, its main content and links belong in the HTML the server sends. Client-side rendering is fine for parts of the product nobody searches for, like an account dashboard.

The web.dev authors also suggest considering server-side or static rendering over a full rehydration approach. That’s a performance argument, but it lines up neatly with the SEO one.

Branch 1: Your Site Renders in the Browser

If your marketing pages, product pages or blog are built as a client-side app, then Google has to render every URL before it sees any content. Other crawlers may see nothing but a script tag and an empty <div id="root">.

That doesn’t guarantee failure. Plenty of client-rendered sites get indexed fine, because Google renders them without trouble. But the margin for error is thin, and one blocked API call or one script error can blank out the content for Googlebot while the page looks perfect in your browser.

Here’s the path I recommend:

  • Move indexable routes to SSR or static generation in the framework you already use. This is usually a configuration and data-fetching change, not a rewrite.
  • Leave app-only screens client-rendered. Settings pages and logged-in tools don’t need to rank.
  • If a migration isn’t possible this quarter, prerender your key public routes at build time as a stopgap.

If you’re on a SaaS stack where marketing pages and the app share one codebase, split them. My SaaS landing page SEO post covers how those page types should be planned.

Branch 2: Your Site Is Server-Rendered or Static

If your pages arrive as full HTML, the big risk is gone. What’s left are the quieter bugs that come from JavaScript changing the page after load.

The one I find most often is a mismatch. The server sends one title, canonical or robots tag, and client code swaps it for another. Google’s guide notes that you can inject a canonical with JavaScript, though it doesn’t recommend it, and that the injected value should match the original HTML.

The second is content that only appears after a click. Tabs and accordions are fine when the text sits in the HTML and is just hidden. They’re a problem when the text is fetched from an API only after someone clicks, because Googlebot doesn’t click.

Google’s JavaScript SEO Rules, in My Order of Importance

These come from Google’s basics guide and its JavaScript troubleshooting page. I’ve ordered them by how much damage each one can do when it’s wrong.

Use real links. Google says it can only discover links that are <a> elements with an href attribute. Click handlers on a <div> or a <span> don’t count.

<!-- Google can follow this -->
<a href="/pricing/">Pricing</a>

<!-- Google can't discover this as a link -->
<span onclick="goTo('/pricing/')">Pricing</span>

Don’t rely on JavaScript to remove noindex. Google’s exact wording: “When Google encounters the noindex tag, it may skip rendering and JavaScript execution, which means using JavaScript to change or remove the robots meta tag from noindex may not work as expected.” If you want the page indexed, keep noindex out of the original HTML.

Return honest status codes. A single-page app often answers every URL with 200, including pages that don’t exist. That creates soft 404s. Google suggests either redirecting to a URL that returns a real 404, or adding a noindex robots tag to the error view. My soft 404 guide covers the Search Console side.

// Error view in a client-rendered app: tell Google not to index it
const meta = document.createElement('meta');
meta.name = 'robots';
meta.content = 'noindex';
document.head.appendChild(meta);

Use the History API, not fragments. Routes like /#/products aren’t reliably resolved. Google points out that the old AJAX crawling scheme has been deprecated since 2015.

Don’t depend on storage or permissions. Google’s troubleshooting page says local storage, session storage and cookies are cleared between page loads, and Googlebot declines permission prompts such as location.

Fingerprint your JS files. The rendering service may ignore caching headers, so file names like main.2bb85551.js stop Google from using stale code.

Is Dynamic Rendering Still a Good Idea?

No, not for new builds. Google’s dynamic rendering page now says it “was a workaround and not a long-term solution for problems with JavaScript-generated content in search engines.” It recommends server-side rendering, static rendering or hydration instead.

Dynamic rendering means serving prerendered HTML to bots and the normal JS app to users. Google says it generally isn’t treated as cloaking when both versions show similar content. Still, you’re now maintaining two outputs, and they drift. If you have it running today and it works, plan the move to SSR rather than ripping it out in a panic.

How Do You Test What Google Actually Sees?

When I review a JavaScript site, I use three checks, in this order.

  1. View the raw source. Right-click, View page source, and search for a sentence from your main content. If it isn’t there, that text depends on rendering.
  2. Run the URL Inspection live test in Search Console. Open “View tested page” to see the rendered HTML, a screenshot and the JavaScript console messages. My guide on how to index pages in Google Search Console shows where these buttons are.
  3. Check Crawl stats if many pages misbehave. Google’s troubleshooting guide points to it for spotting resource fetch problems.

If the rendered HTML in the live test contains your content and links, Google can see them. If it shows an empty shell or a console error, fix that before anything else. For the wider list of checks, my technical SEO checklist covers crawl, render and index in order.

Common JavaScript SEO Problems by Framework

I keep this generic on purpose. Framework defaults change between versions, so check the docs for the version you run.

  • React built as a plain single-page app renders in the browser by default. Public pages need SSR or static output through a framework or a prerender step.
  • Next.js can render on the server or at build time, but a component that fetches its main content in the browser after load brings back the client-side risk for that section.
  • Vue built as a plain single-page app has the same risk as React. Nuxt renders on the server by default, which helps unless someone turns it off for the whole site.
  • Any framework can ship a router that uses click handlers instead of <a href>, or a catch-all route that returns 200 for every bad URL.
  • Head tags managed by JavaScript sometimes leave two canonicals or the wrong robots tag. Inspect the rendered HTML, not just your code.

What About AI Crawlers?

This is where JavaScript SEO is getting more important, not less. Google renders. Most AI crawlers, from what the public evidence shows, fetch only the raw HTML. A client-rendered page that ranks fine on Google can still look blank to ChatGPT’s or Claude’s crawlers.

I go through the evidence, the exceptions and the robots.txt side in technical SEO for AI search. The short version for this post: server-rendered HTML solves Google and AI crawlers at the same time.

Decision Matrix

If your pageAnd it should rankThen
Is client-renderedYesMove to SSR or SSG, prerender as a stopgap
Is client-renderedNo (app screens)Leave it, add noindex if it’s public
Is server-renderedYesCheck JS doesn’t change title, canonical or robots
Uses dynamic renderingYesKeep it for now, plan the SSR move
Loads text on clickYesPut the text in the HTML, hide it with CSS
Returns 200 for missing URLsAnyReturn a real 404 or add noindex

When Should You Bring In a Developer?

You can run the source check and the live test yourself. Changing how a site renders is developer work, and so is anything touching routing, server config or the build pipeline.

If you want someone to find the rendering gaps first, our technical SEO service covers rendering, crawling and indexing together. You can also start with a free SEO audit.

Frequently Asked Questions

Does Google Index JavaScript Content?

Yes. Google renders pages with a headless Chromium after crawling and indexes the rendered HTML. Rendering can be delayed by the render queue, and it fails if scripts or resources are blocked, so server-rendered content is safer.

Is Client-Side Rendering Bad for SEO?

Not automatically, but it carries the most risk. Google has to render every URL, and many other crawlers won’t render at all. For pages that should rank, I recommend server-side or static rendering.

Is Next.js Good for SEO?

It can be, because it supports server and static rendering. The result still depends on how you build each page. Content fetched only in the browser carries the same risks as any client-side app.

Can I Add Noindex With JavaScript?

You can add it, and Google’s own soft 404 advice uses that method. What doesn’t work reliably is removing noindex with JavaScript, because Google may skip rendering once it sees noindex in the original HTML.

Last updated: October 2026 by Mizanur Rahman

Put this guide to work.

Want help applying it? Start with a free audit of your site. We’ll show you what to fix first.

Get a free SEO audit