Local business schema markup examples: copy-paste JSON-LD for 2026
Copy-paste local business schema markup examples in JSON-LD: storefronts, service area businesses, multiple locations and opening hours, checked against Google.
A good local business schema markup example is one you can paste, change the details in, and pass validation on the first try. This page gives you exactly that: JSON-LD templates for a storefront business, a service-area business, a brand with several locations and a solo consultant, plus every opening-hours pattern you are likely to need. Each template is checked against schema.org (opens in a new tab) and Google's LocalBusiness structured data documentation (opens in a new tab), which Google last updated in September 2026.
Quick answer
- Put LocalBusiness JSON-LD in a
<script type="application/ld+json">block on the page that describes the location: the home page for a single-location business, each location page for a multi-location one. - Google requires only
nameandaddress. It recommendstelephone,url,geo(at least 5 decimal places),openingHoursSpecification,priceRangeandimage, andmenuandservesCuisinefor restaurants. - Use the most specific type that fits (
Dentist,Plumber,Restaurant), not plainLocalBusiness. - For a service-area business, list where you work with
areaServedand leave out the street address if you hide it on your Google Business Profile. - Keep name, address and phone identical to your Google Business Profile, then test in the Rich Results Test and the Schema Markup Validator.
What local business schema does, and what it doesn't
Schema markup for a local business (people often search it as schema markup local business) is a machine-readable copy of facts already on your page: who you are, where you are, when you are open, how to call you. It helps Google connect your website to your business entity, and it makes the page eligible for local business features in Search. It is not a ranking factor on its own, and it does not move you into the map pack. The local pack is driven mainly by your Google Business Profile, your relevance and distance to the searcher, and your prominence (reviews, links, mentions).
Three facts most guides leave out:
- Your own reviews will not earn stars. Google's review snippet guidelines (opens in a new tab) say pages using
LocalBusinessor any otherOrganizationmarkup are ineligible for star ratings when the business controls the reviews about itself. Only sites that review other businesses qualify. - FAQ rich results are gone. Google stopped showing FAQ rich results in Search for all sites from May 7, 2026. FAQPage markup is harmless but no longer produces a visible result.
- There is no special schema markup for AI search. Google's guide to generative AI features (opens in a new tab) states that structured data is not required for its AI features and that no special schema.org markup is needed. Schema still helps machines read your facts accurately, which is reason enough to have it, but it is not an AI ranking switch. I cover what does help in how to get cited in AI Overviews.
So the honest answer to "does schema markup help SEO" is: it helps search engines understand and display you correctly, and it is cheap to do well. Treat it as hygiene, not a growth tactic.
Choose the right LocalBusiness type
Schema.org has dozens of LocalBusiness subtypes. Pick the most specific one that is true. Google also accepts an array when a business is genuinely two things, such as "@type": ["Electrician", "Plumber"].
| Business | Type to use | Parent type |
|---|---|---|
| Restaurant, cafe, bakery | Restaurant, CafeOrCoffeeShop, Bakery |
FoodEstablishment |
| Dentist, clinic, physician | Dentist, MedicalClinic, Physician |
MedicalBusiness |
| Plumber, electrician, roofer, HVAC | Plumber, Electrician, RoofingContractor, HVACBusiness |
HomeAndConstructionBusiness |
| Lawyer, notary | LegalService, Attorney, Notary |
LocalBusiness |
| Accountant | AccountingService |
FinancialService |
| Salon, spa | HairSalon, BeautySalon, DaySpa |
HealthAndBeautyBusiness |
| Car repair | AutoRepair |
AutomotiveBusiness |
| Shop | ClothingStore, HardwareStore, FurnitureStore and others |
Store |
| Real estate agency | RealEstateAgent |
LocalBusiness |
A note on ProfessionalService: many guides recommend it for agencies and consultants. It still validates, but schema.org notes (opens in a new tab) that the general type was deprecated because people confused it with Service. Prefer a specific subtype when one exists, and plain LocalBusiness when none does.
If you have no place customers can visit and no service area (an online-only agency, say), LocalBusiness is the wrong type. Use Organization on your home page instead.
Local business schema markup example 1: a storefront
A single-location dental practice. Replace every value; the structure is what you keep.
{
"@context": "https://schema.org",
"@type": "Dentist",
"@id": "https://www.example-dental.com/#business",
"name": "Example Dental Studio",
"url": "https://www.example-dental.com/",
"telephone": "+1-512-555-0142",
"email": "hello@example-dental.com",
"image": [
"https://www.example-dental.com/images/clinic-front.jpg",
"https://www.example-dental.com/images/reception.jpg"
],
"logo": "https://www.example-dental.com/images/logo.png",
"priceRange": "$$",
"address": {
"@type": "PostalAddress",
"streetAddress": "1200 Example Avenue, Suite 210",
"addressLocality": "Austin",
"addressRegion": "TX",
"postalCode": "78701",
"addressCountry": "US"
},
"geo": {
"@type": "GeoCoordinates",
"latitude": 30.26715,
"longitude": -97.74306
},
"hasMap": "https://maps.google.com/?cid=0000000000000000000",
"openingHoursSpecification": [
{
"@type": "OpeningHoursSpecification",
"dayOfWeek": ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"],
"opens": "08:30",
"closes": "17:30"
},
{
"@type": "OpeningHoursSpecification",
"dayOfWeek": "Saturday",
"opens": "09:00",
"closes": "13:00"
}
],
"sameAs": [
"https://www.facebook.com/exampledental",
"https://www.instagram.com/exampledental"
]
}
Points that trip people up:
telephoneincludes the country code, as Google asks.geouses at least five decimal places. Copy them from your pin in Google Maps, not from a geocoder guess.urlmust be the page for this specific location and must resolve.- Sunday is simply not listed. Google's documented way to state "closed all day" is an entry with
opensandclosesboth set to00:00, which you can add if you want to be explicit. @idgives the business a stable identifier you can reference from other markup on the site.
Example 2: service area business schema
A plumber who drives to customers and does not receive visitors. This is the case most templates get wrong, and Google's documentation does not address it directly, so here is the approach I use. Google requires an address, so keep the city, region, postal code and country, but drop streetAddress if you hide your street address on Google Business Profile. Then describe where you work with areaServed.
{
"@context": "https://schema.org",
"@type": "Plumber",
"@id": "https://www.example-plumbing.com/#business",
"name": "Example Plumbing Co.",
"url": "https://www.example-plumbing.com/",
"telephone": "+1-512-555-0187",
"image": "https://www.example-plumbing.com/images/van.jpg",
"priceRange": "$$",
"address": {
"@type": "PostalAddress",
"addressLocality": "Round Rock",
"addressRegion": "TX",
"postalCode": "78664",
"addressCountry": "US"
},
"areaServed": [
{ "@type": "City", "name": "Austin" },
{ "@type": "City", "name": "Round Rock" },
{ "@type": "City", "name": "Georgetown" },
{ "@type": "City", "name": "Pflugerville" }
],
"openingHoursSpecification": {
"@type": "OpeningHoursSpecification",
"dayOfWeek": ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"],
"opens": "00:00",
"closes": "23:59"
}
}
If you serve a radius rather than named towns, use a GeoCircle. Schema.org defines geoRadius in metres unless you say otherwise, so 40 km is 40000:
"areaServed": {
"@type": "GeoCircle",
"geoMidpoint": {
"@type": "GeoCoordinates",
"latitude": 30.50826,
"longitude": -97.67890
},
"geoRadius": 40000
}
Named cities are usually the better choice because they match how people search ("plumber in Georgetown") and the service areas you set in Google Business Profile. Keep the two lists the same. And areaServed describes reality; listing 60 towns you never visit does not create relevance there.
Example 3: multiple locations
Each location gets its own page and its own LocalBusiness block with its own url, telephone, geo and hours. Google's documentation is explicit that each location should be marked up separately with a URL that points to that location. Tie them together with an Organization on the home page and parentOrganization on each location (schema.org's older branchOf property has been superseded by parentOrganization).
On the home page:
{
"@context": "https://schema.org",
"@type": "Organization",
"@id": "https://www.example-fitness.com/#organization",
"name": "Example Fitness",
"url": "https://www.example-fitness.com/",
"logo": "https://www.example-fitness.com/images/logo.png",
"sameAs": ["https://www.linkedin.com/company/example-fitness"]
}
On /locations/downtown/:
{
"@context": "https://schema.org",
"@type": "ExerciseGym",
"@id": "https://www.example-fitness.com/locations/downtown/#business",
"name": "Example Fitness Downtown",
"url": "https://www.example-fitness.com/locations/downtown/",
"telephone": "+1-512-555-0110",
"parentOrganization": { "@id": "https://www.example-fitness.com/#organization" },
"address": {
"@type": "PostalAddress",
"streetAddress": "400 Example Street",
"addressLocality": "Austin",
"addressRegion": "TX",
"postalCode": "78701",
"addressCountry": "US"
},
"geo": { "@type": "GeoCoordinates", "latitude": 30.26820, "longitude": -97.74210 },
"openingHoursSpecification": {
"@type": "OpeningHoursSpecification",
"dayOfWeek": ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"],
"opens": "05:00",
"closes": "23:00"
}
}
Do not put all twenty locations on the home page as one big array of LocalBusiness items. One location per page, matched to the Google Business Profile for that location, is cleaner for search engines and for you. If a store has departments with different hours (a pharmacy inside a supermarket), nest them with department, each as its own LocalBusiness with only the properties that differ.
Example 4: freelancer or consultant
A consultant who meets clients at an office can use the storefront template with a fitting type (AccountingService, LegalService, or LocalBusiness). One who works remotely (as I do, as a web developer in Ahmedabad with clients abroad) is better described as a Person who runs an Organization, without pretending to have a storefront:
{
"@context": "https://schema.org",
"@graph": [
{
"@type": "Person",
"@id": "https://www.example-consulting.com/#person",
"name": "Alex Example",
"jobTitle": "Bookkeeping consultant",
"url": "https://www.example-consulting.com/about/",
"sameAs": ["https://www.linkedin.com/in/alex-example"],
"worksFor": { "@id": "https://www.example-consulting.com/#organization" }
},
{
"@type": "Organization",
"@id": "https://www.example-consulting.com/#organization",
"name": "Example Consulting",
"url": "https://www.example-consulting.com/",
"founder": { "@id": "https://www.example-consulting.com/#person" },
"areaServed": "Worldwide"
}
]
}
Opening hours: every pattern you will need
All of these follow the patterns in Google's documentation. Times use 24-hour hh:mm.
| Situation | How to mark it up |
|---|---|
| Same hours on several days | One OpeningHoursSpecification with an array in dayOfWeek |
| Closed all day | Set opens and closes both to 00:00 for that day |
| Open 24 hours | opens 00:00, closes 23:59 |
| Open past midnight | One entry on the opening day, e.g. Saturday 18:00 to 03:00 |
| Split shift (lunch break) | Two entries for the same day |
| Holiday or seasonal hours | Add validFrom and validThrough (YYYY-MM-DD) |
A holiday closure looks like this, added alongside your regular entries:
{
"@type": "OpeningHoursSpecification",
"opens": "00:00",
"closes": "00:00",
"validFrom": "2026-12-25",
"validThrough": "2026-12-25"
}
Entries without validFrom and validThrough apply all year. Remember to update holiday hours in Google Business Profile as well; that is what most people see first.
Adding services and breadcrumbs
Your service pages can describe each service and point back to the business by @id, so you do not repeat the address everywhere:
{
"@context": "https://schema.org",
"@type": "Service",
"name": "Water heater installation",
"serviceType": "Water heater installation",
"provider": { "@id": "https://www.example-plumbing.com/#business" },
"areaServed": { "@type": "City", "name": "Austin" }
}
BreadcrumbList is still a supported rich result and worth adding to every inner page. Skip AggregateRating on your own business pages for the reason above, and do not invent reviews in markup under any circumstances: it breaks Google's policies and can lead to a manual action.
Keep NAP consistent with Google Business Profile
Name, address and phone (NAP) in your markup should match the visible page and your Google Business Profile character for character: same business name (no extra keywords), same suite number format, same main phone number. If the page says "Suite 210" and the profile says "#210", pick one and use it everywhere, including directory listings. Inconsistent data gives Google conflicting facts about one entity, which is why NAP is the first thing I check in local SEO work.
Where to put the markup
- WordPress: Rank Math and Yoast (with its Local SEO add-on) output LocalBusiness markup from settings screens. Check the output: plugins often default to
Organizationor a generic type, and two plugins can both print markup. - Custom sites: generate the JSON from the same database fields that render the visible address and hours, so they never drift apart. In a Laravel app that means a method on the model and Blade's
@json; I show the pattern in the Laravel SEO guide. In Next.js, render the script tag in a server component. - Google Tag Manager: possible, but the markup is injected by JavaScript, so it depends on rendering. Server-rendered markup is more reliable.
If several blocks describe the same business, either reference one @id or combine them in an @graph, so search engines see one entity, not three.
Test and monitor
Whichever local business schema markup example you start from, test it before and after it goes live.
- Paste the URL into Google's Rich Results Test (opens in a new tab). It shows which Google features the page is eligible for and flags missing required fields.
- Run the same URL through the Schema Markup Validator (opens in a new tab). It checks general schema.org validity, including properties Google does not use, such as
areaServed. - After deploying, use URL Inspection in Search Console to confirm Google sees the live markup.
- Re-test after theme updates, plugin changes or a redesign. Markup silently disappearing is more common than markup breaking.
Search Console does not have a dedicated LocalBusiness report the way it does for some other types, so these spot checks are your monitoring.
Common mistakes
| Mistake | Fix |
|---|---|
| Markup says one thing, the page says another | Generate both from the same data |
| Same LocalBusiness block on every page of a multi-location site | One location per location page |
Self-serving AggregateRating |
Remove it; it cannot earn stars |
| Street address shown in markup but hidden in GBP | Match what GBP shows publicly |
geo with 2 or 3 decimals |
Use at least 5 |
Generic LocalBusiness when a subtype exists |
Use the specific type |
| Hours not updated for holidays | Add validFrom and validThrough entries |
Frequently asked questions
Does schema markup help SEO for local businesses?
Indirectly. It helps Google understand your business details and makes your pages eligible for some search features, but it is not a ranking factor and does not replace a complete Google Business Profile. It is worth doing because it is a one-time task that removes ambiguity.
Should I use a schema markup generator for my local business?
A generator is a fine starting point, but check its output against the examples above. Most generators default to plain LocalBusiness, skip geo precision, and cannot express service areas or multiple locations properly. Whatever you use, validate the result.
What schema should a service area business use?
Use the most specific LocalBusiness subtype (Plumber, Electrician, HVACBusiness), an address without the street if you hide it publicly, and areaServed listing the cities or a GeoCircle. Keep the service areas identical to those in your Google Business Profile.
Does schema markup help with AI search?
Google says no special markup is needed for its AI features, and structured data is not required to appear in them. Accurate markup still makes your facts easier for any system to read, so keep it correct, but put your effort into clear, specific content and a complete business profile.
Can I put LocalBusiness schema on every page?
You can, but you do not need to. Put the full block on the home page (single location) or on each location page, and reference it by @id from service pages. Repeating a large block everywhere adds weight without adding information.
If you want this set up and validated across your site, my schema markup service covers the templates, the CMS integration and the testing.