What Google and ChatGPT actually see on your store
Server-side rendering decides what Google, AI assistants and link previews see on your store. Here's why it matters for rankings, sales and ad costs.
On this page
The empty page nobody tells you about#
Open your store in a browser and it looks great. Products, prices, photos, a nice "Add to cart" button.
Now picture what a bot gets when it asks for that same page. On many stores built as a single-page app (SPA), the server's answer looks roughly like this:
<html>
<head><title>Shop</title></head>
<body>
<div id="root"></div>
<script src="/app.js"></script>
</body>
</html>
That's it. No product name. No price. No photo. Just an empty box and a note that says "run this script and the store will appear."
A browser on a decent phone runs the script and builds the page in a second or two. But plenty of the visitors that matter most to your business don't run it, or don't run it right away:
- ChatGPT, Claude and Perplexity crawlers looking for products to recommend
- the WhatsApp, Facebook, Slack or iMessage bot building a preview when someone shares your link
- Google, which does run JavaScript, but later, in a separate step
Each of them is deciding something about your store based on what's in that first response. If the first response is an empty box, you're asking them to take your word for it.
SSR vs SPA, in plain words#
Think of a restaurant. A single-page app is like handing each guest a box of ingredients and a recipe card. The guest's own kitchen (their phone) does the cooking. Fast kitchens manage fine. Slow kitchens take a while. And some guests (bots) never cook at all; they just look at the raw box and leave.
Server-side rendering is the kitchen cooking the dish and bringing it to the table ready to eat. The guest can start right away. A little JavaScript still arrives afterward to make the buttons and the cart interactive, but the meal is already on the plate.
| Single-page app (SPA) | Server-side rendering (SSR) | |
|---|---|---|
| What arrives first | An empty shell plus a script | The full page: text, prices, images, tags |
| Who builds the page | The visitor's device | Your server |
| Bots that skip JavaScript | See almost nothing | See everything |
| Slow phones, weak signal | Wait for the script before seeing much | See content sooner |
| Good fit for | Dashboards, account areas, internal tools | Product pages, collections, content |
Google's own Rendering on the Web guide defines SSR as rendering on the server "to send HTML, rather than JavaScript, to the client." That's the whole idea. The rest is consequences.
Why it matters for a store#
Google indexes you sooner#
Google does run JavaScript. It just doesn't do it on the first pass. According to Google's JavaScript SEO basics, it handles JavaScript sites in three phases: crawling, rendering and indexing. Pages go into a render queue, and Google says a page "may stay on this queue for a few seconds, but it can take longer than that."
For a store, "longer" has a cost. Say you sell handmade candles and you drop a holiday collection on Monday morning. With SSR, Google sees the new product names and prices on the very first crawl. With an SPA, those pages may sit in a queue as empty shells until rendering catches up. Same goes for a price cut or a sold-out item coming back in stock.
The same Google page says plainly that "server-side or pre-rendering is still a great idea," partly because not every bot can run JavaScript. We agree.
Big catalogs waste less crawl attention#
Google spends a limited amount of effort on each site. Its crawl budget guide is aimed at large sites (roughly 1 million+ pages) or sites with 10,000+ pages that change daily, and it notes that if Google can "load and render your pages faster, we might be able to read more content from your site."
A few dozen products? Don't lose sleep over it. Thousands of variants with prices that change often? Then pages that arrive finished start to pay off.
AI assistants can actually read you#
This is the one we think most merchants are underestimating.
When someone asks ChatGPT "what's a good unscented soy candle under $30?", the answer is built from pages those AI systems were able to read. Vercel and MERJ studied this in The rise of the AI crawler and found that "none of the major AI crawlers currently render JavaScript." That list includes OpenAI's GPTBot, ChatGPT-User and OAI-SearchBot, Anthropic's ClaudeBot, and PerplexityBot. (Google's Gemini is the exception, because it uses Googlebot's infrastructure.)
These bots aren't small, either. In the month Vercel measured on its network, GPTBot made 569 million fetches and Claude's crawler made 370 million. Their advice is short: "Prioritize server-side rendering for critical content."
So if your product pages are empty shells, a growing share of product discovery simply can't see them. Not ranked low. Not there.
Shared links that sell#
When a customer pastes your product link into a WhatsApp group or a Facebook post, a bot fetches the page and builds the little card: photo, title, sometimes the price. Those preview bots read the HTML they're handed. In practice they don't sit around waiting for your app to finish loading.
With an SPA, that card often shows your store name and a generic logo. With SSR, it shows the actual candle and its price. Guess which one gets tapped.
Rich results and Shopping#
Structured data is a small block of code that tells Google "this is a product, it costs $24, it's in stock, it has 4.8 stars." It's what powers those richer search results with price and rating right under the link.
You can inject it with JavaScript, but Google warns against relying on that for products. Its guide on generating structured data with JavaScript says "dynamically-generated markup can make Shopping crawls less frequent and less reliable," which matters most for fast-changing details like stock and price. If you run Google Shopping or Merchant Center listings, you want that data sitting in the page from the first byte.
Real "not found" pages#
Here's a quiet SPA problem. When a product is deleted, a server-rendered store can answer with a real 404 status, the official "this doesn't exist" signal. Many SPAs answer every URL with a cheerful "200 OK" and then let JavaScript draw a "Product not found" message.
Google calls that a soft 404: a page that returns success but looks like an error or empty page. Its JavaScript SEO guide even lists workarounds SPAs need just to avoid it. And per the crawl budget guide, soft 404 pages "will continue to be crawled, and waste your budget." Dead products keep eating attention that should go to live ones.
Some other quiet wins#
A few more that don't need a whole section each:
- It still works when JavaScript breaks. A third-party widget throws an error, an ad blocker kills a script, a corporate network blocks a domain. With SSR the shopper still sees the product and price.
- Reader modes, translators and screen readers get real content to work with from the start.
- Paid ads land better. Landing page experience is one of the three parts of Google Ads Quality Score. A page that shows the product immediately, instead of a spinner, is a better landing page for the click you just paid for.
Speed is money (and there's data on it)#
Most of your shoppers are on phones. Not all of those phones are new, and not every connection is good. A client-side app has to download, parse and run its JavaScript before the page shows much of anything. Google's rendering guide notes that the amount of JavaScript "tends to grow as an application grows" and that client-side rendering "can be difficult to make and keep fast for mobile devices." SSR, by contrast, "generally produces a fast FCP" (first contentful paint: the moment something useful appears on screen).
Does a fraction of a second really matter? The best-known study says yes. Milliseconds Make Millions, commissioned by Google and conducted by 55 and Deloitte, looked at 37 European and American brand sites and more than 30 million user sessions. A 0.1 second improvement in mobile site speed came with an 8.4% increase in conversions for retail sites, and retail shoppers spent 9.2% more per order.
One honest footnote: that lift showed up when every page in the shopping journey got faster. The homepage alone doesn't cut it.
SSR won't make a heavy page light by itself. It removes one big delay: waiting for the app to boot before anything shows.
The honest downsides#
We're fans of SSR, but it isn't free, and we'd rather you hear the trade-offs from us.
Someone has to run servers. With an SPA you can drop static files on a cheap host. With SSR, a server builds pages on request. That's more infrastructure, more monitoring, more to go wrong.
Done badly, it can be slower. If the server takes ages to fetch data and build the page, the shopper stares at a blank tab waiting for the first byte. Google's guide calls this out directly: SSR "can increase your page's TTFB" (time to first byte). Good SSR is fast SSR.
Hydration hiccups. After the server sends the finished page, the browser loads JavaScript to make it interactive. That step is called hydration. If what the server drew doesn't match what the browser expects (say the server shows one price and the browser computes another), you get flicker, broken buttons or errors. And until hydration finishes, the page can look ready while ignoring taps. Google notes hydration can hurt interactivity "even if it improves FCP."
Caching vs. personal data. This one is serious. To keep SSR fast, people cache pages. But a store page often has personal bits: a cart count, a chosen currency, a logged-in wholesale price. If a page with one shopper's cart or prices gets cached and served to the next shopper, that's a privacy and trust problem, not a performance tweak. Personal content must never land in a shared cache.
Scripts that assume a browser. Some third-party widgets (chat bubbles, review badges, tracking pixels) expect to run in a browser and crash on a server. They need to be loaded carefully, on the client only.
Caching, done right (the simple version)#
You don't need to be an engineer to know what "right" looks like. Three ideas cover most of it.
First, files that never change get cached for a long time. Images, stylesheets and scripts can carry a version in their file name. When the file changes, the name changes. So the browser can keep the old one for a year without ever showing a stale version.
Second, every release is a matched set. A page should always load the exact scripts and styles it was built with. The classic bug is a new page pulling an old script (or the reverse) in the middle of a deploy, and something breaks for ten minutes. Versioned releases stop that.
Third, personal data stays out of shared caches. Anything specific to one shopper (cart, account, personalized price) is either fetched fresh or kept in that shopper's own browser. Never in a cache other people read from.
When an SPA is perfectly fine#
Honestly, not everything needs SSR.
Your order dashboard, a customer's "My account" area, an internal stock tool: none of these need to rank on Google or be read by ChatGPT. They sit behind a login, and people use them in long sessions where a snappy app matters more than the first second. An SPA is a great fit there.
The rule of thumb we use: if a stranger, a search engine or an AI assistant should be able to find and understand the page, render it on the server. If it's for someone already logged in, do whatever makes the app nicest to use.
What we do at NanoSite#
Every store page on NanoSite is server-rendered on each request. So Google, AI assistants and link preview bots get the full page (products, prices, images) on the first response, without waiting for JavaScript.
The SEO basics are built in: title and meta tags, canonical URLs, hreflang for multi-language stores, Open Graph tags for link previews, and Product and Store structured data (JSON-LD). Each store also gets its own sitemap.xml and robots.txt generated automatically. AI crawlers are allowed by default, and you can switch them off if you'd rather not be read by them.
Each store renders in its own isolated sandbox, separated even in memory. A traffic spike or a bug in one store stays in that store; it doesn't spill over into anyone else's pages or data.
Every publish is a new, immutable version. A page and its assets always match, and old files never mix with new ones. Versioned assets are cached long-term by browsers, so returning shoppers load less.
And if you're building a regular website rather than a store, those pages are prerendered to static HTML at build time, so they arrive finished too.
If you want a store that shows up whole for people, search engines and AI assistants alike, take a look at NanoSite.