Content & Answer Pages · 7 min read · September 24, 2026 · Hafsa Tariq, gaash.ai
The PDF trap: when your price list is a file, an assistant cannot quote it
A fetcher that reads your page receives its HTML and, in most cases, nothing else. A price list inside a PDF, a menu uploaded as an image, or a brochure built by a script after the page loads sits outside that HTML, so an assistant asked what you charge has nothing to quote. In our audit of 9,483 small business websites, 2.1% kept their substance in a PDF and 3.0% rendered it only in JavaScript.
What does a fetcher receive when it opens your page?
The HTML your server sends, and that is close to all. Our audit crawler, identifying itself as gaash-audit/1.0, fetched the homepage, the contact page and the about page of each site with JavaScript off, which is how the assistants' own crawlers describe themselves too: none of the operator documentation for OAI-SearchBot, PerplexityBot or Claude-SearchBot promises to run a page's scripts. Google does render JavaScript, but its JavaScript documentation describes rendering as a separate, deferred step after the initial crawl.
So the words that matter have to be in that first response as text. A heading, a paragraph, a table, a list: those are text. A PDF is a separate file behind a link, which a fetcher may or may not open and, if it does, reads as a document rather than as your page. An image of a menu is pixels. A price table that a script assembles from a spreadsheet after the page loads is an empty container at fetch time. Each of these is a common way for the most-asked facts about a business, what it costs, what it offers, when it is open, to leave the page.
What the crawl found
Across the 9,483 sites that answered (40 trades, 90 metros, September 2026), 2.1% kept their real content, the price list or the service menu, inside a PDF. 3.0% served their text only through JavaScript, so a crawler that runs no scripts received an empty shell. Those are small shares next to the 61.5% with no question-and-answer content at all, and they matter out of proportion to their size, because a PDF or an image is where the exact fact a buyer asks about most often tends to live.
The pages around the missing fact were not thin. The median homepage ran to 880 words. A restaurant site with eight hundred words about its history and a menu as a PDF has answered every question except "what do they serve and what does it cost", which is the question a buyer asked the assistant.
Which formats an assistant can and cannot use
| Format | What a non-rendering fetcher gets | The move |
|---|---|---|
| Text in HTML: headings, paragraphs, tables, lists | The words, in order, with their structure | Nothing; this is the target |
| A PDF behind a link | A link; the document only if the fetcher chooses to open it, and then as a separate file | Put the content on the page as HTML; keep the PDF as a download if people print it |
| An image of a menu, a price board or a flyer | The image's alt text, if any, and nothing of the words in the picture | Type the words onto the page; use the image as illustration with alt text that says what it shows |
| A table built by a script from a data source | An empty element, or a loading message | Render the table on the server, or paste it in as a static HTML table and update it when prices change |
| A widget from a third party (menu, booking, reviews) | A script tag and a container | State the facts in your own HTML next to the widget: the dishes and prices, the hours, the rating |
| Text inside a video or a slideshow | Nothing | A transcript or a summary in text under it |
The HTML standard's table element exists for exactly the thing a price list is: rows of items with a price beside each, a caption saying what the list is, and a header row a parser can read the columns from. It is also the format that survives being turned into plain text, which is how most retrieval systems read a page. A price list as a table is the same fact stated once for the person and the machine.
Moving a price list or a menu onto the page
- Open the PDF and type its contents into the page as a table: one row per item, a column for the price or the range, a caption that names the list and the month the prices were current.
- Group by section with a heading each (starters, mains; call-out, hourly, materials), so a buyer's question about one part lands on that part.
- Where a price depends on a visit, say so in the row: "quoted after a visit" is a fact; a missing row is a gap.
- Keep the PDF as a download link under the table for people who print, and say it is the same list.
- Mark the business up once with the type for your trade and, for a shop or a restaurant, add Offer or Menu markup that repeats the visible prices; which types describe a business is in structured data for AI.
- Change the table and the PDF on the same day when a price changes. Two versions of a price is a wrong price.
For an image, the same procedure with one extra step: keep the image, because it may be the nicer thing to look at, and give it alt text that says what it is. Google's image documentation is clear that the words a picture contains are not read from the picture; they have to be in the page. The alt text describes the image; the table carries the prices.
Why a script-built page is the same trap
A page that loads a shell and then fills it from a data source is a PDF with extra steps. The 3.0% of audited sites in that state had, in many cases, a modern site with a menu system that fetched its content on the client. To a person with a browser it looked complete; to a fetcher that ran no scripts it was a heading and a spinner. Google may render it eventually, on its own schedule; the assistants' documented crawlers do not promise to.
The fix is on the server side: render the page with its content already in the HTML, which every current site framework can do, or publish the facts as static HTML and update them by editing the page. What you should not do is leave the words to a script and hope. The test is the one that closes every article on this site: view the source with scripts disabled, and read what a fetcher reads.
How to find your own trap in ten minutes
- Ask yourself the three facts a buyer most often calls about. For most trades: what it costs, what you offer, when you are open.
- Find where each fact lives on your site. If the answer is "in the PDF", "in the photo" or "in the booking widget", you have found the trap.
- View the source of that page with scripts disabled and search for one price. If it is not in the text, a fetcher does not have it.
- Move the fact into the HTML as a table or a paragraph, on the page a buyer would open for it.
- Ask the four assistants what you charge for the thing you moved, a month later, and read what they say. Our measurement does the same with one of them, Claude, on a fixed panel of twelve questions; the crawler access check confirms the crawlers are allowed as far as the page in the first place.
Common questions
Do AI crawlers read PDFs at all?
Some fetchers open a linked PDF and some do not, and none of the assistant operators documents a rule you could rely on. What every one of them reads is the HTML of the page it was sent to. A price list that exists only as a PDF depends on a behavior nobody promises; a price list on the page as a table does not. Keep the PDF for printing and put the words on the page.
My menu changes every week. Do I have to retype it each time?
You have to publish it as text each time, which is different from retyping. Most site systems let you keep a menu as a list in the editor and render it as HTML; the point is that the rendering happens on the server and the words are in the page when it is fetched. A photographed board is faster on the day and invisible for the week; a text list takes ten minutes and answers the question all week.
Is a table better than a paragraph for prices?
Yes. A table states an item and its price on one row with a header a parser can read the columns from, and it survives being turned into plain text, which is how retrieval systems read pages. A paragraph that runs six prices together is readable by a person and easy to misparse. Use the table for the list and a sentence for the condition, such as how quotes work.
Does a booking or menu widget count as content on my page?
Not to a fetcher that runs no scripts, which is how the assistants' crawlers describe themselves. The widget is a script tag and an empty container until a browser runs it. Keep the widget for the visitor and state the same facts in your own HTML beside it: the dishes and prices, the hours, the rating. Then both readers get the same answer.
Sources
The percentages are this site's own, from the audit named below; the sample was drawn per metro and trade, not from a random frame. What a rendering step is, and what an image's words are to a crawler, is from Google's documentation; the table element is the HTML standard's.
Sources: our audit of 9,483 small-business sites, with its method · Google, JavaScript SEO basics · Google, image best practices · HTML Standard, tables
Read on