How to set up Schema.org for a restaurant on Joomla
Which Schema.org type a restaurant should use, which fields matter, how to link the menu and how to check the result on a Joomla site.
Why a restaurant should publish it
Someone who searches "Italian restaurant near me", or asks ChatGPT where to eat in Belgrade, gets an answer built from whatever the search engine or assistant can find and trust about each place. Your address, hours, cuisine and prices are all on your website, but often in a footer, a photo of the menu or a PDF.
Schema.org markup states those facts in a form a machine reads without guessing. It will not rank you, and it will not make an assistant recommend you. It removes one way of getting your details wrong. For local search I would still put your Google Business Profile first, and make sure the markup on your site agrees with it.
The type to use
Use Restaurant. It is a subtype of FoodEstablishment, which is a subtype of LocalBusiness, so declaring Restaurant brings the parent types with it. A café is CafeOrCoffeeShop, a pub is BarOrPub and a bakery is Bakery.
{
"@context": "https://schema.org",
"@type": "Restaurant",
"name": "Acme Bistro",
"url": "https://acme-bistro.com",
"telephone": "+381 11 123 4567",
"image": "https://acme-bistro.com/images/dining-room.jpg",
"servesCuisine": "Italian",
"priceRange": "$$",
"hasMenu": "https://acme-bistro.com/menu",
"acceptsReservations": true,
"address": {
"@type": "PostalAddress",
"streetAddress": "Knez Mihailova 10",
"addressLocality": "Belgrade",
"addressCountry": "RS",
"postalCode": "11000"
},
"geo": {
"@type": "GeoCoordinates",
"latitude": 44.8178,
"longitude": 20.4569
},
"openingHoursSpecification": [
{
"@type": "OpeningHoursSpecification",
"dayOfWeek": ["Monday", "Tuesday", "Wednesday", "Thursday"],
"opens": "12:00",
"closes": "23:00"
},
{
"@type": "OpeningHoursSpecification",
"dayOfWeek": ["Friday", "Saturday"],
"opens": "12:00",
"closes": "01:00"
},
{
"@type": "OpeningHoursSpecification",
"dayOfWeek": "Sunday",
"opens": "13:00",
"closes": "22:00"
}
]
}The fields that matter
Google's local business documentation lists name and address as required. The rest are optional, but each one answers a question people actually ask about a restaurant.
| Field | What it holds |
|---|---|
name | The restaurant's name, as on the sign |
address | The full postal address |
telephone | A number in international format |
url | The restaurant's website |
image | A photo of the food or the room |
servesCuisine | One or more cuisines, such as "Italian" or "Serbian" |
priceRange | A rough price level, such as $$ |
openingHoursSpecification | Opening hours, day by day |
geo | Latitude and longitude |
hasMenu | The address of the menu page |
acceptsReservations | true, false, or the booking page's address |
Ratings
If you have good reviews on TripAdvisor or Google, the obvious move is to copy the score into aggregateRating. Don't. Google's review guidelines forbid ratings taken from other websites. And since 2019 Google has not shown review stars for a business that marks up reviews of itself on its own site. The stars beside a restaurant in Google come from its Business Profile, so that is where reviews do their work.
Menus
Link the menu page with hasMenu. The older menu property means the same thing.
"hasMenu": "https://acme-bistro.com/menu"Schema.org also has Menu, MenuSection and MenuItem for a full menu with dishes and prices. Google's list of rich results has no menu type, so write that markup for completeness if you like, not for a change in your listing. If your menu is a PDF or a photo, turning it into an ordinary HTML page will help people and crawlers more than any markup.
Sharing previews
When someone shares your site in a chat app or on Facebook, the preview comes from OpenGraph tags, mainly og:title, og:description and og:image. Without them the app picks whatever image it finds, which is often your logo squashed into a square. A photo of a dish or the room at 1200 × 630 pixels works well.
On Joomla with AI Boost
By hand, this means a template override or a custom module, and remembering to edit it every time the hours change.
In AI Boost for Joomla, open the Structured Data screen and choose Restaurant in the "Schema Type" field on the "General and Business" sub-tab. The form then shows the restaurant fields, among them "Cuisine Types", "Price Range", a menu address, reservations and diets. Every type also takes a name, address, phone and an image, and every type but Person takes coordinates.
The "Opening Hours" sub-tab has a weekly schedule with a row per day and a switch to mark a day closed, with holiday and seasonal hours beside it. No hours are published until at least one day has times.
Once you switch the output on and fill in "Organisation Name", every indexable page carries your restaurant in its JSON-LD block. It includes servesCuisine, priceRange, hasMenu, acceptsReservations, suitableForDiet and openingHoursSpecification, wherever you filled them in.
It publishes no aggregateRating and no Menu or MenuItem markup. The menu goes out as an address only.
To check the result, open your home page, view the source and find the application/ld+json block. Then run the page through Google's Rich Results Test. A clean result means the markup is valid and eligible. Then keep the hours current, because stale hours in markup are worse than none.