Auditing your own schema by hand means juggling four tabs: the Rich Results Test, the schema.org validator, your page source, and a JSON linter to catch the stray comma that breaks everything. The GEO Grader collapses that into one step. Paste a URL, wait about ten seconds, get a score from 0 to 100 with a field-by-field breakdown. No login, no email.
Here's what it actually measures, what a strong result looks like, and the handful of fixes that move most local sites.
What it checks, and how it's weighted
The grader reads your LocalBusiness JSON-LD through three lenses, each contributing to the score.
Completeness — the biggest share. Does your markup include the fields that matter for a local entity? Google requires only two for a valid LocalBusiness — name and a complete address — but the recommended set is what actually makes you legible: telephone, url, geo coordinates, openingHoursSpecification, priceRange, image, and (from the Organization side) sameAs. Each missing recommended field costs you points. areaServed and sameAs aren't on Google's rich-result list, but they're exactly the properties that help an AI engine understand who and where you are — so the grader rewards them.
Correctness. Is your @type actually LocalBusiness or a valid subtype, and is @context set to https://schema.org? Using the wrong type is the most common failure, and it's costly.
Machine-readability. Does the JSON-LD parse without errors? Nested objects that break validation, or a single trailing comma, can void the entire block. A human reads around a typo; a crawler doesn't.
What a strong block looks like
Here's a clean Plumber block — a specific subtype, real hours, multiple served cities, and sameAs links — that scores in the mid-90s:
{
"@context": "https://schema.org",
"@type": "Plumber",
"name": "Westside Plumbing Co.",
"image": "https://westsideplumbing.com/logo.jpg",
"url": "https://westsideplumbing.com",
"telephone": "+1-403-555-0142",
"priceRange": "$$",
"address": {
"@type": "PostalAddress",
"streetAddress": "412 Bow Trail SW",
"addressLocality": "Calgary",
"addressRegion": "AB",
"postalCode": "T3C 2E8",
"addressCountry": "CA"
},
"openingHoursSpecification": [{
"@type": "OpeningHoursSpecification",
"dayOfWeek": ["Monday","Tuesday","Wednesday","Thursday","Friday"],
"opens": "07:00",
"closes": "18:00"
}],
"areaServed": ["Calgary","Airdrie","Cochrane","Okotoks"],
"sameAs": [
"https://www.facebook.com/westsideplumbing",
"https://g.page/westsideplumbingcalgary"
]
}
Notice the choices: a specific subtype (Plumber, not generic LocalBusiness), day-ranged hours, four served cities rather than one, and sameAs pointing at the Google Business Profile and a social account. That last one matters for AI: sameAs is how you tell an engine "these profiles are all the same real entity," which is the heart of the Recognize layer in the REAL Method.
What a failing block looks like
A score in the mid-40s is typical of a site built from a template years ago and never touched. It usually looks like this:
@typeset toOrganizationorWebSiteinstead ofLocalBusiness— the single biggest deduction.- No
areaServed, so nothing tells an engine which cities you serve. - No
priceRange— a one-character field ($to$$$$). - No
openingHoursSpecification. - Only the homepage URL, no
sameAslinks. - A
telephonethat's missing or written as plain text instead of a clean+1-…number.
Add a stray comma from a theme update and the whole block stops parsing.
The four fixes that move most sites
After running a lot of local sites through this, the same failures dominate, in roughly this order:
- Use
LocalBusiness(or a subtype), notOrganization.Organizationis for entities without a physical trade area, like a software company. If you serve customers in specific places, you're aLocalBusinessor one of its subtypes (Dentist,Electrician,RoofingContractor). Specificity wins. - Add
areaServed. List the cities or regions you actually serve. This is how you tell an engine where you work — and it's missing on the majority of contractor sites. - Add
priceRange. Three seconds of work, one character. - Put your phone in the schema. A click-to-call button is for humans; the
telephonefield is for the crawler. Many sites have the button and not the field.
Fix those four and most sites jump from a failing grade to a solid one in an afternoon.
A note on what schema does and doesn't do for AI
Be realistic about the mechanism. AI engines mainly read your page's rendered text — schema doesn't make hidden content visible. Its value is entity disambiguation: confirming, in a machine-readable way, who you are, where you are, and that your profiles describe one real business. Microsoft has said on record that Bing and Copilot use structured data to help their models interpret content; Google hasn't made an equivalent claim for AI Overviews, so treat schema as a strong supporting signal, not a magic citation switch. It clears the Recognize layer and lets the engine trust the facts it's about to repeat about you.
Run your own site
Head to the GEO Grader, paste your URL, wait ten seconds. Above 90 and you're in good shape. Below 60 and you've got a quick afternoon of cleanup. If you'd rather not hand-edit JSON, the Schema Generator builds a clean block from a short form. Think the grader scored something wrong? hello@rankinglocal.ai reaches me directly.