JavaScript SEO Services

JavaScript SEO Consultant for React, Next.js and Headless Sites

I find out what Google actually receives from your JavaScript front end, then give your developers a fix list they can ship and test, template by template.

20+ yearsIn search since 2005, with 50+ brands
200M+Monthly visits, 11 countries, as OLX Group Global Head of SEO
20 portalsAt BOLD: 5 global plus 15 multilingual, multi-regional sites
6 platformsReal projects: custom JavaScript, Shopify, WordPress, custom CMS, Webflow, Squarespace
Book a JavaScript SEO Audit

Quick answer

JavaScript SEO makes sure search engines get your content, links and metadata from a site built on React, Next.js, Vue, Nuxt, Angular or a headless commerce front end. Google crawls the raw HTML first and renders JavaScript later, in a queue, so anything that only exists after rendering is at risk, and most AI crawlers never render at all. As a JavaScript SEO consultant, I test what Google receives on each of your templates and hand your developers a prioritised, testable fix plan. Audits start at $1,100.

Your developers picked React or Next.js for good reasons. Fast interfaces and shared components, mostly. None of that tells Google what’s on the page, though. Search engines judge the HTML they receive and the HTML they manage to render, and on a lot of JavaScript sites those two don’t match.

I’m Ram Kr Shukla. I’ve worked in search since 2005, with 50+ brands. I’ve done SEO on custom JavaScript builds (React and Next-style front ends) as well as Shopify, WordPress, custom CMS, Webflow and Squarespace sites. My last in-house role was Global Head of SEO at OLX Group: 11 countries, 200M+ monthly visits, classifieds and autos. Below: what I check on a JavaScript site, what usually breaks, and what an audit costs. And if your problem goes wider than rendering, my technical SEO service covers the full stack.

Signs Your JavaScript Site Has an SEO Problem

You’ll probably recognise at least one of these. They’re the symptoms that bring JavaScript sites to me.

1
Pages look complete, but view-source is nearly empty

The product or article text shows in the browser, then it’s missing when you press Ctrl+U. Google can still render it later. But anything that reads only HTML gets the empty shell.

2
Indexing reports balloon after a rebuild

You moved to Next.js, Nuxt or a headless storefront, and the Page indexing report started filling with Discovered, currently not indexed and Crawled, currently not indexed URLs while impressions slid.

3
Soft 404s and error screens in the index

A single page app answers 200 for every route, including deleted products, expired listings and typos. Google flags soft 404s, or worse, indexes the error screen.

4
Menus that work for people and pass nothing to Google

Category links built as buttons or click handlers. Shoppers get through fine. Crawlers find no href to follow, so deep pages look orphaned.

5
Prices in search trail the prices on the page

Product schema is injected after load, so price and availability in Google lag what the shopper sees on the page.

6
Core Web Vitals pass on desktop and fail INP on mobile

Hydration ties up the main thread, so taps on filters, menus and add to cart feel slow on mid-range phones.

Need the whole app rebuilt? Then you need a development team as well. I work alongside yours, or alongside your agency, from diagnosis to verified release.

How Google Renders JavaScript, and Why Timing Matters

Google’s own documentation splits JavaScript processing into three phases: crawling, rendering and indexing (JavaScript SEO basics). First Googlebot fetches the URL and reads the raw HTML. Any page that returns a 200 goes into a render queue, where a headless Chromium runs your JavaScript. Only then does Google index the rendered HTML.

The queue is the part teams underestimate. Google says a page may stay there for a few seconds, but it can take longer. Multiply that across tens of thousands of product or listing URLs and longer adds up. The same document has a few rules that catch people out, too. If your raw HTML carries a noindex, Google may skip rendering, so removing it with JavaScript later won’t work. Links only count when they’re real <a> elements with an href.

How Google processes a JavaScript pageGoogle crawls the raw HTML, queues the page for rendering in headless Chromium, then indexes the rendered HTML. Server-rendered pages carry their content from the first fetch. Client-side pages wait for the render queue. Most AI crawlers skip rendering entirely. Where JavaScript content waits 1. Crawl Fetches the raw HTML response 2. Render queue Headless Chromium runs your scripts 3. Index Uses the rendered HTML Google: a page may sit in the queue a few seconds, or longer. Server-rendered (SSR, SSG, ISR) Content, links and metadata arrive in the first response. Rendering only confirms what was already there. Client-side only (CSR) The first response is a shell. Text and links wait for step 2, and a raw noindex can stop rendering altogether. Most AI crawlers Fetch the HTML and stop. There’s no step 2, so a CSR shell is all they ever read. RamKrShukla.com
Google’s three phases for JavaScript pages, and what each kind of page carries into them. Sources: Google Search Central’s JavaScript SEO basics and Vercel’s AI crawler research.

There’s a second audience now. Vercel’s crawler research found that none of the major AI crawlers it measured (OpenAI, Anthropic, Meta, ByteDance, Perplexity) render JavaScript. Gemini and Applebot were the exceptions. So if your copy only shows up after hydration, ChatGPT and Perplexity are reading an empty shell. That matters for AI search visibility just as much as it does for Google.

Rendering Choices: SSR, SSG, ISR, CSR and the One Google Calls a Workaround

In my experience, most JavaScript SEO problems come down to which rendering mode each route uses. Here’s how they compare for search:

ModeWhat Google gets firstGood forWatch for
Server-side rendering (SSR)Full HTML on every requestPages that change per request: search results, stock-sensitive product pagesServer cost and response time. Hydration still costs INP.
Static generation (SSG)Full HTML built ahead of timeMarketing pages, docs, blogsBuild times grow with page count. Content is stale between builds.
Incremental static regeneration (ISR)Static HTML, rebuilt on a timer or on demandLarge catalogues that update through the dayRevalidation windows. Google can pick up a stale price.
Client-side rendering (CSR)A shell and script tagsLogged-in screens that shouldn’t rank anywayEverything that must rank waits for the render queue. AI crawlers see nothing.
Dynamic rendering or a prerender serviceA snapshot served only to botsA short bridge while SSR shipsGoogle calls it a workaround. Two versions of every page to keep in sync.

On dynamic rendering, Google is blunt: it was a workaround and not a long-term solution, and the recommendation is server-side rendering, static rendering or hydration instead. If you’re paying for a prerender service today, treat it as scaffolding with an end date.

For most sites the right answer is a mix by route: SSR or ISR for anything that should rank, client-side behind the login. Framework defaults help. In the Next.js App Router, components are Server Components by default, and Nuxt server-renders unless someone turns it off. The trouble usually comes later: data fetched inside useEffect, a component loaded with ssr: false, or a single-page Vue or Angular app with no server rendering at all. Each one quietly pushes content back into the browser.

What I Check on a JavaScript Site

Eight areas, checked per template. Most of the damage I find on JavaScript sites sits in one of them.

1
Links without a crawlable href

Google can only discover links that are <a> elements with an href. Its link guidelines name the formats it can’t reliably parse: onclick handlers, <span href>, <a routerLink> and javascript: URLs. I’ve written up how to find links Google can’t follow.

2
Client-side routing, status codes and soft 404s

A single page app usually serves one HTML file with a 200 for every path. Google’s docs give two fixes for error routes: a JavaScript redirect to a URL that returns a real 404, or a robots noindex added on the error view. With SSR, return the real 404 or 410 from the server. Routes should use the History API, since Google can’t reliably resolve #/ fragment URLs.

3
Metadata set by JavaScript

Titles and descriptions set by JavaScript do get picked up after rendering. Canonicals are where I push back. Google doesn’t recommend setting them with JavaScript, and if you must, the value has to match the raw HTML. One Next.js bug I see a lot: a title set once in a shared layout and never overridden, so every product page ships the same title.

4
Lazy-loaded content and infinite scroll

Google’s lazy-loading guidance is plain: Google Search doesn’t interact with your page. Content that loads on scroll or click stays invisible unless it loads when it enters the viewport. Infinite scroll needs a unique URL per chunk, such as ?page=12, linked in sequence. More in my guide to crawlable product grids.

5
Structured data injected with JavaScript

Google reads JSON-LD that’s in the rendered DOM, Tag Manager included. For products, though, it adds a warning: dynamically generated markup can make Shopping crawls less frequent and less reliable. So price and availability belong in the server HTML. More on that in structured data at scale.

6
Hydration and INP

INP has replaced First Input Delay as the responsiveness Core Web Vital, and good is 200 milliseconds or less. Until hydration finishes, taps queue up behind script. The usual causes are big client bundles, third-party tags and hydration mismatches (where React discards the server HTML and re-renders on the client). The fixes live in the templates, same as in my Core Web Vitals post.

7
Blocked or failing resources

A robots.txt rule on /_next/, /api/ or a CDN subdomain, or an API call that times out for Googlebot, and the render comes back as an empty template. URL Inspection lists failed page resources and console errors, so this one’s quick to prove.

8
Headless commerce specifics

A Next.js or Hydrogen storefront over Shopify, BigCommerce or commercetools adds its own traps. The old storefront stays live and indexable, filters sit in client state with no URL, and canonicals get built from the request URL with every parameter attached. My faceted navigation rules apply here too. The e-commerce SEO audit covers the catalogue side.

How I Test What Google Actually Sees

Four tests. None of them needs access to your code, and you can run the first two yourself.

The JavaScript SEO test kit:

  • Raw HTML against rendered DOM. I pull the raw response (curl, or view-source) and the rendered DOM (Chrome DevTools, or a headless browser for a sample per template), then compare word count, internal hrefs, title, canonical, robots and JSON-LD. Every difference goes into a table by template.
  • URL Inspection live test. In Search Console, View tested page shows the HTML Google rendered, a screenshot, and under More info, the page resources that failed and the JavaScript console messages.
  • Two Screaming Frog crawls. One text-only, one with JavaScript rendering on. The JavaScript tab then flags pages with JavaScript-only content and links, noindex only in the original HTML, titles changed by JavaScript, canonical mismatches and blocked resources.
  • Status codes on fake URLs. I request a product or listing that doesn’t exist. A 200 with Not found text on screen is a soft 404 waiting to happen.

Want to try the first one yourself? The steps are in your content exists but Google can’t see it, and the product page version is in client-side rendering and product indexability. I won’t repeat them here.

How a JavaScript SEO Audit Runs, Step by Step

1
Inventory the templates and rendering modes

I list every page template (home, category, product or listing, article, search, location) and record how each one renders: SSR, SSG, ISR or client-side. Search Console and analytics access come first, and staging or repo read access if you can share it.

2
Test what Google receives on each template

For a sample of URLs per template I diff the raw HTML against the rendered DOM and run URL Inspection live tests. Then I crawl the site twice in Screaming Frog, once text-only and once with JavaScript rendering on.

3
Read the Search Console evidence

Page indexing reasons, crawl stats and Core Web Vitals get grouped by template. That way soft 404s on expired listings, or INP failures on filter pages, point at one fix instead of thousands of URLs.

4
Write a fix plan your developers can test

Every issue gets the template it lives on, the evidence, the change, an acceptance test the developer can run, and a priority based on the revenue or leads that template carries.

5
Verify after release

When fixes ship, I re-run the diff and URL Inspection on the changed templates and watch indexing and impressions in Search Console, so you know the fix reached production.

The acceptance tests matter more than they look. Take a rule like every menu link opens in a new tab and shows up as an href in view-source. A developer can check that in a pull request, and that’s what stops the problem coming back with the next refactor.

Rebuilding on a JavaScript Framework?

Moving from WordPress or a Shopify theme to Next.js or a headless storefront is a migration. So you get all the migration risk stacked on top of the rendering risk. URLs change, templates drop metadata, and staging often ends up indexed.

Even simple moves catch people out. On a Squarespace to WordPress migration I ran for a US fitness studio, all 16 URLs were mirrored 1:1. Staging QA still found no meta descriptions, no analytics, no LocalBusiness schema and a staging site open to indexing, all before cutover. A framework rebuild has far more moving parts than that. My process for platform moves is on the e-commerce migration SEO page. If you’ve already launched and lost rankings, start with recovering rankings after a redesign.

Where This Experience Comes From

At OLX Group I was Global Head of SEO across 11 countries in Asia, Europe and LATAM, with 200M+ monthly visits across classifieds and autos. At that size you can’t fix pages one at a time. Rendering, internal links and status codes are template decisions, and that’s how I audit a JavaScript site now: by template, with the fix written once.

Before that, at BOLD, I ran SEO for 5 global career portals and 15 multilingual, multi-regional portals across Europe, the UK and New Zealand. At OYO Rooms it was India organic plus a multilingual international setup for the US, UK, Indonesia, China and Japan. Locale routing and hreflang at that scale are the same class of problem a Next.js internationalisation setup creates.

Today I work hands-on with businesses on custom JavaScript builds (React and Next-style front ends) as well as the other platforms above. I don’t name those clients. What I can show is published work:

Published case studies and notes:

What a JavaScript SEO Audit Costs

Audits start at $1,100. That covers the test kit above across your main templates, the Search Console evidence and a written fix plan your developers can work from. Retainers and implementation support are quoted after the audit, once we both know how long the fix list is.

What moves the scope:

1
Templates and rendering modes

A site with four templates all on SSR is a smaller job than one mixing SSR, ISR and a client-side app across fifteen.

2
Size and locales

More URLs and more languages mean more sampling, and hreflang and locale routing to check on every template.

3
Access

Search Console, analytics and staging access shorten the evidence work. Repo read access lets me point at the exact component.

4
Implementation support

Developer calls, ticket writing, pull request review and release verification are scoped separately, if you want them.

5
Core Web Vitals depth

Profiling INP template by template on real devices takes longer than reading field data.

Not ready for an audit? My free SEO tools cover some of the basics, and the posts linked above walk through the first checks.

JavaScript SEO Questions, Answered

What does a JavaScript SEO consultant do?

A JavaScript SEO consultant checks whether search engines receive your content, links, metadata and structured data from a site built on a framework such as React, Next.js, Vue, Nuxt or Angular. In practice that means comparing raw and rendered HTML on every template, testing routing and status codes, and turning each problem into a fix your developers can build and test.

Can Google index JavaScript websites?

Yes. Google runs JavaScript in a headless Chromium during a separate rendering phase after crawling. The catch is timing and reliability: pages wait in a render queue, links only count when they’re real a elements with an href, and a noindex in the raw HTML can stop rendering altogether. Content that’s already in the server HTML avoids all three.

Is Next.js good for SEO?

It can be very good, because server rendering and static generation are built in. The problems come from how it’s used: data fetched in the browser instead of on the server, components loaded with server rendering switched off, one title set in a shared layout and never overridden, or client bundles heavy enough to hurt INP.

Is React bad for SEO?

React isn’t the problem, client-only rendering is. A React app that ships a near-empty HTML shell leaves Google waiting on the render queue and gives most AI crawlers nothing to read. Rendered on the server, through Next.js or a similar setup, a React site can rank like any other.

Should we use dynamic rendering or a prerendering service?

Only as a short bridge. Google describes dynamic rendering as a workaround and not a long-term solution, and recommends server-side rendering, static rendering or hydration instead. A prerender service also leaves you with two versions of every page to keep in sync.

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

Open view-source and search for a sentence you can see on the page. If it’s missing, it’s rendered client-side. Then run a live test in Search Console’s URL Inspection tool and read the rendered HTML and screenshot. For the whole site, crawl it in Screaming Frog with JavaScript rendering on and compare it with a text-only crawl.

Do ChatGPT and other AI tools see JavaScript content?

Mostly not. Vercel’s published crawler research found that the major AI crawlers from OpenAI, Anthropic, Meta, ByteDance and Perplexity don’t render JavaScript, while Gemini and Applebot do. Content in the server HTML is the safest way to be readable by all of them.

How much does a JavaScript SEO audit cost?

Audits start at $1,100. The final scope depends on how many templates and rendering modes you have, site size and number of locales, the access you can give, and whether you want help through implementation. Retainers and implementation support are quoted after the audit.

Not sure what Google sees on your site?

Send me the URL and the framework you’re on. I’ll look at a few key templates and tell you straight whether there’s a rendering problem worth an audit.

Book a JavaScript SEO AuditSee Technical SEO Services
RS

Written by Ram Kr Shukla

SEO and growth consultant with 20+ years in SEO and growth and 50+ brands. Google Analytics and Google Ads certified. Former Global Head of SEO at OLX Group, across 11 countries and 200M+ monthly visits. Works with companies as a consultant or Fractional Chief Digital Officer.