Technical SEO

Schema markup for a local business: a JSON-LD template to copy

Copy-ready LocalBusiness JSON-LD for a storefront or service-area business, which properties Google reads, and how to test the markup before it goes live.

// in this article

Local business schema markup is a block of JSON-LD code on your website that states your business name, type, address, phone number and hours in a format search engines read directly. Copy the template below, swap in your own details, paste it into the page that describes your business, and check it with Google’s Rich Results Test.

Two things to know before you start. Google lists only two required properties, name and address, so a small block done right beats a long one full of guesses. And the markup doesn’t move you up the map pack: Google’s local ranking help page names relevance, distance and prominence, and says nothing about structured data. What it does is give Google a clean, machine-readable copy of facts that should already match your Business Profile.

The template for a business with a storefront

This is for a business customers visit. The details belong to a made-up hair salon in Tucson, Arizona. Replace every value, and delete any line you can’t fill truthfully.

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "HairSalon",
  "name": "Saguaro Street Hair Studio",
  "url": "https://www.example.com/",
  "telephone": "+15205550136",
  "image": [
    "https://www.example.com/photos/1x1/salon.jpg",
    "https://www.example.com/photos/4x3/salon.jpg",
    "https://www.example.com/photos/16x9/salon.jpg"
  ],
  "priceRange": "$$",
  "address": {
    "@type": "PostalAddress",
    "streetAddress": "2810 N Campbell Ave, Suite 4",
    "addressLocality": "Tucson",
    "addressRegion": "AZ",
    "postalCode": "85719",
    "addressCountry": "US"
  },
  "geo": {
    "@type": "GeoCoordinates",
    "latitude": 32.25750,
    "longitude": -110.94320
  },
  "openingHoursSpecification": [
    {
      "@type": "OpeningHoursSpecification",
      "dayOfWeek": ["Tuesday", "Wednesday", "Thursday", "Friday"],
      "opens": "09:00",
      "closes": "18:00"
    },
    {
      "@type": "OpeningHoursSpecification",
      "dayOfWeek": "Saturday",
      "opens": "08:00",
      "closes": "14:00"
    }
  ],
  "sameAs": [
    "https://www.facebook.com/example",
    "https://www.instagram.com/example"
  ]
}
</script>

The shape follows the example in Google’s local business structured data guide, which uses a New York restaurant. sameAs isn’t in Google’s list, but it’s a standard schema.org property for pages that identify the same business, such as your social profiles. Keep it or drop it. The salon is closed Sunday and Monday, so those days have no block.

If you’d rather not write it by hand, our free local business schema generator builds the same block from a form.

Required by Google
name
address
missing = not eligible
Recommended
telephone · url · geo
openingHoursSpecification
priceRange · department
menu · servesCuisine (food)
Skip for your own business
aggregateRating
review
only for sites reviewing others
fig 1 · how google's local business guide sorts the properties. source: google search central

What to put in each line

Google’s guide sets a few format rules that most generators don’t warn you about. These are the ones that trip people up.

Property What Google asks for Common mistake
@type The most specific type that fits Leaving the generic LocalBusiness when HairSalon or Plumber exists
address A PostalAddress with as many fields as you can fill Writing the whole address as one line of text
telephone Your main number with country and area code (520) 555-0136 with no +1
geo Latitude and longitude with at least 5 decimal places Coordinates rounded to 2 or 3 places
url The full, working URL of this location’s page The homepage on every location page
priceRange A range or currency signs, under 100 characters A sentence about your prices
Hours Times as hh:mm, days as names such as “Monday” Writing hours as “9 to 6, Tue to Fri”

To get coordinates, Google Maps help says to right-click the place on a computer and click the latitude and longitude at the top of the pop-up to copy them. Paste them in and keep at least 5 decimal places.

Pick the most specific type

Google’s structured data guidelines say to use “the most specific applicable type” schema.org defines. LocalBusiness has 30 direct subtypes on schema.org, such as Dentist, LegalService, AutomotiveBusiness, FinancialService, Store and HomeAndConstructionBusiness, and many of those split again. Under HomeAndConstructionBusiness you’ll find Electrician, GeneralContractor, HVACBusiness, HousePainter, Locksmith, MovingCompany, Plumber and RoofingContractor.

Search schema.org for your trade, and walk down the tree until you can’t go further. If your business is two things at once, such as a bakery that’s also a cafe, Google lets you list both as an array: "@type": ["Bakery", "CafeOrCoffeeShop"]. Google’s guide says additionalType isn’t supported, so don’t use that instead.

Your schema type doesn’t need to match your Business Profile category word for word. Google’s categories and schema.org’s types are separate lists. Pick the closest schema.org match.

✕ Copied from a generator
@type: "LocalBusiness"
telephone: "520-555-0136"
geo: 32.26, -110.94
aggregateRating: 4.9 from 212
✓ Fixed
@type: "HairSalon"
telephone: "+15205550136"
geo: 32.25750, -110.94320
aggregateRating: removed
fig 2 · four fixes to the made-up tucson salon's markup, each from google's own rules

That last fix matters. Google’s guide says aggregateRating and review are only for sites that capture reviews about other local businesses. Marking up your own star rating won’t earn stars, and the guidelines warn that a structured data issue can lead to a manual action, which removes the page’s eligibility for rich results.

The version for a service-area business

Plumbers, HVAC companies, cleaners and other businesses that drive to customers often hide their street address on Google. That creates a conflict, because Google lists address as required, and its guidelines also say “Don’t mark up content that is not visible to readers of the page.”

The honest fix: mark up only the address you show on your site. If your site shows a city and ZIP code, use those fields and leave out streetAddress. Then describe where you work with areaServed, a schema.org property that accepts cities, regions or plain text. Here’s a made-up HVAC company in Mesa, Arizona:

{
  "@context": "https://schema.org",
  "@type": "HVACBusiness",
  "name": "Red Mountain Heating and Air",
  "url": "https://www.example.com/",
  "telephone": "+14805550178",
  "address": {
    "@type": "PostalAddress",
    "addressLocality": "Mesa",
    "addressRegion": "AZ",
    "postalCode": "85203",
    "addressCountry": "US"
  },
  "areaServed": [
    { "@type": "City", "name": "Mesa" },
    { "@type": "City", "name": "Gilbert" },
    { "@type": "City", "name": "Chandler" }
  ],
  "openingHoursSpecification": {
    "@type": "OpeningHoursSpecification",
    "dayOfWeek": ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"],
    "opens": "00:00",
    "closes": "23:59"
  }
}

Two caveats. Google’s local business guide doesn’t list areaServed, so treat it as a description for any search engine that reads schema.org, not a way to rank in Gilbert. And leave out geo if it would pinpoint a home address you keep private. If you also need to tell people which towns you cover in the page text, our service area meta generator helps with titles and descriptions.

Hours that aren’t simple

The 00:00 to 23:59 block above is how Google’s guide marks a business open 24 hours. The guide covers three other cases:

  • Closed all day. Set both opens and closes to "00:00" for that day.
  • Past midnight. One block can run from "18:00" to "03:00". Don’t split it into two days.
  • Seasonal hours. Add validFrom and validThrough dates (YYYY-MM-DD) to a block. Without them, Google treats the hours as year-round.

Holiday hours belong in your Business Profile first, since that’s what shows on Maps. If you mark them up too, use a dated block for the holiday and update the page text to match.

Where to put the markup

Google’s guide says you can add LocalBusiness markup to any page, but it usually makes sense on the page that describes the business. For a single location, that’s your homepage or contact page. Pick one, not every page.

For several locations, give each its own page with its own block, its own url, phone and hours. A store inside a store, such as a pharmacy counter in a grocery, goes in a nested department named “{store name} {department name}”, as Google’s example “gMart Pharmacy” shows.

There are three ways to get the code onto the page:

  1. Paste it into the page HTML, inside the <head> or the body. Most website builders have a “custom code” or “header code” box per page.
  2. Use your CMS or SEO plugin’s schema settings, if it lets you choose the type and fill in hours. Check its output with the test below, and make sure it uses the specific type you picked rather than a generic one.
  3. Inject it with Google Tag Manager as a Custom HTML tag. Google’s JavaScript structured data guide says Search can process markup that’s in the rendered page, and advises pulling values from the page with GTM variables rather than typing them twice, so the two can’t drift apart.

Option 1 is the safest for a small business site. The code sits in the page source, it’s easy to find when your hours change, and nothing depends on a tag firing.

How to test it

  1. Open Google’s Rich Results Test, which lists “Local business” among the types it supports. Paste the live page URL. Google’s JavaScript guide recommends the URL option over pasting code, especially for markup added by GTM.
  2. Fix every error, then read each warning. Google’s JavaScript guide says errors and warnings usually mean a syntax error or a missing property. A missing recommended property you left out on purpose, such as menu for a business that isn’t a restaurant, can stay missing.
  3. Run the same URL through the Schema Markup Validator. Google’s structured data docs describe it as the tool for checking all schema.org markup without Google-specific warnings, so it catches problems in properties like areaServed and sameAs that the Rich Results Test ignores.
  4. In Search Console, run URL Inspection on the page to confirm Google can reach it, as Google’s local business guide suggests.
https://www.example.com/contact/
Page is eligible for rich results crawled as: smartphone
Local business · 1 valid item HairSalon: name, address, telephone, hours
Warning missing field "menu": fine for a salon
fig 3 · a simplified rich results test for the made-up salon, and which warning to ignore

A passing test means the page is eligible, not that anything new will show. Google’s guidelines say plainly that structured data “does not guarantee” a feature appears. Google’s search gallery describes local business markup as feeding “business details displayed in the Google knowledge panel”.

Keep it in step with your Business Profile

The markup is only useful if it says the same thing as everywhere else. Before you publish, open your profile and check the name, phone, address and hours against the block, character for character. If you rebrand, move or change hours, update the profile, the page text and the markup on the same day. Our guide to editing a Business Profile covers which profile edits Google reviews, and the local citation audit covers the directories that should match too.

Schema is one line on a longer list. If you’re still working through the basics, the technical SEO checklist shows where structured data sits, after crawling and indexing. And if you’re tempted to add FAQ markup while you’re in there, read whether FAQ schema is still worth it first.

FAQ

Does local business schema help my rankings?

Not directly. Google’s local ranking help lists relevance, distance and prominence and doesn’t mention structured data, and its structured data guidelines say markup makes a page eligible for features without guaranteeing them. Add it for accuracy, not for a ranking jump.

Can I add my Google review stars to my own schema?

No. Google’s local business guide says aggregateRating and review are only for sites that collect reviews about other businesses, so stars on your own LocalBusiness markup won’t show and can put the page at risk of a manual action.

Do I need schema if I already have a Google Business Profile?

The profile does far more for your local visibility, so set it up first. The markup is a small extra that confirms the same facts on your own site, and with the template above it’s a short job.

Paste it, test it, then check it each time your hours change

Copy the template that fits, fill in only what’s true and visible on the page, pick the most specific type, and run the Rich Results Test on the live URL. After that, the markup only needs attention when your business details change, so add “update the schema” to the same list as “update the Business Profile”.

Portrait of Liam Fraser
// written byLiam FraserSEO specialist with 3 years of experience. Liam writes about what works in local, technical and AI search.About SerpSurfers →