What schema markup does for a local business
Your website is written for people. Schema markup is the same facts written for machines: your business name, address, phone number, hours, the services you offer and the questions you answer. It sits in the page as a block of code that visitors never see.
This guide is part of our work on AI search optimization. It shows the three types most local service businesses need (LocalBusiness or a subtype, Service and FAQPage), gives a complete example you can adapt, and explains how to test it.
First, an honest limit. Google says it does not require special schema to appear in AI Overviews or AI Mode: “There’s also no special schema.org structured data that you need to add.” Its AI optimization guide adds that structured data is not required for AI search and that you should keep using it for rich result eligibility. We found no statement from OpenAI or Perplexity that schema affects their answers. So think of schema as insurance against misreading. It states your facts without ambiguity. It does not promise a ranking or a mention.
JSON-LD vs microdata: which format to use
Schema.org vocabulary can be written three ways: JSON-LD, Microdata and RDFa. Google supports all three and recommends JSON-LD. JSON-LD lives in one <script type="application/ld+json"> block, separate from the page layout, so it is easier to write, test and fix than microdata scattered through the HTML. Use JSON-LD.
The three types a local service business needs
1. LocalBusiness, or a subtype. This is the business itself. Schema.org has specific subtypes, for example Dentist, Plumber, HVACBusiness, HairSalon and LegalService. Google’s documentation says to use the most specific subtype available. In Schema.org, Dentist sits under both LocalBusiness and MedicalBusiness, so it inherits properties like areaServed, priceRange, openingHoursSpecification and sameAs.
Google lists name and address as required for local business markup and recommends geo, openingHoursSpecification, priceRange, telephone and url. Include as many accurate properties as you can.
2. Service. One per main service, with a provider, serviceType, areaServed and, if you publish a price, an offers entry. Schema.org lists these properties for Service.
3. FAQPage. Questions and answers that are visible on the page. More on its status below.
Complete JSON-LD example: Example Dental of Brookline
The business below is fictional, written only to show the structure. The address, phone number, coordinates and prices are made up. Replace every value with your own, and only publish facts that are true and visible on your page.
{
"@context": "https://schema.org",
"@graph": [
{
"@type": "Dentist",
"@id": "https://www.example.com/#business",
"name": "Example Dental of Brookline",
"url": "https://www.example.com/",
"telephone": "+1-617-555-0100",
"image": "https://www.example.com/images/office-front.jpg",
"description": "General and family dentistry in Brookline, Massachusetts. This is a fictional example business.",
"priceRange": "$$",
"address": {
"@type": "PostalAddress",
"streetAddress": "100 Example Street, Suite 2",
"addressLocality": "Brookline",
"addressRegion": "MA",
"postalCode": "02446",
"addressCountry": "US"
},
"geo": {
"@type": "GeoCoordinates",
"latitude": 42.33176,
"longitude": -71.12116
},
"openingHoursSpecification": [
{
"@type": "OpeningHoursSpecification",
"dayOfWeek": ["Monday", "Tuesday", "Wednesday", "Thursday"],
"opens": "08:00",
"closes": "17:00"
},
{
"@type": "OpeningHoursSpecification",
"dayOfWeek": "Saturday",
"opens": "09:00",
"closes": "13:00"
}
],
"areaServed": [
{ "@type": "City", "name": "Brookline" },
{ "@type": "City", "name": "Boston" },
{ "@type": "City", "name": "Newton" }
],
"sameAs": [
"https://www.facebook.com/exampledentalbrookline",
"https://www.yelp.com/biz/example-dental-of-brookline"
]
},
{
"@type": "Service",
"@id": "https://www.example.com/services/dental-cleaning/#service",
"name": "Dental cleaning and exam",
"serviceType": "Dental cleaning",
"description": "A routine cleaning and exam for adults and children. Example text for illustration.",
"url": "https://www.example.com/services/dental-cleaning/",
"provider": { "@id": "https://www.example.com/#business" },
"areaServed": { "@type": "City", "name": "Brookline" },
"offers": {
"@type": "Offer",
"priceCurrency": "USD",
"price": "120.00",
"description": "Example price for illustration only. Insurance and X-rays billed separately."
}
},
{
"@type": "FAQPage",
"@id": "https://www.example.com/services/dental-cleaning/#faq",
"mainEntity": [
{
"@type": "Question",
"name": "Do you accept new patients?",
"acceptedAnswer": {
"@type": "Answer",
"text": "Yes. We accept new patients Monday to Thursday and on Saturday mornings. Book online or call +1-617-555-0100."
}
},
{
"@type": "Question",
"name": "How long does a cleaning and exam take?",
"acceptedAnswer": {
"@type": "Answer",
"text": "Plan on about an hour for a first visit. Return visits are usually shorter."
}
}
]
}
]
}
How the example is built
- One
@graph, three entities. The Dentist, the Service and the FAQPage are separate entities in one block, so you paste one script. @idlinks them. The Service points to the business with"provider": { "@id": "https://www.example.com/#business" }. That tells a reader the cleaning is offered by this dentist, without repeating the whole business record.- Dentist, not just LocalBusiness. The subtype says more. If no subtype fits, use LocalBusiness.
areaServedlists real places. Use the towns you actually serve, not every town within 50 miles.- Hours use two blocks. Monday to Thursday share one block, Saturday gets its own. Days you are closed are left out. Google’s documentation covers special cases such as seasonal closures.
priceis one honest number. If your price varies, say so in the visible text, and only mark up a price you can stand behind. This price is made up for the example.
Where to put it
Put the script in the <head> or the <body> of the page it describes. Put the business entity on your home page and contact page, put each Service block on its own service page, and put the FAQPage on the page where those questions are shown. Google’s guidelines say to place markup on the page it describes. Do not copy a Brookline block onto a page about a different service or a different town.
Rules that keep you out of trouble
Google’s general structured data guidelines are short and strict:
- Mark up only what visitors can see. The FAQ answers in the example must also appear on the page as text.
- Do not mark up fake or irrelevant content. Fake reviews are called out by name.
- Keep patient and customer details out. Markup describes the business, never a named patient or customer. Clinics should also keep health information out of any public code.
- Keep it current. An old phone number or old hours in markup is worse than none.
- Do not block the page. The page must not be blocked by robots.txt, a
noindextag or a login, or Google cannot read the markup.
One more rule from the local business documentation: aggregateRating and review are listed for sites that collect reviews of other local businesses. Do not add star ratings to your own business markup with reviews you collected yourself and expect stars in search. We left both out of the example.
FAQ schema in 2026: what still works
Google restricted FAQ rich results to well-known government and health sites in 2023, announced their deprecation in May 2026, and removed the FAQ documentation in June 2026. FAQ rich results stopped appearing in Google Search on May 7, 2026.
So what should you do with FAQPage? Two things.
- Keep a visible FAQ section on your service pages. Customers read it, and it puts short, direct answers in plain text for any system to quote.
- Keep or add FAQPage markup only if it matches that visible text exactly. The Schema.org type remains valid, and it costs little. Do not expect an FAQ rich result, and do not remove good FAQ content because the rich result is gone.
For a longer look, see FAQ, review and breadcrumb schema.
How to add schema markup to your site
On a custom or static site. Paste the <script type="application/ld+json"> block into the page template, and fill in values for each page.
On WordPress. Use an SEO or schema plugin that outputs LocalBusiness data, or add the script through a header and footer code tool or your theme. Plugins often write generic types, so check the output. Make sure two plugins are not writing duplicate or conflicting blocks.
On a site builder. Most builders have a code injection or custom code field for a page or the site header. Paste the script there, then test the published page.
If you would rather not manage it, our website projects include schema for your business, services and questions, matched to the visible page text.
How to test schema markup
Test twice, with two tools that answer different questions.
1. Google’s Rich Results Test
The Rich Results Test checks whether a page’s structured data can produce Google rich results. It tests publicly accessible pages. You can enter a URL, or paste code into the code tab, which is useful before a page is live. You can run it as Google’s smartphone or desktop crawler.
Fix critical errors. Google’s local business documentation recommends running the test, then using the URL Inspection tool in Search Console to confirm Google can access the page, and confirming it is not blocked by robots.txt, noindex or a login.
2. The Schema.org validator
The Schema Markup Validator is a general-purpose checker from Schema.org. Per Search Engine Journal’s report at its launch, it checks structured data against Schema.org properties, including ones Google does not use for rich results, and flags syntax errors. It reads JSON-LD, RDFa and Microdata. It has a “Fetch URL” option and a “Code snippet” option.
Use it for FAQPage and for anything outside Google’s supported features. Because Google no longer shows FAQ rich results, this is the better check for the FAQPage entity in the example.
What to look for
- Syntax errors. A missing comma or a stray quote breaks the whole block.
- Wrong types. Dentist should show as Dentist, not just Thing.
- Missing required fields. For local business:
nameandaddress. - Warnings are not failures. A warning for a recommended property you chose not to add is fine.
- Mismatch with the page. Compare the markup with the visible page. Phone, hours and prices should match exactly.
After publishing, request indexing of the page in Search Console and check again in a few days. Google says crawling can take anywhere from a few days to a few weeks, so do not expect instant changes. For more on checkers, see how to test schema markup.
A short checklist
- Choose the most specific LocalBusiness subtype for your trade.
- Write name, address, phone, hours and website exactly as they appear on your Google Business Profile and in the page footer.
- Add one Service block per main service page, with provider, area and an honest price if you publish one.
- Add FAQPage only where the same questions are visible.
- Leave out star ratings for your own business and anything not on the page.
- Test in the Rich Results Test and the Schema.org validator.
- Re-check after any change of phone, hours, address or prices.
Schema is one part of a larger plan. If you want the full sequence for making a business readable to ChatGPT and other assistants, read how to show up in ChatGPT. To see how your site reads today, ask for a free demo.
Published . Updated .