Local Schema Markup: The LocalBusiness JSON-LD Guide

Add LocalBusiness schema markup to make your NAP, hours, and location machine-readable for Google and AI engines. A practical JSON-LD implementation guide.

Most local SEO signals live inside HTML that search engines have to interpret. Schema markup is different. It hands Google, Bing, and AI engines a structured data packet that says exactly who you are, where you are, what you do, and when you’re open. If your site is missing it, your NAP data is present but not machine-readable in the way that earns features and citations.

This guide focuses on LocalBusiness schema specifically. It’s separate from general schema markup for AI SEO, which covers broader types like Article, Product, and FAQ. Here we’re going deep on the properties that drive local pack performance, AI citations, and map-pack features for location-based businesses.

What LocalBusiness schema actually does

LocalBusiness schema is a block of JSON-LD that you embed in your page’s <head>. It tells search engines the formal facts about your business in a format they can parse without inference. Name, address, coordinates, phone number, opening hours, price range, the areas you serve: all expressed as structured key-value pairs rather than scattered across your page copy.

Search engines have always read your page content, but they make probabilistic guesses about what your address means versus your trading hours. JSON-LD removes the guesswork. It’s the difference between Google reading your page and Google reading your business record.

Why it matters for AI engines

AI engines like ChatGPT, Perplexity, and Google’s AI Overviews pull business facts from structured signals, not just body copy. When someone asks “who is a good dentist in Brunswick?” those engines aggregate data from review platforms, directory listings, and on-page structured data. A complete LocalBusiness schema block gives them clean, authoritative facts to cite directly.

Businesses with well-structured schema are more likely to be cited accurately and completely. If your schema specifies areaServed: "Brunswick" and your competitor’s doesn’t, your structured data is objectively stronger evidence for a “dentist in Brunswick” query. Tools like Fokal track how often AI engines cite your business for target queries, which is useful for measuring whether your structured data improvements translate into actual AI mentions over time.

The key properties

PropertyWhat it does
nameYour legal or trading business name
address (PostalAddress)Street, suburb, state, postcode, country
geo (GeoCoordinates)Latitude/longitude to anchor you to a map location
telephoneYour primary contact number (include country code)
openingHoursSpecificationTrading hours per day, with optional valid date ranges
urlYour website’s canonical homepage URL
imageA photo representing the business (ideally 1200x900px)
priceRangeDollar symbols indicating price tier ($, $$, $$$)
areaServedSuburbs, cities, or regions you serve
sameAsAuthoritative profiles: Google Business Profile, Facebook, LinkedIn

Each of these maps to something Google and AI engines already use. geo anchors your business to a physical point, which reinforces the “distance” component of local ranking. areaServed tells Google and AI engines which searches are relevant to you even if you don’t have a street-level location in every suburb. sameAs links your schema to your profiles on other authoritative platforms, which helps consolidate your entity identity.

A complete LocalBusiness JSON-LD example

Here’s a realistic example for a plumbing business in Melbourne. Place this inside a <script type="application/ld+json"> tag within the <head> of your page.

{
  "@context": "https://schema.org",
  "@type": "Plumber",
  "name": "Fitzroy Plumbing Co",
  "url": "https://fitzroyplumbing.com.au",
  "telephone": "+61 3 9412 5500",
  "image": "https://fitzroyplumbing.com.au/images/fitzroy-plumbing-van.jpg",
  "priceRange": "$$",
  "address": {
    "@type": "PostalAddress",
    "streetAddress": "12 Smith Street",
    "addressLocality": "Fitzroy",
    "addressRegion": "VIC",
    "postalCode": "3065",
    "addressCountry": "AU"
  },
  "geo": {
    "@type": "GeoCoordinates",
    "latitude": -37.7991,
    "longitude": 144.9784
  },
  "openingHoursSpecification": [
    {
      "@type": "OpeningHoursSpecification",
      "dayOfWeek": ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"],
      "opens": "07:00",
      "closes": "17:00"
    },
    {
      "@type": "OpeningHoursSpecification",
      "dayOfWeek": "Saturday",
      "opens": "08:00",
      "closes": "13:00"
    }
  ],
  "areaServed": [
    "Fitzroy",
    "Collingwood",
    "Carlton",
    "Richmond",
    "Brunswick"
  ],
  "sameAs": [
    "https://www.google.com/maps/place/fitzroy-plumbing-co",
    "https://www.facebook.com/fitzroyplumbing",
    "https://www.hipages.com.au/fitzroyplumbing"
  ]
}

Note @type is set to Plumber, not LocalBusiness. That’s intentional, and it leads to the next point.

Using a subtype instead of LocalBusiness

LocalBusiness is the base type, but schema.org defines dozens of subtypes that inherit all LocalBusiness properties and add their own. Using the most specific subtype gives search engines a stronger signal.

Common subtypes:

  • Plumber, Electrician, HVACBusiness
  • Dentist, MedicalClinic, Physician
  • Restaurant, CafeOrCoffeeShop, Bakery
  • LegalService, AccountingService, FinancialService
  • AutoRepair, Locksmith, MovingCompany

Here’s a shorter example for a dental practice:

{
  "@context": "https://schema.org",
  "@type": "Dentist",
  "name": "Sydney CBD Dental",
  "url": "https://sydneycbddental.com.au",
  "telephone": "+61 2 9211 4400",
  "address": {
    "@type": "PostalAddress",
    "streetAddress": "Level 3, 80 Pitt Street",
    "addressLocality": "Sydney",
    "addressRegion": "NSW",
    "postalCode": "2000",
    "addressCountry": "AU"
  },
  "geo": {
    "@type": "GeoCoordinates",
    "latitude": -33.8670,
    "longitude": 151.2094
  },
  "areaServed": ["Sydney CBD", "The Rocks", "Circular Quay", "Haymarket"]
}

If your subtype isn’t in the schema.org list, LocalBusiness is the right fallback. Don’t use a type that doesn’t accurately describe your business: mismatched types create a negative signal rather than no signal.

Where to place it

Put the <script type="application/ld+json"> block inside your page’s <head> element, not in the body. Most CMS platforms and Astro sites make this straightforward with a dedicated head component.

Per-page or sitewide? Both approaches are valid, but the logic differs:

  • Homepage schema: Always include your full LocalBusiness block on the homepage. This is the primary entity declaration for your site.
  • Location pages: If you have a dedicated “Contact” or “About Us” page, add the schema there too. The properties reinforce each other.
  • Inner pages: A lighter-weight schema with just name, url, and telephone on inner pages is fine. It signals consistency without duplicating the full block everywhere.

The most important rule: the data in your schema must match your Google Business Profile and your on-page content. Inconsistencies across these three surfaces confuse Google about which facts are authoritative.

Multi-location businesses

If you have multiple locations, each location gets its own LocalBusiness schema block on its own dedicated page. Never bundle multiple addresses into a single schema block. Instead, create a URL for each location (for example /locations/sydney/ and /locations/melbourne/) and place location-specific schema on each.

Tie them together with a parent Organization type on your homepage that uses sameAs to point to each location’s page. This is the structure search engines expect for franchise or chain businesses. Our multi-location SEO guide covers the full strategy for managing separate local signals at scale.

How to validate your schema

After implementing, run your pages through Google’s Rich Results Test (search.google.com/test/rich-results). It parses your JSON-LD, highlights errors, and shows which rich result types your markup is eligible for.

Schema.org’s own validator at validator.schema.org is stricter and useful for catching property-level issues that the Rich Results Test doesn’t flag.

Common mistakes to check:

  • Missing required properties. Some subtypes require specific properties. Restaurant expects servesCuisine. Dentist expects medicalSpecialty to unlock Knowledge Panel eligibility.
  • Mismatched data. Your schema address must match your GBP address exactly, including abbreviations. “St” versus “Street” matters.
  • Invalid JSON syntax. A missing comma or mismatched bracket breaks the entire block silently. Run your JSON through a linter before publishing.
  • Stale hours. Opening hours that don’t reflect your actual trading hours are a negative signal. Update schema whenever your hours change.

Schema as one layer in a broader local strategy

Local schema markup makes your facts machine-readable, but it works alongside your other local signals, not in place of them. Your local citations need to agree with your schema. Your GBP profile needs the same address, hours, and name. Your website content needs to support the areaServed claims you make in your JSON-LD.

Schema is the syntax layer. The strategy behind it is covered in the local SEO guide.

What to do next

If your site doesn’t have LocalBusiness schema yet, implement the full block on your homepage first. That’s the single highest-leverage move. Then add location-specific schema to any dedicated location pages, and use the Rich Results Test to confirm there are no validation errors.

Once schema is live, it’s worth checking whether your structured data is influencing AI engine citations. That’s a separate measurement problem from Google’s Rich Results Test, since AI engines don’t publish their citation logic. Running target queries across ChatGPT, Perplexity, and Google AI Overviews before and after the implementation gives you a baseline to compare against.

Implementation checklist:

  • Write a full LocalBusiness (or subtype) JSON-LD block for your homepage
  • Include: name, address, geo, telephone, openingHoursSpecification, url, image, priceRange, areaServed, sameAs
  • Use the most specific schema.org subtype that accurately describes your business
  • Verify data matches your Google Business Profile and on-page content exactly
  • Validate with Google’s Rich Results Test
  • Add location-specific schema to any dedicated location pages
  • Update schema whenever hours, address, or key details change
  • For multi-location businesses, create one schema block per location page

Eight minutes to something you can ship.