# What an AI agent sees on your product page

> Paste your product page source and see what a crawler that does not run JavaScript gets: text, headings, meta and JSON-LD. A free tool.

URL: https://clione.ai/tools/what-an-agent-sees/
Lang: en

If you sell online, or run your clients' stores from an agency, this tool answers one specific question: **what is on your page for an [AI agent](/glossary/ai-agent/) that does not run JavaScript**. You paste the source of a [product page](/glossary/product-page/) and the tool reads it the way a [crawler](/glossary/web-crawler/) of that kind would: nothing executed, nothing loaded, only what your server wrote. It finds the title, the tags that decide its [indexing](/glossary/indexing/), the text, the links and every [JSON-LD](/glossary/json-ld/) block. Paste the page as your browser draws it as well, and it tells you which part of the page only exists after JavaScript.

It all happens in your browser. The tool makes no requests: it reads what you paste as data, without running its scripts, and **nothing you paste leaves this page**.

## How to use it

1. **Copy the page source.** Open the product page and ask for its source: "View page source" in the right-click menu, or `view-source:` in front of the URL. Select all, copy it and paste it into the first field. That text is the HTML your server sent, before any script ran.
2. **Copy the rendered page, if you want to compare.** Open the developer tools, go to Elements, right-click the `<html>` element and choose Copy › Copy outerHTML. Paste it into the second field. It is optional, but it is the half that answers the JavaScript question.
3. **Press Check.** If you'd like to see a result first, "Load an example" fills both fields with a fictitious store built in the browser: the source is an empty container with three scripts, and the linen shirt, its heading and its data block only show up in the rendered version.
4. **Read the result from top to bottom**: first what a crawler that does not run JavaScript gets, then what only appears after JavaScript runs.

## How to read the result

### What a crawler that does not run JavaScript gets

The first part reads only the source. Each row is something a crawler finds without rendering, and "Missing" marks what is not there:

- **Title.** The text of the `<title>` element. Google accepts JavaScript setting or changing the title and the [meta description](/glossary/meta-description/),[^google-js-seo] but a crawler that does not render only has what is here.
- **Meta description.** The summary the page gives of itself in `<meta name="description">`. If it is missing from the source and you can see it on the page, a script is putting it there.
- **Meta robots.** The page's indexing instructions. "None" is the usual answer: without that tag, the page can be indexed as normal. If you see [noindex](/glossary/noindex/) here, the page is asking to stay out of search results,[^google-robots-meta] and Google warns that if it finds it before rendering, it may skip rendering altogether: removing it with JavaScript may not work.[^google-js-seo]
- **[Canonical](/glossary/canonical-url/).** The URL the page declares as the right one, in `<link rel="canonical">`. Google asks that JavaScript not change a canonical that is already in the HTML; if you cannot put it in the HTML, let JavaScript set it and leave it out of the original.[^google-js-seo]
- **Page language.** The `lang` attribute of the `<html>` element. It declares the language, but don't take it for the signal that decides it: Google says it determines the language from the visible content and does not use the `lang` attribute.[^google-multilingual]
- **Words of text.** The words in the body that are not inside scripts, styles, templates, SVGs, iframes or objects. The menu and the footer count too, so **compare it with the rendered page's count** rather than reading it on its own.
- **Links.** How many links with an `href` the source has. [Googlebot](/glossary/googlebot/) looks for links in the HTML of the response before rendering anything.[^google-js-seo] If the number jumps after JavaScript, part of your navigation only exists in the browser.
- **Images without [alt text](/glossary/alt-text/).** The `<img>` elements with no `alt` attribute; an empty `alt=""` does not count as missing. Google uses that text, together with computer vision and the rest of the page, to understand what each image is about.[^google-images]
- **Scripts.** The `<script>` elements that are not data. The number alone says nothing; next to a low word count it does, and that is why the warning in the next section exists.
- **JSON-LD blocks.** One for each `<script type="application/ld+json">`, with the types it declares inside. On a product page, you should expect at least one [Product](/glossary/product-schema/) node. If a block cannot be read, it is flagged with the error: broken JSON is a block no machine can use.
- **Headings.** The `h1`, `h2` and `h3` of the source, up to sixty. If the product name is not here, look for it in the rendered part.

### When the page is built in the browser

If the source has fewer than 150 words of text and three or more scripts, the tool warns you above the list: the page is probably assembled in the browser, and a crawler that does not run JavaScript gets little of it. It is a hint, not a diagnosis, and the threshold is ours, not any standard's.

If it fires, paste the rendered page to see what is missing, and ask whoever maintains the theme or the app to put that data in the server's HTML, with [server-side rendering](/glossary/server-side-rendering/) or prerendering. Google recommends it because the web gets faster for people and crawlers alike, and because **not all bots can run JavaScript**.[^google-js-seo]

### What only appears after JavaScript runs

With the rendered page pasted, the second part compares the two versions and shows only the differences:

- **More words**: how many words of text JavaScript adds.
- **Fields that change**: whether the title, the meta description, the canonical or the meta robots has a different value after JavaScript, with the before and the after.
- **Headings that appear only after JavaScript.**
- **JSON-LD blocks that appear only after JavaScript.** The comparison is exact: a block a script modifies, even in one field, counts as new. If your Product is here, JavaScript generates it, and Google warns that markup generated this way can make Shopping crawls less frequent and less reliable, which is a problem for fast-changing data like [price and availability](/glossary/price-and-availability/).[^google-js-sd]

If JavaScript adds no text, headings or JSON-LD, the tool says so with an "=": what you see on the page is already in what any crawler you let in downloads.

## What this tool can't tell you

- **It does not download your page.** For security, browsers restrict the requests a script makes to another domain, and only let them through if that server allows it with CORS headers.[^mdn-cors] That is why the tool works with what you paste, not with a URL.
- **What you paste is what your browser received.** Your server, your [CDN](/glossary/cdn-caching-for-bots/) or your firewall may answer [GPTBot](/glossary/gptbot/) with something different from what they answer you, or stop it before it reaches the page. Google asks that crawling be allowed in [robots.txt](/glossary/robots-txt/) and also in any CDN or hosting,[^google-ai-features] and [Perplexity](/glossary/perplexity/) advises anyone setting up a firewall to check the agent's name and its IP as well.[^perplexity-bots] What the real crawler gets is only visible in your server logs, and how to read them is in the guide [what an AI crawler sees in your store](/guides/what-an-ai-crawler-sees/).
- **It does not know whether an agent renders.** It compares two texts; it runs nothing. Google documents that it renders, and OpenAI says nothing about JavaScript in the documentation for its crawlers.[^openai-bots]
- **It only reads JSON-LD.** It does not read [microdata](/glossary/microdata/) or [RDFa](/glossary/rdfa/), and it does not validate the markup: it tells you which types are there, not whether they are complete. For that, use the [data coverage check](/tools/data-coverage/).
- **It does not read your robots.txt.** If an agent is barred from the page, none of this reaches it. Check it with [robots.txt for AI bots](/tools/robots-txt-ai-bots/).

## Source and DOM: why the difference decides what an agent reads

A page exists twice. Chrome's developer tools put it this way: the HTML is the page's initial content and the DOM is its live content, the current one, and when JavaScript adds, removes or edits nodes, the DOM stops matching the HTML.[^chrome-devtools-dom] The source you paste into the first field is that HTML; the rendered page in the second is the DOM.

A crawler downloads the first. Only something that runs the scripts has the second: your browser, and a crawler that does [JavaScript rendering](/glossary/javascript-rendering/). Googlebot is one of those: it queues the pages that answer with a 200 for rendering, renders them with a headless Chromium, and what comes out goes on to indexing.[^google-js-seo] About the others we know less, because they don't document it: OpenAI, for example, does not mention JavaScript.[^openai-bots]

The practical consequence is a single one. **What is in the source reaches any agent you let in; what is only in the DOM depends on that agent rendering.** That is why a product page's [structured data](/glossary/structured-data/), its name, its price and its availability have to be in the HTML the server sends, and why this tool starts there. The guide [what an AI crawler sees in your store](/guides/what-an-ai-crawler-sees/) follows the whole path: the robots.txt, the source, Google's renderer, the borrowed [user agent](/glossary/user-agent/) and the logs.
