LocalBusiness Schema Markup: The Local SEO Tag Most Sites Get Wrong
If you run a business with a physical location or a defined service area, LocalBusiness schema is probably the highest-leverage piece of structured data you can add. It feeds Google Business Profile, local pack rankings, and the knowledge panel that sometimes shows up next to your brand searches.
And most sites do it wrong — either by skipping it entirely, using the wrong subtype, or shipping a copy-pasted template with broken geo coordinates.
What LocalBusiness Schema Does
LocalBusiness is a Schema.org type that describes a business entity with a physical presence. When you add it as JSON-LD on your site, you're giving Google a structured version of the same information a human would read on your contact page — name, address, phone, hours, payment types, price range, service area, social profiles.
Google uses this data to:
- Confirm the facts on your Google Business Profile match your website (mismatches hurt local rankings)
- Populate the knowledge panel for brand searches
- Qualify you for rich results like review stars, business hours, and map cards
- Match queries with location intent ("plumber near me", "dentist open now")
You can't rank in the local pack without a verified Google Business Profile. But LocalBusiness schema is what ties your website authority back to that profile and reinforces the signals.
Pick the Right Subtype
This is the part most tutorials skip. LocalBusiness is the generic parent type — Schema.org has dozens of specific subtypes that inherit from it, and Google prefers the most specific one.
Common subtypes:
Restaurant,BarOrPub,CafeOrCoffeeShop,FastFoodRestaurantDentist,MedicalClinic,Physician,HospitalAutoRepair,AutoDealer,GasStationHomeAndConstructionBusiness→Plumber,Electrician,RoofingContractor,HVACBusiness,HousePainterProfessionalService→AccountingService,LegalServiceStore→ClothingStore,HardwareStore,GroceryStoreLodgingBusiness→Hotel,BedAndBreakfast,CampgroundHealthAndBeautyBusiness→HairSalon,BeautySalon,DaySpa
If your business fits a specific type, use it. A roofing contractor should use RoofingContractor, not LocalBusiness. Google reads the full type hierarchy, so you inherit all the LocalBusiness properties automatically.
If no subtype fits, fall back to LocalBusiness. Don't invent types — Google will ignore unknown ones.
The Minimum Viable JSON-LD
Here's what a complete, working LocalBusiness block looks like. This is for a plumbing business with one physical office:
{
"@context": "https://schema.org",
"@type": "Plumber",
"@id": "https://example.com/#business",
"name": "Acme Plumbing & Drain",
"image": "https://example.com/storefront.jpg",
"url": "https://example.com",
"telephone": "+16015551234",
"priceRange": "$$",
"address": {
"@type": "PostalAddress",
"streetAddress": "123 Main St",
"addressLocality": "Petal",
"addressRegion": "MS",
"postalCode": "39465",
"addressCountry": "US"
},
"geo": {
"@type": "GeoCoordinates",
"latitude": 31.3454,
"longitude": -89.2578
},
"openingHoursSpecification": [
{
"@type": "OpeningHoursSpecification",
"dayOfWeek": ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"],
"opens": "08:00",
"closes": "17:00"
},
{
"@type": "OpeningHoursSpecification",
"dayOfWeek": "Saturday",
"opens": "09:00",
"closes": "13:00"
}
],
"sameAs": [
"https://www.facebook.com/acmeplumbing",
"https://www.instagram.com/acmeplumbing"
]
}
Drop that into a <script type="application/ld+json"> tag in your site's <head>. Every field above is one Google actually uses.
The Fields That Matter Most
Not every property is equal. These are the ones that affect rich results and ranking:
name— match your Google Business Profile exactly. No "best plumber in town" marketing fluff.address— every subfield filled in, matching what's on your GBP to the comma.telephone— E.164 format (+16015551234), not a vanity format with dashes or parentheses.geo— latitude/longitude to at least 4 decimal places. Get these from Google Maps (right-click your location).openingHoursSpecification— structured hours, not a free-text "Mon-Fri 9-5" string.image— a real photo of the storefront or logo. Must be publicly accessible, at least 112×112, ideally 1:1 or 4:3.priceRange— one of$,$$,$$$,$$$$. Or a literal range like"$50-$500".sameAs— links to your social profiles. This is how Google connects your website identity to your Facebook page, LinkedIn, etc.
Service-Area Businesses (No Storefront)
If you don't have a customer-facing location — a traveling HVAC tech, a mobile dog groomer, a remote consultant — you still need an address for verification, but you can mark your service area separately using areaServed:
{
"@context": "https://schema.org",
"@type": "HVACBusiness",
"name": "Gulf Coast HVAC Services",
"telephone": "+16015551234",
"address": {
"@type": "PostalAddress",
"addressLocality": "Hattiesburg",
"addressRegion": "MS",
"postalCode": "39401",
"addressCountry": "US"
},
"areaServed": [
{
"@type": "City",
"name": "Hattiesburg"
},
{
"@type": "City",
"name": "Petal"
},
{
"@type": "City",
"name": "Laurel"
}
]
}
You can also use a GeoCircle with a center point and radius if you serve a range rather than specific cities:
"areaServed": {
"@type": "GeoCircle",
"geoMidpoint": {
"@type": "GeoCoordinates",
"latitude": 31.3271,
"longitude": -89.2903
},
"geoRadius": 50000
}
geoRadius is in meters — 50000 is a 50km service radius.
Multiple Locations
Two options here and people regularly pick the wrong one:
Option A: Separate pages, separate schema blocks. If each location has its own /locations/[city] page, put a dedicated LocalBusiness block on each page with that location's specific address, hours, and geo. This is the right answer for most multi-location businesses — every location gets its own landing page and its own schema.
Option B: An Organization with subOrganization. Use this if you have a central brand page and need to describe the parent + locations in one graph. Generally only worth it for franchises or chains with 10+ locations.
Never put multiple different LocalBusiness blocks on the same page thinking it boosts rankings. It doesn't — it confuses Google.
Reviews and Aggregate Ratings
You can include aggregateRating if the reviews are genuinely collected on your own site (not scraped from Google, Yelp, or Facebook). Google's guidelines explicitly forbid including third-party review data in your own schema:
"aggregateRating": {
"@type": "AggregateRating",
"ratingValue": "4.8",
"reviewCount": "127"
}
Only use this if you have a real on-site review system generating these numbers. Faking it will get you a manual action.
Common Mistakes That Break Rich Results
Wrong phone format. Google wants E.164: +1 followed by digits, no dashes, no parens. (601) 555-1234 will validate but won't feed the knowledge panel consistently.
Fake or rounded geo coordinates. 31.3, -89.2 is not precise enough — Google needs at least 4 decimal places. And don't make them up; if they don't match the address, you'll lose trust signals.
Address mismatch with GBP. If your schema says "123 Main Street" and Google Business Profile says "123 Main St.", that's a mismatch. Name, address, phone (NAP) must be byte-identical across your website, schema, and GBP.
Missing image or pointing to a non-public image. If Google's fetcher gets a 403 or an image behind a login wall, the rich result won't render.
Using LocalBusiness when a specific subtype exists. Dentist or Plumber or Restaurant will always outperform generic LocalBusiness.
Putting schema inside a rendered component that only loads on interaction. JSON-LD must be server-rendered in the initial HTML. If it's injected by client-side JavaScript after user interaction, Google may miss it.
Duplicating schema across pages with copy-pasted data. Each page's schema should match that specific page's content. Homepage gets the full LocalBusiness block. Contact page can reference the same @id. Location-specific pages get their own location-specific blocks.
How to Combine LocalBusiness with Other Schema
LocalBusiness pairs well with:
FAQPage— service questions right on the homepage or service page. See our FAQ schema markup guide.Service— list the specific services you offer as nestedhasOfferCatalogor separateServiceblocks on service pages.BreadcrumbList— helps Google understand your site structure, especially for multi-location setups.Review(individual) — if you display genuine customer reviews on your site.
The @id field in the example above is how you link these together. Use a unique URI per business entity and reference it with @id in related blocks so Google knows they describe the same thing.
Generate It Without Hand-Coding
Writing this JSON-LD by hand is doable but error-prone — one trailing comma and the whole block silently fails. The Schema Markup Generator builds valid LocalBusiness JSON-LD with the right subtype, properly-formatted hours, and correct nesting. Pick your business type, fill in the fields, copy the code.
Once you've pasted it into your site, run the output through the Structured Data Validator to catch any issues before Google sees them. Missing required fields, wrong data types, and malformed geo coordinates all surface there before they cost you rich results.
Quick Checklist
- Correct subtype for your business (Plumber, Dentist, Restaurant, etc. — not just LocalBusiness)
- NAP matches Google Business Profile exactly
- Phone in E.164 format (
+16015551234) - Geo coordinates to 4+ decimal places
- Structured hours via
openingHoursSpecification, not free text - Publicly-accessible
imageURL - Service-area businesses use
areaServedwith cities orGeoCircle - Each location page has its own schema block
aggregateRatingonly if reviews are on-site- Schema server-rendered in initial HTML, not JavaScript-injected
Build your LocalBusiness schema in a couple minutes with the Schema Markup Generator, then verify it parses clean with the Structured Data Validator before pushing live.
Ready to try it?
Create JSON-LD structured data for your website. Support for Article, LocalBusiness, Product, FAQ, and more schema types.
📋 Schema Markup Generator — Free Online ToolGet notified about new SEO tools
More free tools coming soon — keyword research, sitemap generator, and more.