Losing clicks to competitors? Find out exactly why, and what to fix first.

Show me why
Skip to content

Technical SEO

How to Implement JavaScript SEO Best Practices

Add saadrazaseo.com as a preferred source on Google

Free and no obligation. A real reply from me, not a bot.

Short answer: To implement JavaScript SEO, make sure the content, links and SEO tags that matter are in the HTML your server sends, ideally through server-side rendering, static generation or hydration. Use real <a href> links and clean URLs (no # routes), return proper status codes, never block JavaScript or CSS files, keep bundles small, and confirm what Google sees with the URL Inspection tool in Search Console.

558 KBMedian JavaScript sent to a mobile page in 2024 (613 KB on desktop)HTTP Archive Web Almanac, 2024
44%Of the JavaScript bytes delivered to the median mobile page was unusedHTTP Archive Web Almanac, 2024
NoneOf the major AI crawlers studied (GPTBot, ClaudeBot, PerplexityBot) rendered JavaScriptVercel, 2024

This guide is for developers, SEOs and site owners running React, Vue, Angular, Next.js or any site where JavaScript builds part of the page. You will learn how Google handles JavaScript, which rendering approach to choose, the practical rules that prevent most problems, and a step-by-step way to find out why a JavaScript page is not indexed.

How Google processes JavaScript pages

According to Google’s JavaScript SEO basics, Google processes JavaScript web apps in three phases: crawling, rendering and indexing. Googlebot fetches the URL and reads the HTML response, including links it can find there. The page then waits in a render queue; Google says it may stay there for a few seconds, but it can take longer. A headless, evergreen version of Chromium runs the JavaScript, and Google indexes the rendered result and adds any new links to the crawl queue.

Two consequences matter in practice. First, anything that exists only after rendering is discovered later than content in the initial HTML, and on large sites that delay adds up. Second, signals in the initial HTML can stop the process early: Google says that if it finds a noindex tag, it may skip rendering and JavaScript execution, so removing noindex with JavaScript later does not work. The full pipeline is covered in my guide to rendering in SEO.

Google is not the only reader

Bing, social preview bots and AI crawlers also read your pages. Vercel’s analysis of AI crawler traffic on its network found that none of the major AI crawlers it studied rendered JavaScript; they fetched JavaScript files but did not execute them. If your product descriptions or article text only exist after client-side rendering, assume ChatGPT, Claude and Perplexity cannot read them. My guide to AI crawlers and robots.txt covers how to manage those bots.

Choose a rendering approach

The single decision with the most SEO impact is where the HTML is built. Google’s documentation describes dynamic rendering as a workaround and not a recommended solution, and recommends server-side rendering, static rendering or hydration instead.

ApproachWhere HTML is builtSEO riskBest for
Client-side rendering (CSR)In the browser, after JavaScript runsHigh: content and links depend on rendering; invisible to most AI crawlersLogged-in apps, dashboards, pages that should not rank
Server-side rendering (SSR)On the server for each requestLow, if the server output is completeContent that changes often: listings, prices, news
Static site generation (SSG)At build timeLowestBlogs, documentation, marketing pages
Incremental or on-demand regenerationAt build time, refreshed on a schedule or triggerLowLarge catalogues where full rebuilds are slow
Dynamic rendering (separate HTML for bots)A prerender service for crawlers onlyMedium: extra complexity, risk of bots and users seeing different contentShort-term fix for legacy apps that cannot be changed quickly

Frameworks make this easier than it used to be: Next.js and Nuxt support SSR and static generation per route, and Angular and SvelteKit have their own server rendering. Many headless CMS sites already use one of these, but I still find templates where the main content is fetched in the browser after the server sends an empty shell.

Rather have an expert do this for you?

Hand it over and get back to running your business.

Hand it over to me

JavaScript SEO best practices

Links and URLs

  • Use real links. Google says it can only discover links that are <a> elements with an href attribute. A <span onclick> or a button that changes the route is not a link to Googlebot.
  • Use the History API, not fragments. example.com/#/shoes is one URL to Google. Single-page apps should route with the History API so each view has its own path.
  • Put navigation in the initial HTML. Menus and category links rendered only on click or hover are discovered late or not at all. Good internal linking starts with links Google can see.
  • Paginate with links. Infinite scroll and “load more” buttons need paginated URLs behind them. See how to handle pagination.

Titles, canonicals and robots tags

  • Send them in the server HTML. JavaScript can change them, but if the initial HTML and the rendered page disagree you are relying on Google to pick the right one.
  • Never inject noindex and hope to remove it. Google may skip rendering a page that starts with noindex.
  • Keep canonicals consistent. A wrong canonical in the template, corrected by JavaScript later, is a common cause of pages being treated as duplicates. My guide to canonical tags explains the rules.

Status codes and errors

A single-page app often returns 200 for every URL, including ones that do not exist, which creates soft 404s. Google’s guidance gives two options: redirect with JavaScript to a URL where the server returns 404, or add a robots meta tag with noindex to error views using JavaScript. Server-rendered frameworks can usually return a real 404 status, which is better.

Resources and performance

  • Do not block JavaScript or CSS in robots.txt. If Google cannot fetch them, it cannot render the page as users see it. Check your robots.txt file for old Disallow rules on /js/ or /assets/.
  • Ship less JavaScript. Split bundles by route, defer non-critical scripts and remove unused libraries. Heavy JavaScript hurts Interaction to Next Paint and Largest Contentful Paint; see optimising Core Web Vitals for mobile.
  • Version file names. Use content hashes in bundle names (app.3f9a1c.js) so Google does not render a page with an outdated cached script.
  • Lazy-load images properly. Use the native loading=”lazy” attribute below the fold, never on the main image, and make sure the image URL is in the HTML.

Structured data

JSON-LD added by JavaScript can work, but server-rendered structured data is more reliable and is visible to other crawlers too. Test the rendered output with the Rich Results Test, and keep it consistent with what users see. My schema generator produces valid JSON-LD you can drop into the server template.

How to check what Google sees

  1. Compare view-source with the rendered DOM. View source shows what the server sent; the browser’s inspect panel shows the page after JavaScript. Main content, links, title and canonical should be in both.
  2. Use URL Inspection in Search Console. Run a live test and open “View tested page” to see the rendered HTML, a screenshot, and any resources that could not load.
  3. Crawl with JavaScript rendering on and off. Screaming Frog and Sitebulb can compare raw and rendered HTML across the whole site, which shows template-level problems quickly.
  4. Search for a unique sentence. Put a sentence that only appears after rendering in quotes with site:yourdomain.com. If it does not appear weeks after indexing, Google probably has not processed it.
  5. Check the Page indexing report. Look for “Crawled, currently not indexed”, “Soft 404” and “Duplicate, Google chose different canonical” on JavaScript templates. See my guide to the Page indexing report.

Why is my JavaScript page not indexed?

Does URL Inspection say the URL is on Google or can be indexed (no noindex, not blocked by robots.txt)?

In the live test, does the rendered HTML contain your main content and title?

Is the page reachable through normal <a href> links from other indexed pages, or listed in your sitemap?

Does the Google-selected canonical match the URL you inspected?

Result: a directive or block is stopping indexing. Remove noindex from the server HTML (not with JavaScript), and lift any robots.txt Disallow on the page or on the JavaScript and CSS files it needs. Then request indexing.

Result: rendering problem. Check the “More info” panel for blocked resources and JavaScript errors. Content fetched from an API that fails or times out for Googlebot is a common cause. The lasting fix is to render the content on the server.

Result: discovery problem. Google may not know the URL exists. Replace click handlers with real links, remove # routes, add the URL to your XML sitemap and link to it from relevant indexed pages.

Result: duplicate or canonical problem. The page may look identical to another URL before rendering, or the template sends a wrong canonical. Put unique content and the correct canonical in the server HTML.

Result: probably a quality or priority issue, not JavaScript. Google can see and reach the page but has chosen not to index it yet. Improve the content, strengthen internal links and give it time.

Mistakes I find most often on JavaScript sites

  • A “Loading…” shell as the server response on templates that should rank, such as product and blog pages.
  • Every route returning 200, so deleted products and mistyped URLs become soft 404s.
  • The same title and canonical on every page in the server HTML, corrected only after JavaScript runs.
  • Filters and tabs that change content without changing the URL, so useful filtered views can never rank, or that create thousands of URLs that should not. See faceted navigation SEO.
  • Testing only in Chrome on a fast laptop. Many visitors in Pakistan browse on mid-range Android phones over mobile data, where a large bundle takes far longer to parse and run. Test on a real mid-range phone or with CPU throttling in DevTools before calling a page fast.

Frequently asked questions

Can Google crawl and index JavaScript?

Yes. Google renders pages with an evergreen version of Chromium and indexes the rendered result. It does not mean every JavaScript page is indexed reliably: rendering adds a step, links must be real anchor elements, and errors or blocked resources can leave content unseen.

Is client-side rendering bad for SEO?

Not always, but it carries the most risk. Content and links appear only after rendering, other search engines and AI crawlers may not see them, and performance on slow devices suffers. For pages that need to rank, server-side rendering or static generation is safer.

Should I still use dynamic rendering?

Only as a temporary fix. Google calls it a workaround, not a recommended solution, and suggests server-side rendering, static rendering or hydration instead.

How do I test JavaScript SEO for free?

Use URL Inspection in Search Console for individual pages, compare view-source with the inspected DOM in your browser, run the Rich Results Test for structured data, and use a crawler’s free tier with JavaScript rendering enabled for a sample of URLs.

Do JavaScript redirects work for SEO?

Google can follow them once it renders the page, but server-side 301 or 308 redirects are clearer and work for every crawler. Use JavaScript redirects only when you cannot redirect on the server.

Does JavaScript affect Core Web Vitals?

Yes. Large bundles delay rendering, which hurts Largest Contentful Paint, and long tasks on the main thread hurt Interaction to Next Paint. Splitting code and deferring non-critical scripts usually helps both.

Sources

  • Google Search Central, “Understand JavaScript SEO basics” (last updated 2026).
  • Google Search Central, “Dynamic rendering as a workaround” (last updated 2025).
  • HTTP Archive, “Web Almanac 2024: JavaScript” (2024).
  • Vercel, “The rise of the AI crawler” (December 2024).

If your JavaScript site is not getting indexed the way it should, my technical SEO services include a rendering audit of every key template, or you can ask me a question first.

Rather have an expert do this for you?

Tell me about your website and goals, and I will reply with a free first review.

Your details are only used to reply to your request. No spam.

Grow my trafficCall