Modern sites ship a lot of JavaScript, and JavaScript and SEO have a complicated relationship. Google can render JS — but rendering is expensive, delayed, and full of failure modes that a server-rendered page never hits. If your content only exists after JavaScript runs, you're taking on risk you may not need to.
How Google renders JS
Googlebot processes a JavaScript page in two waves. First it crawls the raw HTML. Then, when rendering resources are available, it runs your JavaScript in a headless Chromium and indexes the result. That second wave can lag the first by anywhere from minutes to days. So anything that only appears after JS executes is indexed later — and only if rendering succeeds. Other search engines and many AI crawlers render JS far less reliably than Google, or not at all.
CSR, SSR and SSG
The rendering strategy you pick decides how much you're relying on that second wave:
- CSR (client-side rendering) — the server sends near-empty HTML and the browser builds everything with JS. Worst case for SEO: your content doesn't exist until rendering runs.
- SSR (server-side rendering) — the server sends fully-formed HTML on each request. Google sees your content in the first wave. Best for SEO-critical, dynamic pages.
- SSG (static site generation) — HTML is pre-built at deploy time. Fastest and most reliable for content that doesn't change per request.
The rule of thumb: if a page needs to rank, its content should be in the HTML response — via SSR or SSG — not assembled later on the client.
Where JS SEO breaks
The common failure modes: content that only loads on interaction (click-to-load, infinite scroll) that Googlebot never triggers; links implemented as onclick handlers or buttons instead of real <a href> tags, so crawlers can't follow them; blocking your JS bundles in robots.txt so Google can't render at all; and slow client rendering that times out. Use real anchor tags, real URLs, and make sure critical content doesn't hide behind an interaction.
Meta tags and JS
Injecting SEO-critical tags with JavaScript is risky. A title tag, canonical, or meta robots directive that only appears after JS runs may be missed or applied late. Worse, a client-side redirect or a JS-injected noindex can behave unpredictably. Put anything that controls indexing in the server-rendered HTML.
React, Next.js and friends
Frameworks like Next.js, Nuxt, Remix and Astro exist largely to solve this — they give you SSR or SSG so your React/Vue components arrive as real HTML. If you're on a framework, use its server-rendering or static-generation mode for public, indexable pages, and reserve pure client rendering for authenticated app views that don't need to rank. A single-page app with client-only routing is the setup most likely to bite you.
Testing what Google sees
The key question is always: what's in the HTML before JavaScript runs versus after? Use Search Console's URL Inspection "view rendered HTML" and the Rich Results Test to see Google's rendered version. For a fast day-to-day check, SEO Inspector reads the current DOM's meta tags, headings, canonical and links — so you can compare what's present against the raw source and spot content or tags that only exist after hydration. When both agree, you know Google isn't guessing.