HomeAboutServices PortfolioSkillsToolsBlog ClientsContact

JavaScript SEO: how to make JS websites crawlable and indexable

Key takeaways

  • Google crawls, renders and indexes JavaScript pages. Test the rendered HTML to confirm that important content and links appear.
  • Server rendering or static generation can make important content available in the initial HTML and improve reliability for crawlers that do not run JavaScript.
  • Common JavaScript SEO problems include empty initial HTML, JavaScript-dependent links, missing meta tags, and soft 404 errors that look like real pages to Googlebot.
  • Frameworks such as Next.js, Nuxt and Astro offer rendering options; the output and configuration matter more than the framework name.
  • Use Search Console's URL Inspection tool to inspect the rendered HTML, screenshot and resource errors, then compare them with your server response.
Computer screen showing JavaScript code, representing the intersection of web development and SEO

Google can render JavaScript, but a page can still have a rendering or indexing problem. A browser session may show content that depends on a blocked resource, a user action or an API response unavailable to Googlebot. The useful question is what appears in Google's rendered HTML for a specific URL.

I work across SEO and front-end development, including React and Next.js sites. This guide shows how to compare the server response with the rendered page and decide whether a rendering change is needed.

This guide explains exactly how Google handles JavaScript, why client-side rendering creates SEO problems, which rendering strategies solve those problems, and how to diagnose and fix JavaScript SEO issues on your own site.

For a framework-specific implementation, see the Next.js App Router metadata and sitemap tutorial.

How Google handles JavaScript

Google describes three stages: crawling, rendering and indexing. A URL may be queued for rendering after the first fetch. See Google's JavaScript SEO basics.

Phase 1: Crawl

Googlebot requests the URL and receives the server's HTML response. It can discover links in ordinary <a href> elements immediately. If the response contains only a JavaScript app shell, Google needs to render the page to see the content generated in the browser.

Phase 2: Render

Google places the page in a rendering queue and eventually processes it using a headless Chromium browser (the same engine that powers Chrome). This step executes your JavaScript, builds the DOM, and attempts to produce the final rendered page. The rendered content is then used for indexing.

The gap between crawl and render

Crawling and rendering do not have to happen at the same moment. Google says the rendering queue may take seconds or longer. Check these possible dependencies:

  • Content that only exists after JavaScript execution is invisible to Google's initial crawl
  • Links that are only generated by JavaScript may not be discovered during the crawl phase, slowing the discovery of linked pages
  • Meta tags injected by JavaScript (like React Helmet) are not present in the initial HTML response
  • If the render fails for any reason (timeout, error, third-party script blocking), the content may never be indexed

The rendering problem: why JavaScript breaks SEO

If important content exists only after JavaScript runs, verify that it appears in Google's rendered HTML. Server rendering or pre-rendering can simplify this and also helps crawlers that do not execute JavaScript.

Why rendering fails

  • Timeouts: Google allocates limited time and resources to render each page. Complex JavaScript that takes too long to execute may be cut off before completion.
  • Third-party scripts: If your page depends on an external API or CDN that is slow or temporarily down during Google's render attempt, the content will be incomplete.
  • User interaction requirements: Content that only loads after a click may not appear in the rendered HTML. For lazy loading, use a method Google can trigger and verify the result with URL Inspection.
  • JavaScript errors: A single uncaught error can prevent the rest of your JavaScript from executing, leaving the page partially rendered.
  • Resource blocking: If your robots.txt blocks CSS or JavaScript files that are needed for rendering, Google cannot execute them.

Rendering strategies compared

A rendering strategy determines when and where the page's HTML is built. It does not establish the site's ranking or guarantee that a URL will be indexed. Compare the actual response, rendered content, metadata, links and route behavior before changing the application architecture.

What each strategy needs you to verify
StrategyTypical responseSEO checksOperational trade-off
Client renderingAn app shell that loads content in the browser.Accessible resources, rendered content, links and direct-route responses.Rendering depends on the scripts and data requests succeeding.
Server renderingHTML produced for the request.Correct status, content, metadata and indexability for each route.Server or data failures can affect response time and availability.
Static generationHTML produced during a build.Published content, freshness, canonical URLs and removed-route behavior.Updates depend on the publishing or regeneration process.
Regeneration or cachingPreviously built content refreshed under an application policy.Stale content, cache behavior, metadata and route changes.The refresh policy must match how quickly the content changes.

Client-side rendering (CSR)

Public client-rendered pages can be indexed by Google when rendering succeeds. Audit what the response initially contains and what the scripts later add. Authentication, blocked resources, failed data requests and inconsistent routes can change the result. For an authenticated dashboard, the intended policy can instead be to keep it out of search.

Server-side rendering (SSR)

Server rendering can include useful content in the initial HTML. Check the response from the production route and the state after hydration. A server-rendered page can still have the wrong canonical, a noindex directive, missing links or weak content.

Static site generation (SSG)

Static HTML can make content available without executing page scripts. Test the deployed route, including its metadata and response for removed or unknown URLs. A build that omitted a page or retained an outdated URL remains an issue even when every included page is static.

Incremental static regeneration (ISR)

Some frameworks can refresh previously generated content without a complete rebuild. Confirm the current framework's behavior, cache policy and deployment configuration. Test that a content or product-status change reaches the public route within the agreed publishing process.

JavaScript code on a dark screen, the type of client-side rendering that needs special SEO handling

Common JavaScript SEO problems and fixes

Empty initial HTML

Problem: your server returns an HTML file that contains only a <div id="root"> and a script tag. All content, including titles and headings, is generated by JavaScript in the browser.

Fix: compare the server response with Google’s rendered HTML and inspect loading errors. If important content or metadata is missing, correct the underlying dependency or consider server or static rendering for those routes. Supplying content in the initial response reduces rendering dependencies; migrating the entire application is not always necessary.

JavaScript-dependent links

Problem: navigation links use JavaScript event handlers (onClick) instead of standard <a href> tags. Googlebot discovers new pages by following links in the HTML. If your links are not real anchor tags, those pages may never be discovered.

Fix: always use standard <a href="/path"> tags for navigation. You can still attach JavaScript event handlers for enhanced behavior, but the underlying HTML must be a real link. For more on link structure, see my internal linking strategy guide.

Hash-based routing

Problem: your SPA uses hash routing (e.g., example.com/#/about). Google treats everything after the hash as a fragment identifier, not a separate URL. All your "pages" resolve to the same URL in Google's eyes.

Fix: use the History API for routing (pushState-based routing). All modern frameworks support this: React Router, Vue Router, and Angular Router all use it by default. Your URLs should be clean paths like /about/, not hash fragments.

Soft 404 errors

Problem: when a page does not exist, your server returns a 200 status code (because it always returns the same HTML shell), and JavaScript displays a "Page not found" message in the browser. Google may classify this as a soft 404 and exclude it from Search; a 200 status does not guarantee indexing.

Fix: return an appropriate HTTP status where possible. For client-routed SPAs, Google documents alternatives: redirect missing content to a URL that returns 404, or add noindex to the error state through JavaScript. Test valid routes too; do not rely on JavaScript to remove an initial noindex directive from a page you want indexed.

Lazy-loaded content below the fold

Problem: content behind an interaction or an infinite-scroll implementation without crawlable paginated URLs may be missed.

Fix: use Google's lazy-loading guidance, provide crawlable URLs for paginated content, and confirm the important text and images appear in rendered HTML. Native loading="lazy" can be appropriate for below-the-fold images.

JavaScript frameworks and SEO

Not all JavaScript frameworks create the same SEO challenges. Here is how the most popular ones compare:

Next.js (React)

Supports server and static rendering, metadata APIs and streaming. It can be a good fit for React projects, provided each public URL returns useful content, metadata and links. See the Next.js implementation guide.

Nuxt (Vue)

Nuxt supports server, static and hybrid rendering. Choose the mode for each public route and verify its actual content, metadata and links. Rendering capability alone does not guarantee indexing or rankings.

Astro

A static-first framework that can serve content as HTML while loading JavaScript only for interactive parts. It is one option for content-heavy sites; test the actual output, speed and maintenance needs before choosing a framework.

Gatsby (React)

Gatsby can generate React pages as static HTML. Evaluate build time, content freshness and route behavior for your project; generated HTML still needs useful content, metadata and appropriate status handling.

Angular server and hybrid rendering

Angular’s current server and hybrid rendering documentation uses @angular/ssr and route-specific rendering modes. Configure the public routes deliberately and test their document responses; no framework makes every route SEO-ready automatically.

Plain React, Vue, or Angular (CSR only)

Client-rendered public pages need closer testing: verify that Google can render their content, follow their links and interpret their status codes. If those checks fail or other crawlers matter, consider server or static rendering.

How your JavaScript application handles links and routing directly impacts whether Google can discover and crawl your pages.

Rules for SEO-safe navigation

  • Use real anchor tags: every navigational link must be an <a href="/path"> element. Google generally discovers links through anchor elements with an href. A click handler alone does not provide the same crawlable link.
  • Use clean URL paths: /products/blue-widget/ is crawlable and keyword-rich. /#/products?id=4829 is not.
  • Use a sitemap where useful: list intended canonical URLs to help discovery. A sitemap does not replace crawlable links or guarantee crawling and indexing.
  • Include breadcrumbs: breadcrumb navigation provides additional internal links and helps Google understand your site hierarchy. Add BreadcrumbList schema for extra visibility.

Meta tags and structured data

Meta tags and structured data are among the most commonly broken elements in JavaScript applications.

The problem with client-side meta tags

In a default React SPA, every page shares the same <title> and <meta description> from the index.html file. Libraries like React Helmet update these tags in the browser after JavaScript executes, but Google may see the original generic tags during the crawl phase.

The fix

Prefer page-specific metadata in the server response where practical. Google can process some JavaScript-injected metadata after rendering, but a server response is easier to verify. With Next.js, use its Metadata API; with Nuxt, use useHead. Check these elements on each public URL:

  • <title> tag with page-specific title
  • <meta name="description"> with page-specific description
  • <link rel="canonical"> with the correct canonical URL
  • Open Graph and Twitter Card meta tags for social sharing; these are not Google ranking tags
  • JSON-LD structured data for Article, Product, FAQ, or other relevant types

My technical SEO guide covers all the essential meta tags and their correct implementation.

JavaScript and Core Web Vitals

Heavy JavaScript can contribute to poor Core Web Vitals, but images, CSS, fonts and server latency can also matter. Measure the affected metric and bottleneck before choosing a fix. See the Web Vitals overview.

Largest Contentful Paint (LCP)

If the largest visible element depends on a large JavaScript bundle, its rendering can be delayed. Measure the actual Largest Contentful Paint with field or lab data before assuming JavaScript is the cause.

Fix: identify the LCP element and its discovery, download and rendering delays. Make its resource discoverable promptly and prioritize it where appropriate. Server-rendered content may reduce a dependency, but it does not resolve every LCP bottleneck. Follow the LCP diagnostic workflow.

Interaction to Next Paint (INP)

Long JavaScript tasks can occupy the main thread and delay an interaction’s response. Bundle size affects download and processing, but it is not itself an INP measurement. Inspect execution, event handlers and rendering work around slow interactions.

Fix: code-split your JavaScript so each page only loads the code it needs. Defer non-critical scripts. Use web workers for heavy computation. Keep the main thread clear.

Cumulative Layout Shift (CLS)

Late insertion can cause layout shifts when it moves existing visible content without reserved space. Insertion into an appropriately sized placeholder may avoid that movement. Ads, fonts and images can also cause shifts; inspect the actual shifted elements.

Fix: reserve appropriate space for images and dynamic content, and investigate insertions above existing content. Server rendering does not prevent every shift. Use the CLS diagnostic guidance to identify the cause.

If React interactions feel slow after the page loads, follow the slow-click and typing diagnostic to separate input delay, processing and presentation before changing rendering priorities.

A JavaScript SEO route audit you can reproduce

Test a URL by loading it directly and by following a link inside the application. Those paths can produce different document responses and metadata. Use this checklist alongside Google's JavaScript SEO guidance, then verify the important URLs in Search Console.

Route states to include in a public-page audit
Route stateInspectDecision
Existing product or articleDocument status, rendered main content, title, canonical and href links.Confirm the real public page is available and indexable as intended.
Unknown URLDocument status and displayed missing-page message.Return an appropriate missing-page status; avoid a generic 200 app shell for every path.
Permanently removed itemReplacement, status and internal links.Redirect only to a relevant replacement, or use the agreed removal status.
Filtered categoryUnique purpose, canonical and link discovery.Choose an indexing policy for the filter; do not canonicalize useful distinct pages automatically.
Data request failsDocument response separately from the API response.An API's 503 does not by itself make the document a 503.

Illustrative failure: a product API returns 404, but the application serves a 200 document showing “Product not found.” Record both responses. Changing a page title cannot fix that document-status mismatch. Test the agreed fix through a fresh direct visit, an internal link and a reload before marking the issue complete.

The React SPA SEO audit tutorial includes a local route lab, downloadable example rows and acceptance checks. Its lab is a framework-neutral browser demonstration, not a Googlebot test or proof that a production React site is indexed. For the implementation handoff, use the React and Next.js technical SEO hiring checklist.

How to test JavaScript SEO

A page can look correct in your own browser while a crawler sees different content. Test the published URL rather than relying only on a local browser session.

Google Search Console URL Inspection

Enter a URL and run “Test Live URL.” In the tested-page details, inspect:

  • HTML: Google's rendered HTML, which can include content added by JavaScript
  • Screenshot tab: shows what Google saw after rendering JavaScript
  • More info tab: shows any resource loading errors or JavaScript errors

Compare the rendered HTML with the raw server response you fetch separately. Look for the main text, canonical URL and crawlable links. If they are missing from Google's rendered HTML, investigate blocked resources, script errors and API dependencies.

View page source vs. Inspect element

A quick local test: right-click your page and select "View Page Source" (not "Inspect Element"). View Page Source shows the raw HTML your server sends, the same thing Googlebot sees during the crawl phase. Inspect Element shows the DOM after JavaScript has executed. If your content appears in Inspect but not in View Page Source, Google may not see it during the initial crawl.

Disable JavaScript in your browser

Open Chrome DevTools, go to Settings, and disable JavaScript. Reload your page. What you see is approximately what Googlebot sees during the crawl phase (before rendering). A blank page shows that the content depends on JavaScript; it does not by itself prove Google cannot render or index it. Compare rendered HTML and Search Console evidence before diagnosing an indexing failure.

Lighthouse and PageSpeed Insights

Run a Lighthouse audit to check Core Web Vitals scores and identify JavaScript-related performance issues. Look specifically at "Reduce unused JavaScript" and "Minimize main-thread work" recommendations.

Put these checks into a repeatable five-route React SPA SEO audit, with a downloadable worksheet and a local practice lab.

If a Next.js title arrives after the initial UI, use the streaming metadata comparison to distinguish streamed tags from genuinely missing or wrong metadata.

Frequently asked questions

Can Google render JavaScript?

Yes. Google renders JavaScript with Chromium and uses the rendered HTML for indexing. Check the rendered HTML in Search Console URL Inspection. Server or static rendering can make important content available in the first response and helps crawlers that do not run JavaScript.

Is React bad for SEO?

React does not prevent a page from being indexed. Google can render JavaScript, but the actual route must supply accessible content, links, metadata and appropriate response behavior. Test the implementation before choosing client, server or static rendering; switching frameworks by itself does not guarantee rankings.

Do I need server-side rendering for SEO?

Not always. Test whether Google can render the public route’s content, links and metadata. Server or static rendering can make content available in the initial response and reduce JavaScript dependencies, including for crawlers that do not render it. Choose based on observed failures, content freshness and operational needs; no rendering mode guarantees indexing or rankings.

How do I test if Google can see my JavaScript content?

Run a live URL Inspection test and inspect the rendered HTML, screenshot and loading errors. Separately fetch the raw server response and compare its main content, links and metadata with the rendered version. Check indexing status for the inspected URL; a site: search is not a reliable indexing audit.

Need help making your JavaScript website visible to search engines? I combine front-end development with technical SEO to build sites that are fast, interactive, and fully indexable. Whether you need to migrate from CSR to SSR, fix rendering issues, or build a new site with SEO baked in from the start, I can help. Get in touch to discuss your project.

B
Bikesh Tamang
SEO Specialist & front-end developer in Kathmandu, Nepal, helping businesses rank higher and turn traffic into customers. More about me →