The Service-Area Schema Markup Cheat Sheet
The exact schema to paste so Google understands every town you cover, even when you work from home.
If you serve clients across multiple towns, cities, or postcodes but you do not have a shopfront in each one, Google needs to be told that explicitly in your schema or it will default to treating you as a single-location business. This cheat sheet gives you the exact LocalBusiness and serviceArea markup to copy, fill in, and paste. No technical background needed, no plugin required, just structured data that works.
- What You Are Actually Building
- The Base LocalBusiness Block
- Adding Service Areas: Three Methods
- Combining areaServed and serviceArea
- No Physical Address? Here Is What to Do
- Additional Fields That Strengthen Local Signals
- Testing and Validating Your Schema
- Common Mistakes That Waste the Effort
What You Are Actually Building
Service-area schema sits inside a JSON-LD script tag in your page head. It tells Google three things: who you are, where you are based, and where you will travel to serve clients.
Use JSON-LD, not Microdata
Google recommends JSON-LD for all structured data. It lives in a script tag, it does not touch your HTML, and it is far easier to update. If a plugin or developer suggests Microdata or RDFa, push back and ask for JSON-LD instead.
One script block per page, not per service area
You add one JSON-LD block that lists all your service areas together. You do not create separate schema blocks for each town. Multiple conflicting LocalBusiness blocks on the same page can confuse Google's parser.
Every service page should carry this schema
Your homepage schema handles your main NAP (name, address, phone). Your service pages should each carry a LocalBusiness block too, scoped to that specific service and the areas it covers. This is how you build topical relevance at scale.
The Base LocalBusiness Block
This is the minimum viable schema for a service-area business. Copy it, replace the placeholder values, and paste it into the head section of your page.
Base template to copy
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "LocalBusiness",
"name": "Your Business Name",
"url": "https://yourdomain.com",
"telephone": "+44-XXXX-XXXXXX",
"email": "[email protected]",
"address": {
"@type": "PostalAddress",
"streetAddress": "Your Street",
"addressLocality": "Your Town",
"postalCode": "XX1 1XX",
"addressCountry": "GB"
},
"geo": {
"@type": "GeoCoordinates",
"latitude": 51.5074,
"longitude": -0.1278
},
"areaServed": [],
"serviceArea": {}
}
</script>What to put in @type
LocalBusiness is the parent type. If your business fits a more specific category, use that instead. Common examples: HomeAndConstructionBusiness for tradespeople, ProfessionalService for consultants and coaches, LegalService for solicitors, AccountingService for accountants, HealthAndBeautyBusiness for salons and therapists. Google gives extra weight to the more specific type.
The geo field is not optional
Even for service-area businesses with no physical shopfront, include a geo block with your approximate coordinates. Use your home postcode, a registered office, or your nearest major town centroid. Google uses this to anchor your local relevance. Without it, service-area matching is weaker.
Adding Service Areas: Three Methods
There are three ways to define where you work. Use the method that matches how precise you need to be.
Method 1: Named places with City or State
"areaServed": [
{"@type": "City", "name": "Manchester"},
{"@type": "City", "name": "Salford"},
{"@type": "City", "name": "Stockport"},
{"@type": "AdministrativeArea", "name": "Greater Manchester"}
]
Use this when you serve specific named towns. You can mix City and AdministrativeArea types in the same array.Method 2: Radius from your base
"serviceArea": {
"@type": "GeoCircle",
"geoMidpoint": {
"@type": "GeoCoordinates",
"latitude": 53.4808,
"longitude": -2.2426
},
"geoRadius": "30000"
}
The geoRadius value is in metres. 30000 = 30km radius. Use this when you serve anything within a drive-time zone rather than named towns.Method 3: Defined shape with GeoShape
"serviceArea": {
"@type": "GeoShape",
"box": "53.35 -2.45 53.65 -2.05"
}
The box value is: south-west-lat south-west-lng north-east-lat north-east-lng. Use this for irregular service territories, such as covering one side of a county but not the other.Combining areaServed and serviceArea
You can and should use both fields together. They serve different purposes and Google reads them independently.
AreaServed is for named places, serviceArea is for geographic reach
AreaServed tells Google the specific place names you target. serviceArea tells Google the geographic boundary of your coverage. Using both gives you named-place relevance plus boundary coverage. If you only use one, you lose half the signal.
Full combined example for a service-area business
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "ProfessionalService",
"name": "Apex Marketing Consultants",
"url": "https://apexmarketing.co.uk",
"telephone": "+44-0161-XXX-XXXX",
"address": {
"@type": "PostalAddress",
"streetAddress": "14 Deansgate",
"addressLocality": "Manchester",
"postalCode": "M3 4LX",
"addressCountry": "GB"
},
"geo": {
"@type": "GeoCoordinates",
"latitude": 53.4808,
"longitude": -2.2426
},
"areaServed": [
{"@type": "City", "name": "Manchester"},
{"@type": "City", "name": "Salford"},
{"@type": "City", "name": "Stockport"},
{"@type": "City", "name": "Bolton"},
{"@type": "AdministrativeArea", "name": "Greater Manchester"}
],
"serviceArea": {
"@type": "GeoCircle",
"geoMidpoint": {
"@type": "GeoCoordinates",
"latitude": 53.4808,
"longitude": -2.2426
},
"geoRadius": "40000"
},
"priceRange": "££",
"openingHoursSpecification": [
{
"@type": "OpeningHoursSpecification",
"dayOfWeek": ["Monday","Tuesday","Wednesday","Thursday","Friday"],
"opens": "09:00",
"closes": "17:30"
}
]
}
</script>No Physical Address? Here Is What to Do
If you run a home-based or fully remote service business, you may not want to publish your home address. Schema still works, but you need to handle this correctly.
Use your nearest major town as addressLocality
You are not required to list a street address. You can set streetAddress to an empty string and use only addressLocality (your nearest town) and postalCode. Google will still anchor your geo relevance to that area. This is common practice for home-based businesses.
Do not fake an address
Using a virtual office address in your schema when your Google Business Profile shows a different address, or no address, creates a NAP inconsistency. Google's local algorithm checks consistency across your schema, GBP, and directory citations. Inconsistency suppresses your local rankings.
Set hasMap only if you have a verified Google Maps listing
The hasMap property takes a Google Maps URL. Only include it if you have a verified Google Business Profile with a maps listing. Linking to a generic maps page or a map showing your general area is not useful and may be ignored by Google's parser.
Additional Fields That Strengthen Local Signals
Beyond the core LocalBusiness and serviceArea fields, these additions give Google more to work with and can improve how your rich results display.
SameAs links your entity to trusted sources
Add a sameAs array pointing to your verified profiles: Google Business Profile URL, LinkedIn company page, Facebook page, Wikidata entity URL if you have one. This builds entity authority and helps Google's Knowledge Graph connect your local schema to your broader web presence.
Example sameAs block
"sameAs": [ "https://www.google.com/maps?cid=YOUR_CID", "https://www.linkedin.com/company/your-company", "https://www.facebook.com/yourpage", "https://www.wikidata.org/wiki/QXXXXXXX" ]
KnowsAbout signals topical expertise
KnowsAbout is an underused field. List the specific services or topics your business specialises in as plain text strings. This helps Google understand your expertise in the context of local searches. Example: "knowsAbout": ["AI marketing automation", "HubSpot implementation", "local SEO for service businesses"]
AggregateRating requires real review data
Only add aggregateRating if you are pulling real review data from a verified source (Google, Trustpilot, Yelp). Do not hardcode a rating. Google can and does manual-review schema that looks fabricated. A flagged schema block can be removed from rich results entirely.
Testing and Validating Your Schema
Schema that contains errors is ignored by Google. Always validate before you consider the job done.
Use Google's Rich Results Test first
Go to search.google.com/test/rich-results, paste your URL or your raw JSON-LD, and run the test. It shows you detected item types, warnings, and errors. Warnings do not block your schema from working. Errors do. Fix all errors before publishing.
Then check Schema.org validator
Go to validator.schema.org and paste your JSON-LD there. This catches property-level errors that Google's test sometimes misses, such as using a property that does not belong to your @type, or nesting a type incorrectly.
Check Search Console after 48 hours
Once your schema is live, open Google Search Console and go to Enhancements. If Google has crawled and processed your structured data, you will see it listed here. Any manual actions or crawl errors related to schema show up in this section. If nothing appears after 7 days, check that your page is indexed and not blocked by robots.txt.
One syntax error breaks the entire block
JSON is unforgiving. A missing comma, an extra bracket, or an unclosed quote mark makes the entire schema block invalid. Always run your JSON through a JSON linter (jsonlint.com works fine) before and after any manual edits.
Common Mistakes That Waste the Effort
These are the errors that show up repeatedly in schema audits. Check your implementation against each one before you move on.
Listing towns you do not serve
Stuffing your areaServed with every city in the country to grab rankings is treated as spam. Google cross-references your schema against your content, your GBP, and your citation footprint. If there is no corroborating signal that you serve those areas, the schema does not help and may actively trigger a quality review.
Mismatched NAP across schema and GBP
Your business name, address, and phone number must be identical in your schema, your Google Business Profile, and your main directory citations. Even minor variations, such as Ltd vs Limited, or including a county in one place and not another, create inconsistency signals that suppress local rankings.
Forgetting to update schema when you expand
If you start serving a new area, update your schema. If you stop serving an area, remove it. Stale schema that claims coverage you no longer provide is a trust signal in reverse. Build schema updates into your quarterly SEO review so they do not get missed.
Putting schema in the body instead of the head
Google can read JSON-LD from the body, but best practice is the head section, before the closing head tag. Some page builders drop custom code into the body by default. Check your source code after implementation to confirm placement.
Get the full resource
Enter your name and email and the complete resource opens on this page, instantly. No spam, unsubscribe anytime.
Already on the Sunday newsletter? Your weekly email carries a one-click access link, so you never see this form.
You do not have to do this yourself.
This resource hands you the volume. The strategy, the judgement, and the bit where it all connects is the work I do for clients: lead generation, ads, SEO, workflow automation, HubSpot, and the systems that make them compound. Done for you, consulting, coaching, or training.
Book a free 30-minute call Or get the Sunday newsletter