XooCode(){

Menu

Menu is a CreativeWork subtype for structured restaurant menus. It has 2 properties of its own: hasMenuSection (grouping items by course or category) and hasMenuItem (individual dishes). Google reads Menu markup for restaurant knowledge panels and local search results, showing menu items with prices directly in search.

The type hierarchy is Thing → CreativeWork → Menu. Use it on the menu page of a Restaurant or FoodEstablishment. The Restaurant's hasMenu property should point to this Menu entity. MenuSection groups items by course ("Appetizers", "Mains", "Desserts"), and each MenuItem has a name, description, and offers with pricing.

Full example of schema.org/Menu json-ld markup

The markup is verified as valid with Rich Results Test from Google.

Highlight legend:Required by GoogleRecommendedOptional
schema.org/Menu
<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "Menu",
  "@id": "https://dunmoregrill.com/menu#menu",
  "name": "The Dunmore Grill - Dinner Menu",
  "url": "https://dunmoregrill.com/menu",
  "hasMenuSection": [
    {
      "@type": "MenuSection",
      "name": "Appetizers",
      "hasMenuItem": [
        {
          "@type": "MenuItem",
          "name": "Loaded Nachos",
          "description": "Tortilla chips, cheddar, jalapeños, sour cream, guacamole",
          "offers": { "@type": "Offer", "price": "12.50", "priceCurrency": "USD" }
        },
        {
          "@type": "MenuItem",
          "name": "Soup of the Day",
          "description": "Ask your server for today's selection",
          "offers": { "@type": "Offer", "price": "8.00", "priceCurrency": "USD" }
        }
      ]
    },
    {
      "@type": "MenuSection",
      "name": "Mains",
      "hasMenuItem": [
        {
          "@type": "MenuItem",
          "name": "Dunmore Burger",
          "description": "8oz beef patty, cheddar, lettuce, tomato, house sauce, brioche bun. Served with fries.",
          "offers": { "@type": "Offer", "price": "18.00", "priceCurrency": "USD" }
        },
        {
          "@type": "MenuItem",
          "name": "Grilled Atlantic Salmon",
          "description": "Pan-seared salmon fillet, seasonal vegetables, lemon butter sauce",
          "offers": { "@type": "Offer", "price": "24.00", "priceCurrency": "USD" }
        }
      ]
    }
  ]
}
</script>

hasMenuSection

hasMenuSection takes MenuSection objects for grouping menu items by category. Each MenuSection has a name ("Appetizers") and its own hasMenuItem array. This creates a two-level structure: Menu → MenuSection → MenuItem.

hasMenuItem

hasMenuItem takes MenuItem objects. Each MenuItem needs name, description, and offers with a price. Google displays menu item names and prices in local search results. If your menu has sections, put hasMenuItem on each MenuSection rather than on the Menu directly.

Minimal valid version

The smallest markup that still produces a valid Menu entity. Use it as the floor. Reach for the advanced example above when you want search engines and AI agents to understand more about your content.

schema.org/Menu (minimal)
<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "Menu",
  "name": "The Dunmore Grill - Dinner Menu",
  "hasMenuItem": [
    { "@type": "MenuItem", "name": "Dunmore Burger", "offers": { "@type": "Offer", "price": "18.00", "priceCurrency": "USD" } }
  ]
}
</script>

Google rich results this unlocks

Markup matching this example makes your page eligible for the following Google Search rich results. The primary target drives the required / recommended property classification in the advanced code block above.

Common Menu mistakes

Mistakes that pass validation but silently fail to earn rich results or mislead consumers walking the graph. Avoid these and your markup will be ahead of most sites in the wild.

  1. 01

    Menu items without prices

    Wrong
    MenuItem with name and description but no offers
    Right
    "offers": { "@type": "Offer", "price": "18.00", "priceCurrency": "USD" }

    Google displays menu item prices in local search results. Without offers, the menu shows item names but no prices, which is less useful to diners deciding where to eat.

  2. 02

    Flat list instead of sections

    Wrong
    Menu with 30 MenuItems in a single hasMenuItem array
    Right
    Group items into MenuSections by course: Appetizers, Mains, Desserts

    MenuSections make the menu navigable. Google can display section headers in search results. A flat list of 30 items with no grouping is harder for both users and search engines to parse.

About the example data

The dinner menu for The Dunmore Grill, structured by course. The Restaurant example references this Menu via hasMenu.

Comments

Loading comments...

Leave a comment