What JavaScript SEO actually is
JavaScript SEO is the set of practices that ensure search engines can crawl, render and index pages built with JavaScript frameworks. React, Vue, Angular, Svelte, Next.js, Nuxt and the rest are all modern ways to build websites. They produce excellent user experiences. They also introduce a layer between your content and search engines that did not exist when sites were plain HTML.
The core problem is timing. Old-fashioned websites send full HTML to the browser on first request. Googlebot fetches that HTML, parses it, and the content is immediately visible to the index. Modern JavaScript websites often send a minimal HTML shell first, then load all the actual content via JavaScript afterwards. The browser experiences this as a slightly slower page load. Googlebot experiences it as a page that initially appears blank, then needs a separate rendering step to see the real content.
Google does perform that rendering step. It runs a recent version of Chrome and executes JavaScript before indexing the page. But the rendering happens on a queue, sometimes hours after the initial fetch, sometimes days. During that window, the page is in the index without its content. And the rendering can fail for all sorts of reasons: JavaScript errors, timeouts, blocked resources, third-party scripts that take too long. When rendering fails, the empty shell is what gets indexed.
For sites where the content is the product (publishers, ecommerce catalogues, knowledge bases), the cost of getting this wrong is enormous. A whole catalogue can sit in Google's index as empty pages while the product team wonders why nothing ranks.
How Google renders JavaScript
Googlebot operates in two phases when crawling a page.
Phase one is the initial fetch. Googlebot requests the URL, the server returns the initial HTML, and Googlebot parses what it sees. Links in this HTML go onto the crawl queue. Meta tags, canonical, robots directives and any content present in this HTML are noted immediately. This phase is fast.
Phase two is rendering. Googlebot's rendering engine (Web Rendering Service, based on a recent Chromium build) executes the JavaScript on the page. CSS loads, scripts run, the DOM updates, and the rendered HTML becomes the version Google indexes. This phase is slower because rendering is resource-heavy, so Google batches it.
Two practical consequences. First, anything present in the initial HTML is indexed almost immediately and confidently. Anything that requires rendering is indexed eventually and with some uncertainty. Second, signals that Google needs early (canonical tag, meta robots noindex, hreflang, structured data) should be in the initial HTML, not injected by JavaScript. If you canonicalise via JavaScript, Google sees the page initially without the canonical, makes initial indexing decisions, and only later corrects them.
The rendering also has limits. Resources blocked in robots.txt cannot be fetched, so JavaScript files blocked there will not execute. Render-blocking resources can time out. Pages that depend on user interaction (click to load more) never trigger that interaction during Googlebot's rendering. Content behind tabs that load on click only appears if the content is in the initial HTML, not lazy-loaded.
The three rendering strategies
Three approaches for delivering JavaScript content to search engines. Each has trade-offs.
Strategy 1. Server-side rendering (SSR)
The server runs the JavaScript framework on every request and returns fully rendered HTML to the browser (and to Googlebot). The user gets a complete page on first paint. Search engines get full HTML on first fetch. SEO performance is essentially identical to a traditional HTML site.
Frameworks that support SSR natively: Next.js (for React), Nuxt (for Vue), SvelteKit (for Svelte), Remix, Astro in SSR mode. All of these can render on the server with one configuration setting.
Trade-off: server cost and complexity rise. Every request runs the framework on the server, so you need infrastructure that can handle that load. For a small marketing site, this is fine. For a high-traffic ecommerce catalogue, the cost adds up.
Strategy 2. Static site generation (SSG)
The framework generates static HTML files at build time, before any user visits. The server just serves the pre-built HTML. Search engines get full HTML on first fetch. The page is fast because it is literally just files being served.
Frameworks: Next.js (with getStaticProps or App Router static rendering), Nuxt (with generate), Astro by default, Gatsby, Hugo, Eleventy. All produce static HTML output.
Trade-off: content cannot change at request time. If product prices update every five minutes, SSG is too inflexible. Hybrid approaches (incremental static regeneration in Next.js, on-demand rebuilds) help but add complexity. For content sites where pages are stable, SSG is hard to beat for both SEO and performance.
Strategy 3. Client-side rendering (CSR) with hydration
The traditional "single-page app" approach. The server returns an empty HTML shell. JavaScript downloads, executes and builds the page in the browser. Without intervention, this is the slowest path for SEO because the initial HTML has no content.
You can make CSR work for SEO by pre-rendering the routes that matter. Tools like Prerender.io or Rendertron generate static snapshots for bot user-agents while serving the regular CSR experience to humans. This used to be called "dynamic rendering" and Google itself recommended it for years. They have since deprecated the recommendation in favour of SSR or SSG, but dynamic rendering still works.
Trade-off: complexity. You are now serving two versions of the page based on user-agent detection, which Google does allow but treats with light suspicion. The maintenance burden is higher than SSR or SSG, and the failure mode (serving wrong content to bots) is hard to detect.
Which one to pick
For most Perth businesses on a JavaScript framework, the answer is SSR if the content changes frequently, SSG if it does not. Both produce full HTML for Googlebot. Both deliver fast user experiences. Both avoid the failure modes of pure CSR.
Pure client-side rendering should be reserved for parts of the page that genuinely do not need to be indexed: dashboards behind login, interactive widgets that customise after page load, user-specific personalisation. The publicly indexable content should always come through SSR or SSG.
How to audit JavaScript rendering
Six checks to confirm Googlebot can see your content.
- View source vs DOM. In Chrome, right-click and choose "View page source" to see the raw HTML. Then open DevTools and inspect the Elements panel to see the post-JavaScript DOM. Any content visible in DOM but missing from View Source is content Googlebot may see late or miss entirely.
- Search Console URL Inspection. Run Inspect URL on the page. Click "Test live URL", then "View tested page". This shows the rendered HTML Google would use. Compare it to the user-visible page. Missing chunks are red flags.
- Disable JavaScript in the browser. Cmd-Shift-P (Mac) or Ctrl-Shift-P (Windows) inside DevTools, type "Disable JavaScript", reload. If the page is blank or missing key content, the page depends on client-side rendering.
- Check canonical, meta robots, title, meta description, hreflang. Confirm each appears in the initial HTML (View Source), not just the DOM. Tags injected via JavaScript are unreliable.
- Screaming Frog JavaScript crawl. Configure Screaming Frog to render JavaScript (Configuration menu, Spider, Rendering tab, set to JavaScript). Compare a JS-rendered crawl to a normal crawl. Significant differences mean important content is rendering-dependent.
- Pick and document the rendering strategy. Based on the findings, decide whether SSR, SSG or hybrid is right for the page templates that matter. Document the decision so the next developer does not unknowingly undo it.
Common mistakes
- Put canonical, meta robots and structured data in the initial HTML, not in JavaScript.
- Use SSR or SSG for any page that needs to rank.
- Test rendering with Search Console URL Inspection after any deploy that touches templates.
- Run Screaming Frog with JavaScript rendering enabled at least once per quarter on JS-heavy sites.
- Allow Googlebot to fetch JavaScript and CSS in robots.txt. Blocking these breaks rendering.
- Ship pure client-side rendering for indexable content. The risk is too high.
- Block CSS or JS in robots.txt. Googlebot needs them to render.
- Hide content behind user interactions (click to load more) and expect Google to find it.
- Use JavaScript to inject canonical or noindex tags after page load. Google sees the page before the injection.
- Lazy-load above-the-fold content. It will not appear in the initial render snapshot.
Tools and checklists
- Search Console URL Inspection. Free. The authoritative answer for what Google sees. The "Tested page" view is the only Google-eye view that exists outside Google's data centres.
- Chrome DevTools. Free. View Source, Elements panel, disable JavaScript, network tab. The core toolkit for rendering diagnostics.
- Screaming Frog with rendering enabled. Paid, worth it for JS-heavy sites. Crawls the rendered DOM, compares against the initial HTML, flags content that only appears post-rendering.
- PageSpeed Insights. Surfaces render-blocking resources and slow JavaScript. The chapter on Core Web Vitals covers the performance side.
- Our free SEO audit tool. Flags rendering and Lighthouse issues alongside the broader audit. Run a free audit.
For sites where JavaScript rendering is a core part of the engagement, the work goes beyond a single chapter. Our website audit service covers rendering audits in depth. Speed optimisation tackles the performance side that overlaps with rendering.
Perth and WA context
Three JavaScript-rendering patterns we see most often on Australian sites.
The marketing-led React rebuild. A Perth professional services or healthcare practice replatformed from WordPress to a React site because the design agency recommended it. Six months later, traffic has dropped 30 percent. The rebuild shipped without server-side rendering, so the bio pages, service pages and case studies are invisible to Googlebot in the way that matters. The fix is moving the build to Next.js with SSR. The Joondalup and Bunbury healthcare audits run into this pattern often.
The headless ecommerce migration. A Fremantle or Cottesloe ecommerce business moved from Shopify or WooCommerce to a headless setup (Shopify backend with a custom React or Vue storefront). Product pages take 5 to 8 seconds to render because the JavaScript bundles are large and the API calls cascade. Googlebot times out before the rendering completes on the slower pages. The fix is SSG for product pages (rebuilt on stock changes) or aggressive caching at the edge.
The JavaScript-driven faceted catalogue. A mining-services or industrial-supply catalogue in Karratha or Port Hedland uses a JavaScript filter system to navigate thousands of products. The filtered URLs work for users (the filters update the page state via JavaScript) but Googlebot never triggers the filters, so the filter combinations stay invisible. The fix is server-rendered filter URLs alongside the JavaScript experience.
One pattern across all three. The site was rebuilt with a modern framework by a team that knew front-end engineering but not SEO. The rendering strategy was the default of the framework, not a deliberate choice. The audit a year later finds the gaps. The fix is conceptually simple but operationally large: switching from CSR to SSR or SSG on a live site is a project, not a tweak.
Related guides
- Back to the Technical SEO pillar for the 12-chapter index.
- The technical SEO audit. Stage seven covers rendering.
- Canonical tags explained. Canonicals injected by JavaScript fail silently.
- Robots.txt and meta robots. Blocking JS or CSS breaks rendering.
- Mobile-first indexing. Rendering happens on the mobile version first.
- Core Web Vitals pillar. The performance side of JavaScript SEO.
- Header tags. H1 has to be in the initial HTML.
- Internal linking strategy. JS-only links can be invisible to Googlebot.
