# JavaScript SEO: What Is JavaScript Rendering?

> What JavaScript rendering is, how Google does it in a second phase, what AI bots that don't run it see and how to check it in your store.

URL: https://clione.ai/glossary/javascript-rendering/
Lang: en

A store page rarely arrives finished. The server sends some HTML and some JavaScript files, and the browser runs those scripts to fill in what is missing: the variant selector, the review stars, sometimes the whole [product page](/glossary/product-page/). That step is JavaScript rendering, and the search "JavaScript SEO" exists because **a search engine is not your browser**: it decides whether to run your scripts, when and within what limits. For a store the useful question is concrete: which data on your [product page](/glossary/product-page/) depends on that step, and who misses out on it.

## How it works

web.dev's rendering guide, by Addy Osmani and Jason Miller, supplies the vocabulary. Client-side rendering is rendering an application in the browser, using JavaScript to modify the DOM. Hydration is running scripts on the client to add state and interactivity to HTML that already arrived rendered from the server. Prerendering is running the application at build time to save its initial state as static HTML.[^webdev-rendering] In all three there is JavaScript running; **what changes is whether the essential content depends on that execution** or came already written.

Google processes pages with JavaScript in three phases: crawling, rendering and [indexing](/glossary/indexing/). Before requesting a URL, [Googlebot](/glossary/googlebot/) checks in [robots.txt](/glossary/robots-txt/) that it may crawl it. Then it puts the page in a render queue, where it **can wait a few seconds or quite a bit longer**. When its resources allow, a headless Chromium renders the page and runs the JavaScript, and Google uses that rendered HTML to extract links and to index the page.[^google-js-seo] That is why a fact that only appears after rendering reaches the index later than one that travels in the initial HTML, and only if nothing breaks along the way.

In December 2025 Google added three clarifications to its documentation that affect any store.[^google-updates]

- **Status codes.** If the page responds with a code other than 200, for example a 404, **rendering may be skipped**.[^google-js-seo]
- **`noindex`.** If Google finds a `noindex` in the original HTML, it may skip rendering and running the JavaScript, so removing it later with a script is no guarantee.[^google-js-seo]
- **The [canonical](/glossary/canonical-url/) URL.** It is best declared in the HTML; if JavaScript touches it, it has to leave it with the same value as the original HTML, never swap it for another.[^google-js-seo]

Google's renderer does not behave like a person browsing either. It declines permission requests, such as camera or location; clears local storage, session storage and cookies between one load and the next; caches aggressively and may ignore cache headers; and does not support connections such as WebSockets or WebRTC.[^google-js-fix] It only discovers links that are `<a>` elements with an `href` attribute, and for client-side navigation it asks you to use the History API instead of `#` fragments.[^google-js-seo]

## The bots that do not render

Google says so in its own guide: [server-side rendering](/glossary/server-side-rendering/) or prerendering is still a great idea, because it makes the web faster and because **not all bots can run JavaScript**.[^google-js-seo] Vercel put numbers on that sentence. In an analysis of its network traffic with the consultancy MERJ, published on December 17, 2024, none of the big AI [crawlers](/glossary/web-crawler/) rendered JavaScript, among them those of OpenAI, Anthropic, Meta, ByteDance and [Perplexity](/glossary/perplexity/). They did download the files: JavaScript files were 11.50% of the requests from ChatGPT's [crawler](/glossary/web-crawler/) and 23.84% of Claude's, but they treated them as text, without running them. The exceptions were [Gemini](/glossary/gemini/), which uses Google's infrastructure, and AppleBot.[^vercel-ai-crawlers]

Its recommendation was to render on the server the main content (articles, product information, documentation), the metadata (titles, descriptions, categories) and the navigation structure, and to leave client-side rendering for the incidental, like a visit counter or a chat.[^vercel-ai-crawlers] Read the figure with its date: it is one company's measurement of its own network, from late 2024, and crawlers change.

## In a store

**Fictitious example.** A Shopify store sells a table lamp. Its theme writes the name, the price and the description with [Liquid](/glossary/shopify-liquid/), and a reviews app adds the stars and their [AggregateRating](/glossary/aggregaterating/) markup from the browser. In the server's first response, the reviews part is just this:

```html
<div id="reviews" data-product="8123"></div>
<script src="https://reviews.example/widget.js" defer></script>
```

The stars and the rating's [JSON-LD](/glossary/json-ld/) exist, but only after someone runs `widget.js`. This is how each fact ends up depending on who reads the page:

| Fact (fictitious example)   | Initial HTML | After running JavaScript | Googlebot                       | Bot that does not run JavaScript |
| --------------------------- | ------------ | ------------------------ | ------------------------------- | -------------------------------- |
| Name and price              | Yes          | Yes                      | Reads it                        | Reads it                         |
| Description                 | Yes          | Yes                      | Reads it                        | Reads it                         |
| Stars and number of reviews | No           | Yes                      | Reads it if rendering goes well | Does not see it                  |
| Rating JSON-LD              | No           | Yes                      | Reads it if rendering goes well | Does not see it                  |

Shopify recommends exactly that split: paint the initial content with Liquid and HTML instead of with JavaScript frameworks in the browser, and add the interactivity on top, so that **the initial HTML works without JavaScript**.[^shopify-render-server] That is server-side rendering, and it is what makes the data the theme publishes, or a [Shopify app embed](/glossary/shopify-app-embed/) written in Liquid, travel in the first response.


That [Search Console](/glossary/google-search-console/)'s URL Inspection showing the fact does not prove any bot sees it. That tool, like Google's other tests, shows the DOM as rendered by Google, with the resources loaded and the JavaScript console;[^google-js-fix] that is, the page **after** the step other crawlers do not take.[^vercel-ai-crawlers]


## How to check it

1. **Look at what Google rendered.** In Search Console's URL Inspection, test the published URL and open the tested page: you will see the rendered HTML, the resources loaded and the JavaScript console messages and exceptions.[^google-js-fix] If a needed resource did not load, start there.
2. **Compare it with the initial HTML.** Open the page's source code (not the inspector) or download it from the terminal with `curl`. What is in the rendered version and not in the source code depends on JavaScript.
3. **Check the status code of empty pages.** A removed product that shows "not found" with JavaScript but responds with a 200 is a _soft 404_. Google suggests a JavaScript redirect to a URL that responds with a 404, or adding a `noindex` with the `robots` tag.[^google-js-seo][^google-js-fix]
4. **Check the menu links, the filters and the pagination.** They have to be `<a>` elements with `href`, not buttons that change the page with a script, and they must not depend on `#` fragments.[^google-js-seo]
5. **Ask what each app does.** For each installed app that adds content to the product page, find out whether it writes it into the theme's HTML or injects it from the browser.

## Related concept: server-side rendering

The two terms get confused because they speak of the same thing from opposite sides. JavaScript rendering is the step in which scripts run to get the final content; server-side rendering is a technique that builds the complete HTML before sending it, so that step is not needed to read the essentials. With hydration they coexist: the content arrives written and JavaScript only adds the interactivity.[^webdev-rendering] A [headless](/glossary/headless-commerce/) store can use either approach, which is why it is worth asking which before assuming its pages can be read.

To go further, the guide to [what an AI crawler sees in your store](/guides/what-an-ai-crawler-sees/) checks it step by step, and the [publishing by platform reading path](/learn/publishing-by-platform/) orders the rest of the terms.
