LocalBusiness Schema: What to Mark Up and Why

LocalBusiness Schema: What to Mark Up and Why

LocalBusiness schema is a block of structured data, usually JSON-LD, embedded on a business's own web page that states the business's core facts in a form software can read directly: its name, its address, its phone number, its hours, its coordinates. Nothing about it is visible to a person reading the page. It exists for the machines reading alongside the person, so they don't have to guess those facts from a logo, a footer line, or a sentence buried in an "About" paragraph.

That distinction matters more than it sounds like it should. A human reader can tell that "Open 9–6, closed Sundays" means something even if it's phrased oddly, tucked into a paragraph, or shown as an image. A parser cannot. Structured data is how you stop making the parser guess, and the value of doing that is exactly proportional to how well the markup matches reality — which is the part most sites get wrong.

What the Markup Is Actually Doing

A LocalBusiness entity is a set of key-value facts wrapped in a script block on the page, written against the vocabulary defined at schema.org and expressed in JSON-LD. It is not a caption for the page and not a summary of the content — it is a direct statement: this business is called X, is located at Y, can be reached at Z. Search engines and other systems that consume structured data, including map providers and aggregators, can read that statement without parsing your prose, your layout, or your images.

Because it's a direct statement rather than an inference, it carries a different kind of responsibility than ordinary page copy. If a paragraph on the page is slightly imprecise, a reader shrugs it off. If the markup is imprecise, a machine treats it as fact, because that's what structured data is for. Get it right once and it works quietly in the background. Get it wrong and you are making an explicit, machine-readable false statement about your own business.

Choosing the Most Specific Type Available

LocalBusiness itself is a generic parent type in schema.org's hierarchy. It works, but it's a fallback, not a target. Schema.org defines dozens of subtypes underneath it that describe an actual kind of business, and each one carries properties the generic type doesn't: a Restaurant can declare servesCuisine and acceptsReservations, a Dentist sits under a medical-business branch with properties relevant to a medical listing, and there are dedicated types for a hair salon, a legal service, an auto repair shop, and a home-services business like a plumber.

Picking the closest matching subtype instead of the generic LocalBusiness does two things. It lets you use properties that only exist on that subtype, and it tells whatever consumes the markup exactly what category of business this is without needing to infer it from your description text. Work down the type hierarchy until you find the most specific match, and only fall back to plain LocalBusiness when nothing closer genuinely fits — not because the specific type was one extra lookup away.

The Properties That Carry the Weight

A handful of properties do almost all the work, and each one has a specific job:

  • name — the business's actual trading name, exactly as it appears on the page and everywhere else the business is listed, not a marketing tagline stitched onto it.
  • address — a structured postal address with street, locality, region, postal code and country as separate fields, not one freeform string.
  • telephone — a single number in a format a dialer can use directly, without decorative characters that obscure which digits are the number.
  • geo — latitude and longitude, which is what lets a map place a pin without having to resolve your street address itself.
  • openingHoursSpecification — operating hours as structured day and time entries, not a single sentence like "Mon–Fri 9 to 5."
  • priceRange — a coarse indicator of cost level, something like a symbol tier or a broad range, not a price list.
  • url — the canonical address of this specific business's own page, so the entity described and the page describing it are unambiguously the same thing.
  • sameAs — links to the business's other authoritative profiles elsewhere on the web, which helps establish that separate listings refer to the same real entity rather than several unrelated ones that happen to share a name.

The Rule That Matters More Than Any Property

Here is the part that decides whether any of the above is worth doing: the markup has to agree with three separate things at once — what's written and shown on the page itself, what your business profile says, and what your other listings around the web say. Same name, same address, same phone number, same hours, in all three places.

This is not a nice-to-have. Contradictory facts about a business are worse than no facts at all. If your markup is silent on a property, a system consuming it simply has nothing to go on for that fact and falls back to whatever other signal it has. If your markup states one address while your business profile states a different one, you have not left a gap — you have actively told the system two different things and forced it to decide which of your own statements about yourself to distrust. Once a source has been caught contradicting itself on a fact as checkable as an address or a phone number, everything else that source asserts, structured or not, gets treated with more suspicion. That is the actual cost of stale or careless markup: not that one field is wrong, but that you stop being treated as a reliable narrator of your own facts.

The common way this happens is entirely mundane. A business moves and updates the visible page but not the schema block, because the schema block was written once at launch and nobody thought of it as part of the "update the address" task. A phone system changes providers and the new number goes on the page footer but not into the markup a few hundred lines up in the source. None of these are dramatic failures. They're maintenance failures, and they're the normal way LocalBusiness markup goes bad.

Multi-Location Businesses Need One Page Per Location

A business with more than one physical location should never try to describe all of its branches from a single shared markup block. Each location needs its own page, at its own URL, carrying its own LocalBusiness entity with its own address, its own phone number, its own hours and its own coordinates. A single script that lists three street addresses under one business entity doesn't describe three locations — it describes one confused location.

The common mistake looks like this: a chain builds a single template, drops the head-office address and central phone number into it, and republishes the identical block on every branch's page, because it's faster than maintaining ten separate ones. The result is ten pages that all technically carry LocalBusiness markup and none of which correctly identify the location the page is actually about. Or the opposite version: one "our locations" page tries to hold every branch's data in a single markup block instead of linking out to pages that each carry their own. Either way, whatever reads the markup can no longer tell which physical place a given page represents, which defeats the point of marking up a physical business at all. If there's a parent brand worth representing, that belongs as a separate organization entity the individual locations can reference — it doesn't replace giving each location its own page and its own facts.

Opening Hours, Including the Cases That Are Usually Wrong

openingHoursSpecification takes a day of the week and an open and close time. That part is simple, and most sites get the simple part right. What gets missed are the two cases that don't fit a single row per day.

Split hours — a business that closes for a lunch break and reopens in the afternoon — needs two separate specification entries for the same day, one for the morning block and one for the afternoon block. Collapsing that into a single "open 9 to 8" entry states hours the business isn't actually open during, which is exactly the kind of small, checkable, easily caught inaccuracy that undermines trust in the rest of the markup.

Holidays and seasonal exceptions are the second case, and the one that ages worst. A specification can carry a validity date range to declare an exception to the standard schedule — closed on a specific date, or open shorter hours for a season — instead of leaving the year-round hours in place and simply being wrong on the days that don't follow them. Standard weekly hours marked up once at launch and never revisited is the single most common state of LocalBusiness markup in practice: technically present, syntactically valid, and quietly incorrect on any day that isn't a normal business day.

What This Markup Does and Doesn't Do

LocalBusiness structured data helps a machine understand, unambiguously, what a business is and where it is. It supports eligibility for certain presentations that key off having clean structured facts to draw from, and it removes the guesswork a system would otherwise have to do by parsing your page's prose. That's the real, honest scope of what it does.

It does not, by itself, produce a map pack ranking. Placement in local map results is driven mainly by proximity to the searcher, relevance to the query, and prominence signals built up through your business profile, reviews, citations and links — not by the presence of a JSON-LD block on your website. A claim that adding LocalBusiness schema will move a business into the map pack is describing something schema was never built to do. Treat it as what it is: the plumbing that lets a machine read your facts accurately, not a lever that moves rankings on its own.

Validating and Keeping It Current

Before publishing a change, run the markup through a structured data testing tool to confirm it parses cleanly and that the properties required for the type you chose are actually present — a missing comma or an unclosed brace is enough to invalidate the whole block silently.

But passing validation only proves the syntax is correct; it says nothing about whether the facts inside it are true. A LocalBusiness block with a perfectly formed but outdated phone number validates without complaint. So validation needs a second, manual pass: read the markup against the live page, against the business profile, and against the other listings the business appears on, and confirm they all still agree.

The only sustainable way to keep that agreement intact is to treat a schema update as part of the same change as the content update it corresponds to — new address, new hours, new phone number, update the markup in the same edit, not as a follow-up task that quietly never happens. Markup that was accurate at launch and never touched again is not accurate markup; it's a snapshot slowly drifting away from a business that keeps changing.

Frequently asked questions

Does LocalBusiness schema need to go on every page of a site?

No. It belongs on the page or pages that represent the actual physical business location — typically the homepage for a single-location business, or each location's own page for a multi-location one. Adding it site-wide on pages that aren't about the business itself doesn't add value and can muddy which page the entity is meant to represent.

Can I use LocalBusiness for a business with no physical storefront customers visit?

If customers are served at a business address, LocalBusiness and its subtypes are appropriate. If the business genuinely serves customers only at their own locations with no public-facing premises, schema.org's vocabulary has adjustments for that case, and the address and geo properties should reflect that reality rather than listing a location the public can't actually visit.

What happens if the markup and the visible page text disagree?

Nothing enforces agreement automatically, which is exactly the danger. A system reading the page has no way to know which of your two statements is correct, and a mismatch this checkable tends to reduce trust in the source rather than simply being averaged out or ignored.

Is priceRange supposed to be exact prices?

No — it's a coarse signal of cost level, not a price list. Using it to communicate an exact figure misrepresents what the property is for and can read as inaccurate the moment actual prices move, which they will.

How often should LocalBusiness markup be reviewed?

Any time something it describes changes — address, phone number, hours, permanent closure — and, separately, on a periodic basis even absent a known change, since hours and other details drift more often than anyone remembers to update everywhere at once.

Updated: September 11, 2026

All articles