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
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
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
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
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
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
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.
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 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" }
}]
}]
}
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
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.
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 ]
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"
}
]
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"
}
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."
}
}]
}
Six well-written FAQ entries — actually useful operational questions, not marketing copy — typically lift AI-search-driven traffic 20-40% within 60 days.
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:
- Copy the block below into a single
<script type="application/ld+json">tag inside your <head>. One tag, not six. - Change the seven fields marked
// EDIT: the restaurant name, address parts (street, city, region, zip), phone, opening hours, and the menu items. - 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
Roma Cucina — Italian Restaurant in Silver Spring
romacucina.example › menu
Italian restaurant in Silver Spring serving hand-rolled pasta and seasonal entrees. Reservations welcome.
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 ]
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.
- 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.
- 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. - 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
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
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
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
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.
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.
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.