2026-03-25

Menu Schema Markup That Is Actually Worth the Effort

Full item-level menu schema is a maintenance burden most restaurants abandon. Which parts of the markup earn their keep, and which ones you can skip.

Most restaurant menu schema gets written once, by an agency, during a website build, and is wrong within four months. The kitchen raises a price, drops a dish, or changes a description, and nobody updates a JSON block buried in the page template because nobody remembers it is there.

That is the actual failure mode, and it should shape how much of this you take on. The value of structured data comes entirely from it being true. A markup file confidently declaring a price you stopped charging last spring is worse than an empty page, because it presents an out-of-date number in the exact format machines trust most.

So the question is not whether to do menu schema. It is which parts survive contact with a working kitchen.

The one line that does most of the work

Your restaurant should have a Restaurant entity in JSON-LD describing the business itself. On that entity, one property called hasMenu points at the URL of your menu page.

{
  "@context": "https://schema.org",
  "@type": "Restaurant",
  "name": "Salvo's Pizza",
  "servesCuisine": "Neapolitan pizza",
  "hasMenu": "https://example.com/menu",
  "acceptsReservations": "False",
  "telephone": "+15555550142"
}

That is roughly ninety percent of the practical benefit for maybe two percent of the effort. It resolves the ambiguity that causes the most trouble, which is a machine not knowing which of your eleven pages is the menu. Sites routinely have a menu page, a catering page, a PDF, and an ordering page from a third party, and without the pointer, a crawler picks by guesswork.

The rest of that entity, the address, the hours, the phone number, belongs to the broader business markup covered in Restaurant and LocalBusiness structured data. Get that right before touching anything menu-specific.

Where full item markup stops paying

The schema vocabulary supports describing a menu in complete detail: Menu contains MenuSection, each section contains MenuItem, each item carries a name, description, price, currency, and dietary restriction flags.

It is well designed. It is also a second copy of your menu, living in your page markup, with no connection to the system where prices actually change. Every price increase now requires two edits, and the second one is invisible, so it does not happen.

If you have a menu that genuinely does not move, a fixed core of thirty items with prices that change once a year, item markup is defensible and not much work. If your menu is seasonal, or your specials rotate weekly, or your prices move with cheese and beef costs, marking up individual items creates an obligation you will not meet. Skipping it is the honest choice, not the lazy one.

The middle path is to mark up the stable core and omit everything else. A Menu with three sections covering the dishes that have been on the board for years, and no attempt to represent the rotating specials. Partial and accurate beats complete and stale.

The one item-level field with an obvious payoff

Dietary flags. The suitableForDiet property attaches values like GlutenFreeDiet or VeganDiet to an item, and unlike price, it almost never changes once set.

That matters because dietary questions are among the most common things people ask an assistant about a restaurant, and among the most consequential to get wrong. A person with celiac disease asking whether you have a gluten-free option is making a decision with real stakes, and a machine that has to infer the answer from review text will sometimes infer wrong.

Marking the four or five items that carry a stable dietary attribute is an afternoon of work that does not need revisiting. It is the highest ratio of value to maintenance anywhere in menu markup, and it is routinely skipped in favor of exhaustively marking up prices that will be wrong by summer.

Structured data does not fix an unreadable menu

This is the sequencing error that wastes the most money. An agency adds JSON-LD to a page whose visible content is a PDF embed or an exported image, and reports the markup as complete.

A machine now has a label saying "this is a menu" attached to a page containing no readable menu. The markup is technically valid and practically useless. What a crawler needs is the item names, descriptions, and prices present as text in the HTML, which is the argument made in full in menu page SEO for restaurants.

Order of operations: menu as HTML text, then hasMenu, then dietary flags, then item-level markup if and only if the menu is stable enough to maintain. Anyone proposing to start at the end is selling deliverables rather than results.

The generated-markup shortcut, and its catch

Some online ordering platforms and website builders generate menu structured data from the menu already stored in their system. When that is on offer, take it, because it solves the maintenance problem outright. The markup regenerates when the menu changes, and the second copy stops being a second copy.

The catch is that it only reflects what lives in that platform. If your ordering platform carries a trimmed version of your menu, the markup describes the trimmed version, and a machine now believes your dining room menu is eleven items long. Compare the generated output against your printed menu once before trusting it.

Ask your vendor directly whether they emit menu markup and where it comes from. It is a question with a short answer, and it decides whether the rest of this page is work you have to do by hand.

Validate it, then set a reminder

Google publishes a rich results test and schema.org has its own validator. Run the page through one after any change. Both will catch malformed JSON and unrecognized properties, neither will tell you a price is wrong, which is the error that actually matters.

Only you can catch that, so the maintenance habit is what to build. Every time prices change, whoever updates the menu page checks whether structured data carries prices too. If that person is not going to remember, that is your answer about whether to mark up prices at all.

The same reasoning applies to FAQ schema on restaurant pages, where the failure mode is an answer about delivery hours that stopped being true when you changed your closing time.

How to tell whether any of it worked

Do not measure this by whether the markup validates. Measure it by asking assistants what a specific dish costs and whether you have a gluten-free option, then checking their answers against your actual menu.

If they answer correctly and specifically, your menu is legible, and it is worth checking again after your next price change to see whether the correctness held. If they hedge or quote an aggregator, the markup is not the problem and adding more of it will not help. That distinction, between a legibility problem and a source problem, is the one worth carrying into every other piece of answer engine optimization work you take on.

More on ai search & local seo

All ai search & local seo articles

Frequently asked questions

Hear it answer a real call.

Call the demo line and order like a customer would, or book time and we'll walk your team through it.