TL;DR
- ChatGPT, Claude and Perplexity read raw HTML and do not execute JavaScript. A menu drawn by a script or delivered in an embedded widget can rank in Google and still be missing from every AI answer.
- A PDF menu hides the only text on a restaurant website that names what the kitchen actually cooks. Those dish names, ingredients and producers are the vocabulary a specific question has to match against.
- Structured data matters less than the industry claims. Google documents no Menu rich result, only a menu URL on Local Business, and one of the best menu pages we tested carries no structured data at all.
- Several statistics quoted about menus and AI search do not survive checking. We traced one popular figure to a single blog post with no method and no dataset.
- Every example below was tested with curl rather than a browser, because that is the only way to see what a machine sees.
A diner asks an assistant for a vegetarian tasting menu near London Bridge. It names three restaurants. Your kitchen has run a vegetarian tasting menu for two years and you are not one of the three.
The usual explanations are reviews, authority, or the general mystery of AI search. Often the reason is duller. The assistant never had your menu. It had your homepage, which describes the room, and your booking page, which describes availability. The one document that lists what you actually cook was a PDF, and its contents never reached the answer.
This is the part of restaurant AI visibility that gets least attention, because it looks like a design decision rather than a marketing one. It is neither. It is a retrieval problem, and it is testable in about thirty seconds.
What does an AI engine actually need from a menu page?
Three things have to happen in order. A restaurant can fail at any one of them and the result looks identical from the outside: the venue is simply not mentioned.
| Layer | What has to be true | What breaks it | How you test it |
|---|---|---|---|
| Retrieval | A crawler can fetch the text without running code | PDFs, images of menus, JavaScript rendering, iframes, vendor subdomains | curl the page and read what comes back |
| Extraction | The text survives being cut into chunks | Multi-column layouts, price columns, tables flattened into prose | Read the extracted text back and see if dish and price still belong together |
| Matching | Something specific exists to match a specific question | Menus described in adjectives instead of dish names | Search the raw response for a dish you are known for |
Most advice concentrates on the third layer and calls it content strategy. Restaurants mostly fail at the first.
Why do AI crawlers miss menus that Google indexes perfectly?
Because the crawlers behind AI answers are not the crawler you have spent fifteen years optimizing for.
OpenAI documents four crawlers with independently controllable robots.txt tokens: GPTBot for training, OAI-SearchBot for surfacing results in ChatGPT search, ChatGPT-User for a live fetch triggered by a person, and OAI-AdsBot [1]. Perplexity documents PerplexityBot for systematic indexing and Perplexity-User for live per-question fetches [2]. Anthropic documents ClaudeBot, Claude-User and Claude-SearchBot, and states that all three honor robots.txt [3].
What none of those vendor pages document is a rendering step. Independent measurement of crawl logs reports that GPTBot, ClaudeBot and PerplexityBot request JavaScript files without ever executing them, and make no second pass once a page would have finished rendering [4]. That is third-party observation rather than a vendor statement, so treat the precise numbers with care, but the direction is consistent and it matches what anyone can reproduce with a terminal.
The practical consequence is specific and expensive. Google renders JavaScript, so Google AI Overviews inherits that tolerance through Googlebot, and Copilot inherits it through Bingbot. Standalone ChatGPT, Claude and Perplexity do not. A menu assembled in the browser can therefore be perfectly visible in Google, perfectly visible to you when you check it, and entirely absent from the assistants your guests are actually asking.
This is why the only honest test is a fetch, not a look. We built a control to show the size of the gap. The same menu, from the same data file, rendered two ways:
$ curl -s http://localhost:3000/menus/borough-market/dinner | grep -o "Bavette Steak"
Bavette Steak
$ curl -s http://localhost:3000/csr-demo | grep -o "Bavette Steak"
$
One dish name, present in the first and absent in the second. In a browser the two pages look the same. To a crawler that does not run scripts, the second restaurant does not serve that dish.
Run the same command on your own menu before you read any further. If your dish names do not come back, nothing else on this page matters yet.
What does a PDF actually cost you?
Two separate things, and they compound.
The extraction tax. A PDF stores visual position, not reading order. Research into retrieval pipelines describes exactly this failure: standard text-based chunking struggles with complex document structures, multi-page tables and content that depends on context across page boundaries, which is why vision-guided chunking methods exist at all [5]. A menu is close to the worst case for the naive version. Dish name, description and price usually sit in separate visual columns, so a column-order extractor interleaves them and produces lines that read like nonsense. The price ends up attached to the wrong dish, or to nothing.
The vocabulary you never publish. This is the part restaurants underrate. Your homepage is adjectives: seasonal, welcoming, produce led. Your menu is nouns. It is the only page on your site that contains Nduja, Herdwick, Osietra, Sauternes, Rockpile, the specific words a specific question is made of. Information retrieval research frames the general problem as document vocabulary mismatch, where rare and long tail queries fail because the terms a person searches for do not exist in retrievable form, and cites "what are the ingredients of a named dish" as a canonical hard case [6]. No study has measured this on restaurant menus specifically, so treat it as reasoning from established retrieval mechanics rather than a menu benchmark. The mechanism is not controversial though. Text that is not retrievable cannot be matched.
Put those together and a PDF menu does not merely rank badly. It removes the restaurant from the entire long tail of dish, ingredient, producer and dietary questions, which is most of how people now ask.
Seven restaurant menu pages that get this right
Each of these was fetched on 5 September 2026 with curl, with the response inspected outside script tags. Each teaches something the others do not.
1. Hawksmoor, for the multi-venue reference implementation

thehawksmoor.com/locations/borough/food/menu is the fullest implementation we found anywhere. Dish names, cut descriptions and prices are plain text in the response, and the page carries a complete graph: Restaurant, Menu, MenuSection, MenuItem, Offer, UnitPriceSpecification. Individual dishes carry dietary marking, for example "suitableForDiet":"https://schema.org/VegetarianDiet". Multiple price points per cut are modeled properly as separate Offer objects rather than a string.
The structural lesson is the URL pattern. Every location has its own address, /locations/<venue>/food/menu/, and its own complete graph. That is how a group avoids the problem where several venues blur into one ambiguous entity and an engine cannot tell which one to name. We have written separately about how restaurant groups cannibalise their own venues in AI answers.
2. Zizzi, for allergen and dietary data at chain scale

zizzi.co.uk/menus publishes calorie counts and diet tags as visible text next to every item, and backs them with NutritionInformation and suitableForDiet in structured data. It is the only example in our set combining both at scale, and the data model was clearly built for structured menu content rather than bolted onto a marketing site later.
Worth noting for anyone about to copy it: the entire national menu ships in one response of around three megabytes, with sections grouped under tabs by the browser. Every section is still in the HTML. Tabs that hide content with CSS are fine. Tabs that fetch content on click are not.
3. The Capital Grille, for a wine list done as text
thecapitalgrille.com/our-wines puts producer, region, varietal, tasting note and food pairing into real markup, using definition lists, so each wine name sits in a <dt> and its description in the matching <dd>. That is unusually good semantic structure, and it is exactly the dense proper-noun vocabulary that a question like "where can I drink Pomerol with a dry aged steak" needs to match.
The judgment call is as instructive as the markup. A chain this size does not attempt to publish its whole rotating bottle list. It publishes curated, evergreen selections in text and leaves the volatile full list to an in-restaurant system. Publishing everything is not the goal. Publishing the durable part is.
4. Core by Clare Smyth, for proving text and schema are different problems

corebyclaresmyth.com/menus serves the entire tasting menu as text, every course, the price and the wine pairing price, with no structured data on the page at all. It is a cleaner proof than any argument we could construct: raw readability and structured data are two independent axes, and the readability one matters more.
There is a genuine curiosity here too. Fetch that page without running scripts and the full course list is in the response. Open it in a browser and the course list is not in the live document until you click through to a menu. We checked both, and the count of the word Osietra is one in the fetched HTML and zero in the rendered page. A crawler that ignores JavaScript currently sees more of that menu than a visitor does before interacting. It is an accident rather than a strategy, but it is a useful reminder that what you see and what a machine gets are different artifacts.
5. Freeman's, for showing you do not need a custom build

freemansrestaurant.com is one independent restaurant on Squarespace, and it passes the fetch test completely. Dinner, lunch, brunch and dessert are all present as text in a single response, prices included, with no custom engineering involved.
One platform detail is worth knowing because it looks alarming and is not. Squarespace's default robots.txt now names AI crawlers individually, including GPTBot, ClaudeBot, anthropic-ai, CCBot, Google-Extended and Applebot-Extended. It names them in order to apply the same administrative disallow list used for everyone, covering paths like /config and /api/. It does not block them from your content.
6. Hans im Glück, for the multi-country price problem

menu.hansimglueck-burgergrill.de is the only non English example in our set, and it solves a problem most groups get wrong. Prices differ across Germany, Austria, Switzerland and the Netherlands, so the shared menu omits price entirely rather than publishing one country's number and misleading everyone else. What it does publish is generous: dish names, ingredient descriptions, diet tags and a full nutrition panel per item, all as text, in German.
If you operate across price zones, this is the honest pattern. Publish everything that is true everywhere and leave out the one field that is not.
7. L'Enclume, for where robots.txt is heading

lenclume.co.uk/sample-menu publishes a full course list and five tiers of wine pairing as text. Two things make it worth studying. Its structured data points at a group level identity on a separate domain using an @id reference, which is one tidy way for a multi-venue group to link its venues without repeating the whole organization object on every site.
The second is that its robots.txt no longer looks like a robots.txt. It uses Cloudflare's newer content signals format, a policy statement about search, ai-input and ai-train uses rather than a list of allow and disallow lines. No signal is actually set in the file, which under the format's own logic means permission is neither granted nor withheld. If you have not looked at your robots.txt since your host last updated it, look now.
Two menus that are unreadable right now
Both of these are good restaurants making an ordinary choice. That is the point: this is not a competence problem, it is an invisible one.

Noble Rot on Lamb's Conduit Street is a wine bar with a serious list. The page carries around 1,600 characters of readable text and no prices at all. The food menu and the wine list are both PDF downloads, the wine list alone running to 580KB. A wine list is the densest possible source of producer, region and vintage vocabulary, and none of it is on the web page.

Tim Raue in Berlin holds two Michelin stars. Its menu page describes the menus in prose and contains no dishes and no prices; the actual menus sit in PDFs under /wp-content/uploads/menu/DE/. One of the menu links on that page is also malformed, pointing at http://wp-content/uploads/..., which resolves to nothing at all. Berlin is a market where the city tourism board is the single most cited source in AI dining answers, which makes a restaurant's own unreadable menu doubly costly.
Does structured data actually help?
Less than you have been told, and it is worth being precise, because this is where most menu advice overreaches.
Google's Search Gallery, the canonical list of every structured data type Google supports for rich results, contains no dedicated Menu, Restaurant or FoodEstablishment feature [7]. Google's Local Business documentation lists menu as a recommended property typed as a URL, described as the fully qualified URL of the menu; the word hasMenu does not appear on that page at all [8]. So the nested Menu, MenuSection and MenuItem graph is valid schema.org vocabulary that you may correctly publish, but Google does not document consuming or rewarding it as its own rich result.
Whether the assistants read it is thinner still. We found no primary statement from OpenAI, Anthropic or Perplexity confirming that their crawlers parse or weight schema.org markup. That is not evidence they ignore it. It is an absence of evidence that the industry routinely fills with invented numbers.
The reasonable position: mark up your menu because it makes your facts explicit and costs little once, and because the Local Business menu URL is genuinely documented. Do not expect it to substitute for readable text. Core by Clare Smyth carries none, and a perfectly legible menu. That is the better failure to have.
One correctness trap if you do implement it. The suitableForDiet property only accepts values from the RestrictedDiet enumeration, which is exactly eleven: DiabeticDiet, GlutenFreeDiet, HalalDiet, HinduDiet, KosherDiet, LowCalorieDiet, LowFatDiet, LowLactoseDiet, LowSaltDiet, VeganDiet and VegetarianDiet [9]. There is no DairyFreeDiet and no NutFreeDiet. Allergen information has to be written as text, which you should be doing anyway.
The menu statistics that are not real
While researching this piece we tried to source the figures that circulate in menu and GEO marketing content. Several do not survive contact.
| Claim you will see quoted | What we found |
|---|---|
| "GPT-4 goes from 16% to 54% correct with structured data" | No such study locatable. Attributed vaguely to a source that does not appear to contain it. |
| "Structured data gets you cited 3.2 times more often" | Traced to one Medium post describing an analysis of 73 sites, with no method, no dataset and no verifiable credentials, then re-cited elsewhere as "recent research". |
| "Menus with structured data are 30% more likely to appear in AI answers" | Vendor blog content only, no sample, no method. |
| "Over 60% of restaurant websites use PDF menus" | Repeated widely, no crawl study or survey behind it that we could find. |
| "85.73% of German diners prefer printed menus" | Attributed to a named 2021 survey. We fetched that survey page directly and the figure does not appear on it. |
We are not claiming these are all false. We are saying nobody has shown them to be true, and a restaurant should not spend money on the strength of a number laundered through two blog posts. The argument for readable menus does not need them. It rests on a mechanism you can verify yourself with one command.
What can your platform actually do?
The honest summary, checked against each vendor's live documentation in September 2026. The distinction that matters is not whether a platform can show a menu, it is whether it can output crawlable text plus valid structured data that a non technical person can keep current.
| Platform | Readable menu text | Menu structured data | The trap |
|---|---|---|---|
| Squarespace | Yes, native Menu block on every paid plan | Only via Code Injection, which needs Core or above | Squarespace emits its own Website, Organization and Local Business schema on every page, which can collide with Restaurant schema added on top, and the Menu block does not feed your injected schema, so the two drift apart silently |
| Webflow | Yes, CMS Collections | Yes, bound to CMS fields in the Collection Template | Field and character caps bite a rich menu late, and each extra locale needs its own schema |
| WordPress | Yes | Not from Yoast or Rank Math, which stop short of Menu schema | The popular advice to install an SEO plugin does not cover this at all |
| Wix | Yes, Restaurants Menus app | Unconfirmed, the vendor documentation does not state what its structured data toggle emits | You cannot verify the output from the documentation, so you have to test the live page |
| Shopify | Yes, via metaobjects | Yes, hand written in the theme | Modelling dishes as products drags in checkout plumbing you do not want |
| Next.js and similar | Yes, pre-rendered | Yes, generated from the same source | Needs a CMS layered on top before a marketing manager can edit it |
| Toast, Popmenu, Flipdish, UpMenu | Yes, on your own domain | Varies by vendor | The domain connection is not automatic, and an unconnected site is invisible |
| Reservation and stock widgets | No | No | An embedded booking or ordering widget is not a menu page, and iframed vendor content often carries noindex of its own |
Two cross-cutting points. First, an iframe is not a shortcut. Google can sometimes attribute iframed content to the parent page, but that breaks if the embedded URL carries noindex, which vendor widgets commonly do, and it does not help with assistants that never run the script in the first place. Second, a menu that lives on a vendor's subdomain rather than your own domain is likely paying a citation cost. The only tracked evidence we found is small and cross-industry rather than restaurant specific, so treat it as directional, but it points the same way as everything else: publish on your own domain.
The strongest objection, and the answer
A working restaurateur has a good reply to all of this. The PDF is the print menu. A designer delivers one file each season, it goes to the print shop and it goes on the website, and maintaining a second structured version is real work that nobody in the building has time for.
That objection is correct, and any advice that ignores it is advice for somebody else's restaurant. The answer is not to maintain two systems. It is to invert which one is the source. Keep the menu as structured data, then generate both outputs from it: the web page and the print ready file. The designer keeps their layout, the kitchen keeps its workflow, and the text becomes retrievable as a side effect rather than as a chore. That is a build, and it is the subject of our step by step guide to building a dynamic menu page.
It is also the thing we do for restaurants as part of the monthly fee rather than as a separate quote, for every venue and every menu. If your menus are PDFs today, that is the work.
Sources
- OpenAI, "Overview of OpenAI Crawlers", https://developers.openai.com/api/docs/bots, verified 2026-09-05.
- Perplexity, "Perplexity Crawlers", https://docs.perplexity.ai/docs/resources/perplexity-crawlers, verified 2026-09-05.
- Anthropic, "Does Anthropic crawl data from the web, and how can site owners block the crawler?", https://support.claude.com/en/articles/8896518-does-anthropic-crawl-data-from-the-web-and-how-can-site-owners-block-the-crawler, updated 7 April 2026, verified 2026-09-05.
- Passionfruit, "JavaScript Rendering and AI Crawlers: Can LLMs Read Your SPA?", https://www.getpassionfruit.com/blog/javascript-rendering-and-ai-crawlers-can-llms-read-your-spa, 2026, verified 2026-09-05. Third-party crawl measurement, not a vendor statement.
- Tripathi, Odapally, Das, Allu and Ahmed, "Vision-Guided Chunking Is All You Need: Enhancing RAG with Multimodal Document Understanding", arXiv:2506.16035, 19 June 2025, https://arxiv.org/abs/2506.16035, verified 2026-09-05.
- "Synthetic Data Powers Product Retrieval for Long-tail Knowledge-Intensive Queries in E-commerce Search", arXiv:2602.23620, https://arxiv.org/html/2602.23620v1, verified 2026-09-05. General retrieval research, not menu specific.
- Google Search Central, "Structured Data Markup that Google Search Supports", https://developers.google.com/search/docs/appearance/structured-data/search-gallery, last updated 15 June 2026, verified 2026-09-05.
- Google Search Central, "Local Business (LocalBusiness) Structured Data", https://developers.google.com/search/docs/appearance/structured-data/local-business, last updated 10 December 2025, verified 2026-09-05.
- Schema.org, "RestrictedDiet" and "suitableForDiet", https://schema.org/RestrictedDiet, verified 2026-09-05.





