Technical

If your menu loads in JavaScript, no AI can read it

Why a JavaScript-loaded menu is invisible to ChatGPT, Claude and Perplexity, how to run the disable-JavaScript test, and whether the fix is a template or a rebuild.

Short answer

Almost. If your menu loads in JavaScript, the crawlers behind ChatGPT, Claude and Perplexity fetch the HTML, never run the script, and see an empty container where the menu should be. Google's AI surfaces and Microsoft Copilot do render it. The usual fix is one template change: output the menu as plain HTML and keep the script for interactivity.

The title is nearly true, and the exceptions matter. If your menu loads in JavaScript, the crawlers that feed ChatGPT, Claude and Perplexity request your page, download the script, and never run it. They read whatever HTML the server sent. If the menu is built in the browser, that HTML contains a container with nothing in it. Google's AI Overviews and Microsoft Copilot are the exceptions, because they inherit rendering from Googlebot and Bingbot. Everyone else sees a restaurant with no food.

Why a menu that loads in JavaScript is invisible to most AI crawlers

A crawler is a program that requests a URL and stores what comes back. A browser does the same, then executes the scripts on the page, which is how a modern site fills in its content after the first response arrives. Those are two different operations, and only one of them is cheap.

Vercel and MERJ analysed more than 500 million crawler fetches and found that no major AI crawler executed JavaScript. GPTBot, ClaudeBot and PerplexityBot all downloaded the script files. None of them ran them. So the crawler holds the raw HTML your server produced, and that is the whole of what the model can retrieve.

For a restaurant or cafe this bites in one specific place. The menu is the block most likely to be loaded by script, because it is the block most likely to come from somewhere else: an ordering platform, a reservations widget, a menu-management app, a headless CMS, or a theme feature that fetches items from an API after the page paints. The header and the About page are usually plain HTML. The menu often is not.

That is why a site can look complete to its owner and empty to the crawler. The owner opens it in a browser. The crawler does not.

The disable-JavaScript test

This needs nothing beyond a browser.

  1. Open your menu page in Chrome.
  2. Open DevTools (F12, or right-click and choose Inspect).
  3. Press Ctrl+Shift+P on Windows or Cmd+Shift+P on Mac to open the command palette, type "disable JavaScript", and select it.
  4. Reload the page with DevTools still open.

Now look at what is left. You are checking for four things: dish names, prices, opening hours and the address. If all four are still on the page, your menu is readable and this article is not about you. If the menu area is blank, shows a spinner, or says something like "Loading menu", that is what OAI-SearchBot, Claude-SearchBot and PerplexityBot receive.

A second check catches cases the first one misses. Right-click the page, choose View Page Source, and search for a dish you sell. If the name is in the source, the crawler can read it. If you can only find it through Inspect Element, the browser built it and the crawler never saw it.

Note what this test does not tell you. It does not tell you whether an AI will recommend you, only whether it can read you. Readable is a precondition. The rest is covered in how to get ChatGPT to recommend your business.

Which crawlers render and which do not

CrawlerFeedsRuns JavaScript
GooglebotGoogle Search, AI Overviews, AI ModeYes
BingbotBing, CopilotYes
OAI-SearchBot, GPTBotChatGPTNo
Claude-SearchBot, ClaudeBotClaudeNo
PerplexityBotPerplexityNo

Google and Bing have rendered pages for years, and the AI answer products built on their indexes inherit that. Whatever the reasoning inside each company, the Vercel and MERJ data shows the stand-alone AI crawlers do not render.

Two consequences follow. The first is that "it shows up in Google" is not evidence that it shows up anywhere else. Google will render your menu, index it, and possibly cite it in an AI Overview, while ChatGPT stores a page that says nothing about food. The second is that the fix is not a file or a setting. Google's own documentation states that no special markup or file is needed for its AI surfaces, and nothing you write in robots.txt will make a crawler render. The only lever is what the server sends. If you want to check what your robots.txt is currently doing to the answering crawlers, we wrote a separate guide to AI crawlers and robots.txt.

The stored snippet makes it worse

Search Engine Land instrumented ChatGPT's retrieval and found that the snippet it stores for a page is roughly 200 characters, taken from the text near the H1, frozen at index time and identical for every query. If the text nearest your H1 is "Loading..." or an empty menu container, that is your 200 characters until the page is fetched again. The same study found pages over 4 MB rejected outright, which is worth knowing if your menu page also carries full-resolution photography.

One template change or a rebuild?

This is the decision that matters, and it depends on where the menu content lives rather than on how the site looks.

The menu is in your CMS but drawn by the theme's script

This is the common case on themes and site builders that ship a menu block. The dishes and prices already exist as content on the server. The theme chose to fetch them with a script and draw them in the browser.

The fix is one template change. Output the menu in the page HTML at build or request time, and keep the script for anything interactive, such as filtering by dietary tag. The interactivity survives, the content is in the source, and nothing else on the site moves.

The menu comes from a third-party embed

Ordering platforms and menu apps usually hand you a script tag or an iframe. The content lives on their server and arrives through their JavaScript. Nothing in your HTML describes a single dish.

You do not need to abandon the platform. Add a plain HTML version of the menu on the same page and keep the embed for ordering. The cost is real: two places to update when a price changes. Some platforms offer an export or an API that a developer can pull from at build time, which removes the double maintenance. Ask before you assume they do not.

The menu is an image or a PDF

Strictly this is a format problem rather than a rendering one, and it fails the same test. An image of a menu is unreadable to every crawler in the table above. The fix is typing the menu into HTML. Boring, and it works.

The whole site is a client-rendered single-page app

If the disable-JavaScript test leaves you with a blank white page rather than a blank menu, the menu is a symptom. Your H1, your address and your hours are all invisible to the same crawlers. This is the case where the rebuild conversation is honest, because a template change cannot fix a template that renders nothing.

Even here, a full rebuild is not the only route. Most modern frameworks can server-render or pre-render pages at build time, and a static menu page can sit alongside the app while the larger decision is made.

How to tell which case you are in

Run the disable-JavaScript test. Then ask one question: is the menu the only thing that disappeared?

  • If yes, and the menu is your own content, it is a template change.
  • If yes, and the menu is an embed, it is a template change plus a maintenance habit.
  • If most of the page disappeared, price a rebuild, and put up a plain HTML menu page this week while you decide.

When the change ships, fetch the page with curl and search the raw response for a dish name. That is the test the crawler runs, and it is the only one that counts. What a readable menu does for you from there is covered in restaurant AI recommendations, and the one free report that shows AI grounding queries is in how to track AI search visibility.

Frequently asked questions

Does Google AI Overviews see a JavaScript menu?

Usually, yes. Google's AI surfaces use the same Googlebot as ordinary search, and Googlebot renders JavaScript. Microsoft Copilot inherits the same ability from Bingbot. That is precisely why the problem hides: the menu shows in Google, the owner assumes every AI can see it, and ChatGPT, Claude and Perplexity are quietly reading an empty page.

Will adding schema markup fix it?

No. Schema describes a page, it does not make invisible content visible, and JSON-LD added through a tag manager is itself delivered by script. Ahrefs compared 1,885 pages that added JSON-LD against 4,000 controls and found no measurable citation gain in ChatGPT or AI Mode, and a 4.6 percent decline in AI Overviews. Fix the HTML first.

My menu is on a third-party ordering platform. Do I have to leave it?

No. Keep the embed for ordering and add a plain HTML copy of the menu on the same page, above or beside it. The cost is maintenance in two places when prices change. We think that trade is worth it, because the HTML copy is the only version the ChatGPT, Claude and Perplexity crawlers can read.

How do I know the fix worked?

Run the disable-JavaScript test again and confirm the menu, prices and hours survive. Then fetch the page with curl and search the raw response for a dish name. If it is there, the crawlers can read it. For measurement beyond that, Bing Webmaster Tools' AI Performance report shows Copilot citations and grounding queries. ChatGPT offers nothing comparable.

Want to know how AI models currently describe your business?

We run a free visibility check across ChatGPT, Perplexity, Claude and Google AI Overviews, then show you exactly which signals are missing.

Book a visibility check

Keep reading