Dynamic content SEO means making sure that content which changes by visitor, device, location or session still reaches search engines and AI crawlers as complete, stable HTML. The pattern that works: render the core content on the server (SSR or static generation), personalize only supplementary blocks, and give every variant you want indexed its own URL with a clean canonical. Google can render JavaScript, but the major AI crawlers do not, so anything that only appears after client-side rendering is likely invisible to ChatGPT, Claude and Perplexity.
This guide covers how Googlebot and AI crawlers actually see dynamic pages, which rendering approach to pick, how to handle variants, parameters and caching, and a short command-line check you can run on your own pages today.
What counts as dynamic content, and which kinds are risky
Dynamic content is any part of a page that is assembled at request time or in the browser instead of being fixed in the published HTML. Typical examples:
- Personalized recommendations ("customers like you also bought", recently viewed items)
- Location-based content: local prices, currency, store availability, language switching by IP
- Logged-in states: dashboards, member pricing, saved lists
- A/B test variants of headlines, hero sections or product copy
- Filters, sorting and faceted navigation that create parameter URLs
- Data loaded from an API after page load: reviews, stock levels, prices, related articles
- Time-based content: countdowns, event listings, "new this week" modules
Not all of this is an SEO problem. Two questions decide the risk. First: is the content present in the HTML the server sends, or only after JavaScript runs? Second: is it tied to a URL a crawler can request, or only to a cookie, a login or an IP address? Content that fails both tests is effectively private to the user who triggered it.
How Googlebot and AI crawlers see dynamic pages
Googlebot: renders JavaScript, but as an anonymous visitor
Google processes JavaScript pages in three phases: crawling, rendering and indexing. Rendering happens in a headless Chromium, so client-side content can be indexed, as Google explains in its JavaScript SEO basics. The same page also notes that server-side or pre-rendering is still a good idea because "not all bots can run JavaScript".
What Googlebot does not do is behave like a returning customer. Google's guide to fixing search-related JavaScript problems states that local storage, session storage and cookies are cleared across page loads, and that Googlebot declines permission requests such as geolocation. Its documentation on locale-adaptive pages adds that Googlebot's default IP addresses appear to be US-based and that it sends requests without an Accept-Language header. In practice Googlebot sees the anonymous, first-visit, default-location version of your page. Whatever you personalize beyond that, Google does not index.
AI crawlers: mostly raw HTML only
For AI systems the situation is stricter. Vercel analyzed crawler traffic across its network and reported in The rise of the AI crawler that none of the major AI crawlers it observed rendered JavaScript, including OpenAI's GPTBot and OAI-SearchBot, Anthropic's ClaudeBot and PerplexityBot. They may download JavaScript files, but they do not execute them. Gemini is the exception because it relies on Google's rendering infrastructure.
The consequence is simple: if your product facts, prices, FAQ answers or article body are injected by client-side JavaScript, Google may index them while ChatGPT and Perplexity never see them. For AI visibility, the initial HTML response is what counts. Our guide on making JavaScript sites accessible to AI crawlers goes deeper into framework-specific fixes.
| Content type | Real user | Googlebot | GPTBot, ClaudeBot, PerplexityBot |
|---|---|---|---|
| Server-rendered core content | Yes | Yes | Yes |
| Client-rendered content (fetched after load) | Yes | Usually, after rendering | No |
| Cookie- or login-based personalization | Yes | No (default state only) | No |
| IP-based location content | Their location | Mostly the US version | Whatever the crawler's IP gets |
| Content behind clicks or scroll events | Yes | Often not | No |
Choose the right rendering: SSR, SSG, ISR or client-side
The rendering strategy decides whether dynamic content is an asset or a blind spot. For pages that should rank or be cited, the rule is: the indexable content must be in the server response.
| Approach | How it works | Good for | Watch out for |
|---|---|---|---|
| Static generation (SSG) | HTML built at deploy time | Articles, docs, category pages that change rarely | Stale data if rebuilds are infrequent |
| Incremental regeneration (ISR) | Static HTML, refreshed on a schedule or on demand | Product and listing pages with changing stock or prices | Cache invalidation must actually fire |
| Server-side rendering (SSR) | HTML built per request | Search results, frequently changing data | Server load, response time |
| Client-side rendering (CSR) | Empty shell, content built in the browser | Logged-in apps, dashboards, non-indexed widgets | Invisible to AI crawlers, delayed for Google |
Hydration is where many frameworks go wrong. With SSR, the server sends finished HTML and the browser's JavaScript then "hydrates" it to make it interactive. That is fine as long as the content itself is part of the server HTML. It breaks when a component renders an empty placeholder on the server and fetches its data in the browser afterwards (the classic useEffect fetch in React). In Next.js, fetching data in server components or at build time avoids this; in Nuxt, use server-side data fetching instead of client-only plugins.
Dynamic rendering, meaning a pre-rendered version served only to bots via tools like Rendertron or Puppeteer, is no longer a recommendation. Google now describes dynamic rendering as a workaround and not a long-term solution, and points to SSR, static rendering or hydration instead. It also adds a maintenance risk: if the bot version drifts from the user version, you are close to cloaking.
Personalize without hurting rankings
Separate core content from personalized blocks
Decide per page what the core is: H1, introduction, main body, product facts, the default price, key FAQs. That part must be identical for every visitor and server-rendered. Personalization belongs in supplementary modules such as recommendations, recently viewed items, greetings or member offers. If those modules are client-rendered, no harm is done, because nothing depends on them being indexed.
Don't show bots something else
Serving crawlers different content than users is cloaking and violates Google's spam policies. The safe interpretation: bots get exactly what an anonymous first-time visitor gets. Avoid user-agent sniffing to swap content. It also creates inconsistencies that AI systems may pick up as conflicting facts about your brand.
Give locations and languages their own URLs
Because Googlebot mostly crawls from US addresses without language headers, IP-based content swapping hides your other versions. Use separate URLs per language or region (/de/, /en/, /fr-ch/), connect them with hreflang, and let users switch manually instead of redirecting them automatically.
Run A/B tests carefully
If test variants live on separate URLs, point them to the original with rel="canonical", use temporary (302) redirects, and end tests once you have a result. Keep the page's topic and core facts identical across variants so neither Google nor an AI system sees two different stories.
Variants, parameters and canonicals
Filters, sorting and tracking parameters generate URLs like ?sort=price, ?color=red&size=42 or ?utm_source=newsletter. Search Console's old URL Parameters tool no longer exists, so the signals have to come from the site itself:
- Tracking and sort parameters: canonical to the clean URL, and don't link to them internally.
- Filter combinations with search demand (for example "red running shoes"): give them a real path such as
/running-shoes/red/, a self-referencing canonical, a unique title and internal links. Treat them as landing pages, not as parameters. - Everything else: keep it crawlable only if it adds value. Endless filter combinations eat crawl budget without adding anything.
- Pagination and infinite scroll: each page needs its own URL reachable through a normal
<a href>link. Don't canonicalize page 2 to page 1.
Caching, the Vary header and structured data
Personalization and caching interact in ways that can leak the wrong version to crawlers. If a CDN caches a personalized HTML response, a crawler may receive another user's page, or users may receive the anonymous page. Two safe setups:
- Cacheable shell plus personalized islands: the anonymous core page is cached and served to everyone, including bots. Personalized modules load separately and are marked
Cache-Control: private. This is the simplest option for most sites. - Personalized HTML at the edge: if the server varies HTML by cookie, send
Vary: Cookieor mark the responseprivate, and make sure requests without cookies always get the default version.
Avoid Vary: User-Agent unless you really serve different HTML per device; it fragments caches and is not needed for responsive designs.
Structured data follows the same logic as content. Generate JSON-LD from the same data source as the visible page and put it in the server HTML. Google can read JSON-LD injected by JavaScript, but AI crawlers that don't execute scripts cannot. Keep values such as price and availability consistent with what an anonymous visitor sees. More on this in why JSON-LD matters for AI search visibility.
15-minute check: see your page the way bots do
You don't need a crawler suite to find the biggest gaps. Pick one important dynamic page and one sentence that must be indexable (a product fact, a price, a key FAQ answer).
- Raw HTML as an AI crawler:
curl -s -A "Mozilla/5.0 (compatible; GPTBot/1.1; +https://openai.com/gptbot)" https://example.com/page | grep -c "your key sentence"
A result of 0 means the sentence is not in the server response, so AI crawlers won't see it. - Headers and caching:
curl -sI https://example.com/page | grep -iE "cache-control|vary|x-robots-tag|location"
Check for unexpected redirects (for example IP-based),noindexinX-Robots-Tag, and whether personalized responses are cacheable. - JavaScript off: disable JavaScript in your browser's developer tools and reload. Whatever disappears is client-rendered.
- Google's view: in Search Console, run URL Inspection, then "Test live URL" and "View tested page" to compare the rendered HTML and screenshot with what users see.
- Parameters: open two filter or sort variants and check the
rel="canonical"in the source of each. - Structured data: run the page through the Rich Results Test and confirm the JSON-LD also appears in the raw HTML from step 1.
Our free AI crawler check shows whether AI bots are allowed to access your site. For a full review of rendering, crawler access and content structure, see our GEO audit.
FAQ: dynamic content and SEO
What are some examples of dynamic content?
Personalized product recommendations, location-based prices or store info, logged-in dashboards, A/B test variants, filtered and sorted product lists, reviews or stock levels loaded from an API, and time-based modules such as countdowns or event listings.
Is dynamic content bad for SEO?
No. It becomes a problem only when indexable content exists solely in the browser, behind a login or cookie, or behind an IP-based switch. Server-render the core content, personalize supplementary blocks, and give indexable variants their own URLs.
Can ChatGPT see content rendered with JavaScript?
Generally not. Vercel's crawler analysis found that OpenAI's crawlers, like ClaudeBot and PerplexityBot, fetch HTML but do not execute JavaScript. Content that only appears after client-side rendering is therefore unlikely to reach ChatGPT.
Is dynamic rendering still recommended?
No. Google describes dynamic rendering as a workaround and not a long-term solution. Server-side rendering, static generation or incremental regeneration are the recommended alternatives.
Should personalized page versions have their own URLs?
Only if they should rank on their own, such as language or region versions. Those need separate URLs with hreflang. Personalization for individual users should stay on the same URL and should not change the core content.
How do I check what Google sees on a dynamic page?
Use URL Inspection in Search Console and view the tested page's rendered HTML and screenshot. For AI crawlers, fetch the raw HTML with curl and a crawler user agent, because they don't render JavaScript.
To place this measure in the wider context of technical access, content and measurement, read our generative engine optimization guide.
To create an optional Markdown overview of your key pages, use our free llms.txt generator.
Ready for better AI visibility?
Test now for free how well your website is optimized for AI search engines.
Start Free AnalysisRelated GEO Topics
Share Article
About the Author
- Structured data for AI crawlers
- Include clear facts & statistics
- Formulate quotable snippets
- Integrate FAQ sections
- Demonstrate expertise & authority


