# What is SSR (server-side rendering)?

> What SSR, or server-side rendering, is, how it differs from rendering in the browser, and why it decides what Google and AI bots read on your store.

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

When someone, or something, requests a [product page](/glossary/product-page/), the store answers with an HTML document. The question this term settles is what that first document carries: the product's name, price and data already written out, or a nearly empty page and a JavaScript file that assembles them afterward in the browser. Here SSR is not the "SSR" rarity tier of gacha games: it is _server-side rendering_. It matters to you because **not everything that reads your store runs JavaScript**, and what is not in the first response may never be read by anyone except a person with a browser.

## How it works

The reference guide on web.dev, written by Addy Osmani and Jason Miller and updated on January 5, 2026, distinguishes these ways of producing a page:[^webdev-rendering]

| Technique                                                | Where the HTML is built                                         | What the first response carries                   |
| -------------------------------------------------------- | --------------------------------------------------------------- | ------------------------------------------------- |
| Server-side rendering (SSR)                              | On the server, on every request                                 | The HTML with the content                         |
| [Client-side rendering](/glossary/javascript-rendering/) | In the browser, with JavaScript that modifies the DOM           | A nearly empty page and the scripts               |
| Static rendering                                         | At build time, one file per URL                                 | The HTML with the content, prepared in advance    |
| Hydration                                                | On the server, and then JavaScript adds state and interactivity | The HTML with the content, which then comes alive |

Web.dev defines SSR as rendering an application on the server to send HTML, rather than JavaScript, to the client, and client-side rendering as rendering it in the browser, using JavaScript to modify the DOM.[^webdev-rendering] The practical difference is in the first response: with SSR, whoever downloads it already has the content; with client-side rendering, they have to run the JavaScript to see it.

**Google does run JavaScript, but in a second phase.** It processes pages in three steps: crawling, rendering and [indexing](/glossary/indexing/). [Googlebot](/glossary/googlebot/) queues pages that respond with a 200 status code for rendering, and a page can spend a few seconds or longer in that queue. Even so, Google's documentation says that **server-side rendering or pre-rendering is still a great idea**, because it makes the website faster for users and crawlers, and because not all bots can run JavaScript.[^google-js-seo]

For years, one way out was dynamic rendering: serving bots a pre-rendered version and people the usual one. Google now describes it as a workaround it does not recommend, because it adds complexity and uses resources, and proposes instead **server-side rendering, static rendering or hydration**.[^google-dynamic-rendering]

## AI crawlers and the initial HTML

The "not all bots" part has become concrete with the [crawlers](/glossary/web-crawler/) of the AI companies. Vercel, with the consultancy MERJ, analyzed its network's and nextjs.org's traffic for several months, and published on December 17, 2024 that **none of the major AI crawlers rendered JavaScript**: among them, OpenAI's ([OAI-SearchBot](/glossary/oai-searchbot/), [ChatGPT-User](/glossary/chatgpt-user/) and [GPTBot](/glossary/gptbot/)) and Anthropic's ([ClaudeBot](/glossary/claudebot/)). They downloaded JavaScript files but did not execute them. The exceptions it pointed out were [Gemini](/glossary/gemini/), which uses Googlebot's infrastructure, and AppleBot, which renders with a browser.[^vercel-ai-crawlers]

Read that figure with its date and its scope: it is one company's measurement of its own network, from late 2024, and crawlers change. What does not change is the practical conclusion, which matches Google's: **if a piece of data has to be readable by any [crawler](/glossary/web-crawler/), it has to be in the initial HTML**.

## In a store

**Fictional example.** The same backpack product page, served two ways. With client-side rendering, the store's first response is this:

```html
<body>
  <div id="app"></div>
  <script src="/assets/store.js"></script>
</body>
```

The name, the price and the [structured data](/glossary/structured-data/) exist, but inside `store.js`, and they only appear when someone runs it. With server-side rendering, the first response already carries them:

```html
<body>
  <h1>Hiking backpack 30 L</h1>
  <p class="price">$89.00</p>
  <script type="application/ld+json">
    {
      "@context": "https://schema.org",
      "@type": "Product",
      "name": "Hiking backpack 30 L"
    }
  </script>
</body>
```

On Shopify, themes are written in [Liquid](/glossary/shopify-liquid/), which is resolved on the server, and Shopify recommends painting essential content that way, with Liquid and HTML, instead of with JavaScript frameworks in the browser: the initial HTML works without JavaScript.[^shopify-render-server] That is why a piece of data stored in [metafields](/glossary/shopify-metafields/) and painted by the theme arrives in the first response. Clione publishes its structured data through each platform's native routes, rendered on the server: a [BigCommerce widget](/glossary/bigcommerce-widget/) on BigCommerce, and metafields with a [Shopify app embed](/glossary/shopify-app-embed/) on Shopify, without injecting them with JavaScript in the browser.


The browser inspector does not show the initial HTML. It shows the DOM, that is, the page after JavaScript has modified it, so seeing the price or the [JSON-LD](/glossary/json-ld/) there does not prove they are in the first response.[^webdev-rendering] The page's source code is for that.


## How to check it

1. **Open the product page and look at the source code** (in most browsers, Ctrl+U or Cmd+Option+U). That is the initial response. Look for the product name, the price and `application/ld+json`.
2. **Compare it with the inspector.** What appears in the inspector and not in the source code was added by JavaScript afterward.
3. **Download it from the terminal**, with no browser: `curl -s https://your-store.example/products/backpack | grep "ld+json"`. If it returns nothing, the structured data is not in the initial HTML.
4. **Turn off JavaScript in the browser and reload the product page.** Whatever disappears depends on JavaScript to be shown.
5. **Look at what Google rendered.** The URL Inspection tool in [Search Console](/glossary/google-search-console/) and the one Google offers to check [rich results](/glossary/rich-results/), the [Rich Results Test](/glossary/rich-results-test/), show the rendered HTML.[^google-js-seo] Remember that this is what Google sees after running JavaScript, not what a bot that does not run it sees.

## Related concept: JavaScript rendering

[JavaScript rendering](/glossary/javascript-rendering/) is the step in which a browser, or a crawler like Googlebot, executes a page's scripts to get its final content. SSR aims to make that step unnecessary for reading the essentials: the content already arrives written out, and JavaScript only adds interactivity on top, as in hydration.[^webdev-rendering] A [headless](/glossary/headless-commerce/) store can use either technique, which is why it pays to ask which one it uses before assuming its product pages can be read.

To keep going, the [publishing by platform reading path](/learn/publishing-by-platform/) explains how each piece of data reaches the store on Shopify and on BigCommerce.
