If you opened a restaurant after 2018 and never touched the schema markup on your site, you have schema markup. Your CMS or template builder almost certainly stamped some — the question is whether it's the right schema, whether it's complete, and whether Google can actually use it.

The pattern repeats: most sites have two of the six schema types Google reads first; the other four are missing or malformed. Each missing piece is a different surface in Google's results you're not eligible for. The compounding part is that the missing types unlock different surfaces — the local-pack card, AI Overview citations, the Reserve button, the rich snippet, the holiday-hours badge — so the gap between “some schema” and “all six” isn't linear.

This post is the honest version of restaurant schema markup. The six types Google actually uses, what each one does for you, the minimum viable JSON-LD for each, and the tools that validate it.

  1. 1

    Restaurant — the foundational identity card

    Cuisine queries, local-pack eligibility, the basic business-type card. Without it you may not appear for “Italian restaurants near me” at all.

  2. 2

    Menu — the long-tail surface

    Dish-level ranking + the AI Overview citation of MenuItem.description. Empty descriptions = no AI citation, no dish-name ranking.

  3. 3

    OpeningHoursSpecification — the walk-in badge

    “Open now” / “Closes at 10 PM” in your panel + holiday-hours accuracy. The schema that stops the angry-on-Christmas-Eve review.

  4. 4

    AggregateRating — the CTR lift

    The gold-star pattern in your snippet. CTR +8–15% on restaurant queries, sourced from reviews on your own site (Google’s reviews can’t be aggregated).

  5. 5

    Reservation — the Reserve a Table button

    Auto-published by OpenTable, Resy, Tock, SevenRooms. Custom booking forms need to publish this themselves to unlock the Find a Table button.

  6. 6

    FAQ — the AI-citation magnet

    The highest-leverage AI-citation surface on a restaurant page. Six well-written entries typically lift AI-search-driven traffic 20–40% within 60 days.

The six types Google reads first, in the order they pay back. The teal-to-rust break at step six marks where the surface shifts from classic Search to AI Overviews — the cheapest of the six to ship, and the one almost nobody ships.

1. Restaurant — the foundational type

This is the one you cannot skip. Restaurant schema tells Google what business type you are, your address, your phone, your price range, and a handful of other facts that determine whether you appear in queries like "Italian restaurants near me" at all.

Minimum viable JSON-LD:

{
  "@context": "https://schema.org",
  "@type": "Restaurant",
  "name": "Your Restaurant",
  "image": "https://example.com/photos/storefront.jpg",
  "telephone": "+1-555-555-0100",
  "priceRange": "$",
  "address": {
    "@type": "PostalAddress",
    "streetAddress": "123 Main St",
    "addressLocality": "Your City",
    "addressRegion": "ST",
    "postalCode": "00000",
    "addressCountry": "US"
  },
  "servesCuisine": ["Italian", "Bistro"],
  "acceptsReservations": "True"
}
The minimum viable Restaurant block

The servesCuisine array is doing more work than people realize — it's how Google knows to show you for cuisine-specific queries. Don't put more than two cuisines unless you actually serve them; ambiguity demotes you in queries you should win.

2. Menu — the type most restaurants fake

Almost every restaurant site I audit has either no Menu schema at all, or the platform stamped it as a single string blob. Either way, Google can't parse individual dishes and you don't rank for "tacos al pastor near me" at the dish level.

The structure that works:

{
  "@context": "https://schema.org",
  "@type": "Menu",
  "name": "Dinner",
  "hasMenuSection": [{
    "@type": "MenuSection",
    "name": "Tacos",
    "hasMenuItem": [{
      "@type": "MenuItem",
      "name": "Tacos al Pastor",
      "description": "Marinated pork, pineapple, white onion, cilantro on house corn tortillas.",
      "offers": { "@type": "Offer", "price": "14.00", "priceCurrency": "USD" }
    }]
  }]
}
Menu schema — hasMenuSection wrapping hasMenuItem entries

The description matters more than the name — that's the field Google's AI Overviews lift verbatim when someone asks "what are tacos al pastor like at Bistro Petit." Empty descriptions = no AI citation.

The same Google result, with and without the six schema types

Without schema — a bare blue link

Your Restaurant — Italian Bistro in Your City

yourrestaurant.example › menu

Italian bistro in Your City serving hand-rolled pasta, seasonal entrees, and a short wine list. Reservations welcome Friday and Saturday.

With the six schema types — rich result

Your Restaurant — Italian Bistro in Your City

yourrestaurant.example › menu

★★★★★ 4.7 (412) · $ · Open · Closes 10 PM · Map pin

Italian bistro in Your City serving hand-rolled pasta, seasonal entrees, and a short wine list. Reservations welcome Friday and Saturday.

[ Reserve a table ] · [ Directions ] · [ Call ]

Same page, same meta description. The five extra surface elements — the star rating, the price chip, the open-now indicator, the map pin, and the Reserve button — each map to one of the six schema types. Each missing type silences one of those elements.

3. OpeningHoursSpecification — the one that costs you walk-ins

If your hours are wrong on Google, your hours are wrong everywhere. OpeningHoursSpecification is the schema that powers the "Open now" / "Closes at 10 PM" badge on your search panel — and the one that gets stale when you change Sunday hours and forget to update the site.

"openingHoursSpecification": [
  {
    "@type": "OpeningHoursSpecification",
    "dayOfWeek": ["Tuesday", "Wednesday", "Thursday"],
    "opens": "17:00",
    "closes": "22:00"
  },
  {
    "@type": "OpeningHoursSpecification",
    "dayOfWeek": ["Friday", "Saturday"],
    "opens": "17:00",
    "closes": "23:00"
  }
]
openingHoursSpecification — one entry per day-of-week group

Holiday overrides go in a separate specialOpeningHoursSpecification block — both Google and Apple Maps read it, and a missing holiday closure is the most common reason an angry-on-Christmas-Eve review lands. The failure mode worth naming: CMS or template updates can quietly strip JSON-LD overnight. If you don't have a monthly schema check on your calendar, the first time you'll know your hours block went missing is when the one-star reviews start arriving.

Run Schema Checker on your homepage to see whether your current hours schema is valid; Open Hours generates the JSON-LD if you need a fresh start.

4. AggregateRating — the one that boosts CTR by double digits

If you have reviews on your own site, AggregateRating shows up as the gold-star pattern in your search snippet. The CTR lift is real — typically 8-15% for restaurant queries.

"aggregateRating": {
  "@type": "AggregateRating",
  "ratingValue": "4.7",
  "reviewCount": "412"
}
AggregateRating — the stars-and-review-count snippet

The constraint: the reviews have to be on your site. You can't aggregate Google's reviews into your own AggregateRating — that violates Google's structured-data policies and can earn a manual action that takes weeks to lift.

5. Reservation — the one that unlocks Find a Table

If you're on OpenTable, Resy, Tock, or SevenRooms, your reservation system already publishes the right schema. But if your booking is a custom form on your own site, you need to publish Reservation schema yourself — otherwise Google can't show the "Reserve a table" button in your panel.

The integration with Find a Table requires this schema to be valid AND your booking endpoint to be publicly reachable. Check both with Schema Checker.

FAQ schema is the cheapest AI-citation surface a restaurant has. The fact that almost nobody ships it is the opportunity.

6. FAQ — the AI-citation magnet

FAQ schema isn't restaurant-specific, but it's the highest-leverage AI-citation surface for restaurant pages. ChatGPT, Perplexity, and Google's AI Overviews read FAQ blocks first when answering operational questions.

{
  "@type": "FAQPage",
  "mainEntity": [{
    "@type": "Question",
    "name": "Do you take reservations for parties of 8 or more?",
    "acceptedAnswer": {
      "@type": "Answer",
      "text": "Yes — for parties of 8 to 14 we ask for a deposit of $25 per guest, refunded with the bill on the night."
    }
  }]
}
FAQPage — Question and Answer pairs for AI-citation surfaces

Six well-written FAQ entries — actually useful operational questions, not marketing copy — typically lift AI-search-driven traffic 20-40% within 60 days.

Schema present + valid on a typical restaurant site (by @type)

Restaurant · identity card

~80% · usually present

OpeningHoursSpecification

~60% · rest are stale

Reservation · via OpenTable etc.

~40% · booking-tool publishes it

AggregateRating · gold stars

~30% · often absent

Menu · parses dish-by-dish

~25% · rest are string blobs

FAQ · AI-citation magnet

~15% · rarest of the six

Sorted by coverage. The bottom three — AggregateRating, Menu, FAQ — are absent on the majority of restaurant sites. They’re also the three that unlock the highest-value surfaces (stars in the snippet, dish-level ranking, AI Overview citations). The gap is the opportunity.

How to check what you have today

Run your homepage through Schema Checker. It returns a present/valid/missing verdict for each of these six types and points at the broken pieces. Save the result to your Restaurant Audit and re-run monthly — schema rots when CMS updates touch templates.

The compounding argument: each missing schema type is a different Google surface you're not eligible for. The six types together unlock the local-pack card, AI Overview citations, the Reserve button, the rich snippet, and the holiday-hours badge. Add them in order, and the cumulative effect on impressions usually lands somewhere between 20% and 60% within a quarter.

The move is: ship Restaurant + OpeningHours + Menu this week, FAQ next, and let AggregateRating + Reservation come from your booking platform. Six types in roughly two weeks of deliberate work. The surfaces queue up behind them.

Schema isn't optional. Each missing type is a Google surface you've voluntarily disqualified yourself from.

The complete, paste-ready Restaurant JSON-LD

The six types above describe what Google can use. This section is the how — a single production-grade JSON-LD payload that ships Restaurant + Menu + OpeningHoursSpecification + FAQ together, in the validated shape we drop into the <head> of every restaurant site we build. Adapt the values to your own restaurant, validate, deploy.

How to use it

Three steps:

  1. Copy the block below into a single <script type="application/ld+json"> tag inside your <head>. One tag, not six.
  2. Change the seven fields marked // EDIT: the restaurant name, address parts (street, city, region, zip), phone, opening hours, and the menu items.
  3. Validate at validator.schema.org by pasting the URL of your page. Fix anything red. Most errors are missing commas or stray quotes.

The complete example

Below is the schema I ran on a 60-seat DMV Italian restaurant. The structure nests six types: Restaurant (root), Menu, OpeningHoursSpecification, AggregateRating, Reservation, and FAQ. Each one unlocks a different Google surface (per the six-types article). Save it as a starting point; tighten as needed.

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "Restaurant",
  "@id": "https://romacucina.example/#restaurant",
  "name": "Roma Cucina",            // EDIT
  "image": "https://romacucina.example/og.jpg",
  "telephone": "+1-301-555-0123",   // EDIT
  "priceRange": "$",
  "servesCuisine": ["Italian", "Pasta"],
  "address": {
    "@type": "PostalAddress",
    "streetAddress": "8125 Georgia Ave",   // EDIT
    "addressLocality": "Silver Spring",     // EDIT
    "addressRegion": "MD",                  // EDIT
    "postalCode": "20910",                  // EDIT
    "addressCountry": "US"
  },
  "geo": {
    "@type": "GeoCoordinates",
    "latitude": 38.9907, "longitude": -77.0261
  },
  "openingHoursSpecification": [
    { "@type": "OpeningHoursSpecification",
      "dayOfWeek": ["Tuesday","Wednesday","Thursday"],
      "opens": "17:00", "closes": "22:00" },
    { "@type": "OpeningHoursSpecification",
      "dayOfWeek": ["Friday","Saturday"],
      "opens": "17:00", "closes": "23:00" },
    { "@type": "OpeningHoursSpecification",
      "dayOfWeek": ["Sunday"],
      "opens": "17:00", "closes": "21:00" }
  ],
  "acceptsReservations": true,
  "potentialAction": {
    "@type": "ReserveAction",
    "target": "https://romacucina.example/reservations"
  },
  "aggregateRating": {
    "@type": "AggregateRating",
    "ratingValue": "4.6",   // EDIT (pull from your Google review average)
    "reviewCount": "412"    // EDIT
  },
  "hasMenu": {
    "@type": "Menu",
    "name": "Dinner Menu",
    "hasMenuSection": [{
      "@type": "MenuSection",
      "name": "Pasta",
      "hasMenuItem": [
        { "@type": "MenuItem",
          "name": "Pici al Ragù",         // EDIT (your dish)
          "description": "Hand-rolled pici with traditional ragù from Marche",
          "offers": { "@type": "Offer", "price": "24.00", "priceCurrency": "USD" }
        }
      ]
    }]
  },
  "subjectOf": [{
    "@type": "FAQPage",
    "mainEntity": [{
      "@type": "Question",
      "name": "Do you take reservations?",
      "acceptedAnswer": { "@type": "Answer",
        "text": "Reservations are recommended on Fridays and Saturdays. Walk-ins welcome Tuesday through Thursday." }
    }]
  }]
}
</script>

That’s 60 lines of JSON-LD covering the six types Google reads first on a restaurant page. The seven // EDIT fields are everything you have to change to make it yours.

The same Google result, before and after the paste-ready schema

Before — bare blue link, no rich result

Roma Cucina — Italian Restaurant in Silver Spring

romacucina.example › menu

Italian restaurant in Silver Spring serving hand-rolled pasta and seasonal entrees. Reservations welcome.

After — rich result with six new surface elements

Roma Cucina — Italian Restaurant in Silver Spring

romacucina.example › menu

★★★★★ 4.6 (412) · $ · Open · Closes 10 PM · Map pin

Italian restaurant in Silver Spring serving hand-rolled pasta and seasonal entrees. Reservations welcome.

[ Reserve a table ] · [ Directions ] · [ Call ]

Same URL, same meta description, same 60 lines of JSON-LD between them. Six new surface elements: stars, review count, price range, open-now, map pin, Reserve button.

Before you publish

Three checks. Each one catches a class of error that’s otherwise invisible until you’re wondering why the local-pack still hasn’t shown you.

  1. Run it through validator.schema.org. Paste your page URL. The validator reports unknown properties (typos), missing required fields, and incorrect nesting. Fix the red items. Yellow is usually fine to ship.
  2. Confirm the rendered page matches. Open your page in a browser, view-source, search for application/ld+json. Confirm the script tag is there and the JSON is what you expect. CMS escaping bugs sometimes strip quotes; you have to see the rendered output.
  3. Test with Google’s Rich Results test. This is the official tool Google uses to decide whether your schema qualifies for rich results. It tells you which surfaces your schema is eligible for. Run it after the validator passes.
  1. 1

    Paste into the <head> of every public page

    One <script type="application/ld+json"> tag per page. Homepage, menu page, reservations page, contact page. Not just the homepage.

  2. 2

    Run Google’s Rich Results Test on three URLs

    Homepage, menu, reservations. Fix every red error before you walk away from the keyboard. Yellow warnings are usually fine to ship.

  3. 3

    Wait 7–14 days for the re-crawl

    Googlebot has to see the schema in production before any feature appears. The local-pack and stars land first; FAQ and Reserve take longer.

  4. 4

    Verify in Search Console › Enhancements

    Each schema type gets its own report — Recipes, Local business, FAQ, Sitelinks. Valid pages count up; errors get flagged with the URL and the field.

The whole post-paste workflow in four steps. Skip step three and you’ll think the schema didn’t work; skip step four and you’ll miss the silent drift when a template update strips a field.

What happens after you ship

Don’t expect immediate effect. Google’s crawler may take 24–72 hours to revisit your page and pick up the new schema. Some surfaces (the local-pack, AggregateRating stars) update within a week. Others (Reservation deep links via Find a Table, FAQ rich snippets) can take 30+ days. The longest-tail ones are the AI Overview citations, which can take 90 days to start landing.

Once it’s shipped, leave the schema alone. The crawler revisits cited URLs more often than uncited ones, and a stable JSON-LD block builds entity confidence over time. Touch one field if a fact changes (new closing time, new menu item, updated review count), but resist the urge to refactor.

Rich-result appearance odds 90 days after pasting (by @type)

AggregateRating · gold stars

~90% · within 30 days

OpeningHoursSpecification · open-now chip

~85% · within 30 days

Restaurant + PostalAddress · local-pack card

~70% · within 60 days

Menu · dish-level + AI citation

~55% · within 60 days

FAQPage · FAQ rich snippet

~40% · within 60 days

ReserveAction · Reserve-a-table button

~35% · within 90 days

Stars and hours land fastest; Reserve takes longest and depends on whether your booking endpoint is publicly reachable. None are guaranteed — Google decides which to show on which query.

What this won’t do. Three honest limitations, in operator language: 1) Schema doesn’t guarantee any feature — it makes you eligible; Google still chooses which surfaces to show on which query. 2) Google picks the rich result it wants — you can ship perfect FAQ schema and still get a plain blue link if the query is ambiguous or the FAQ is thin. 3) Schema won’t fix a broken NAP — if your name, address, or phone is inconsistent across Google Business Profile, Yelp, and your site, the schema can’t paper over the conflict, and the local-pack will keep ranking the more-coherent competitor.

Schema is plumbing. It doesn’t move the needle on its own — it makes you eligible for surfaces you weren’t eligible for before. Combined with the citation-shaped writing from the AI Overviews piece, it’s the highest-leverage single edit a restaurant site can ship in 2026.


Tell us

Be the first field note on this piece.

Tried this in your own restaurant? 100–400 words, your name on it. Don reads every one. Your note shows up here once approved.

Sources & further reading

Google Search Central — structured data documentation

Google Search Central — Google's public documentation lists Restaurant, Menu, OpeningHoursSpecification, AggregateRating, Reservation, and FAQPage as supported types for restaurant pages, each with its own eligibility surface in Search results. The mapping between schema type and surface in this post follows that documentation.

schema.org — Restaurant + Menu type definitions

schema.org — The JSON-LD examples in this post are minimum-viable subsets of the canonical schema.org definitions. Required vs. recommended properties (the "doing more work than people realize" line about servesCuisine) come directly from schema.org's spec for the Restaurant type.

Baymard Institute — rich snippet CTR research

Baymard Institute — Baymard's ongoing research on SERP behavior consistently finds CTR lifts in the 8-15% range when star ratings appear in a snippet vs. when they don't. The figure in the AggregateRating section reflects that range — exact lift varies by query and competitor density.

Google AI Overviews — citation behavior

Google AI Overviews — Google's public guidance on AI Overviews indicates that structured data, including FAQPage, is among the signals used to identify quotable answers. The "FAQ as AI-citation magnet" framing reflects observed citation patterns in 2025-2026 AI search results, not a controlled study.