Service schema markup is a small block of JSON-LD on each service page that tells Google, Bing and AI assistants what you sell, who provides it, where you offer it and on what terms. It's built from four schema.org pieces: a Service, a provider that points to your Organization or LocalBusiness, areaServed and offers. Google has no Service rich result, so you won't get star ratings or a special listing out of it. What you do get is a business that machines can't misread, and that matters more now that buyers ask AI tools before they ever click a link.
Here's the pattern I use, a copy-paste example, and the mistakes that quietly break it.
What is Service schema markup?
Service is a schema.org type for something a business offers: a WordPress build, a boiler repair, a tax return. Search engines already read your page text. Service markup sits behind it as a short fact sheet, in a format machines don't have to interpret.
These are the properties that matter for a service business:
| Property | What it tells machines | Example value |
|---|---|---|
name | The service as you name it on the page | WordPress website development |
serviceType | The general category | WordPress development |
provider | Who delivers it | A reference to your Organization |
areaServed | Where you offer it | United Kingdom, or a 10-mile radius |
offers | Commercial terms, such as currency and price | An Offer in GBP |
hasOfferCatalog | Packages or sub-services | Brochure site, store build |
url | The canonical service page | https://www.example.com/services/wordpress-development/ |
Watch the naming. The business type ProfessionalService is old. Schema.org's own ProfessionalService page says it was deprecated because it was too easily confused with Service, and Schema App recommends Service or more specific subtypes instead. Use Service for the thing you sell, and Organization or a LocalBusiness subtype for the business.
Does Service schema help SEO and AI search?
Partly. It helps Bing and Copilot understand your content and it's cheaper for Google's systems to process. But Google says AI Overviews don't need any special markup, and there's no Service rich result. A lot of "AEO" advice oversells this, so here's what the search engines have actually said.
Google's guide to AI features and your website says structured data isn't required for AI Overviews or AI Mode, and you don't need any special schema.org markup for them. It still recommends structured data as part of normal SEO. The same guide says a Google Business Profile can help your services show up in AI responses, so keep your schema and your Business Profile consistent.
There's also no Service rich result in Google. Service isn't in Google's list of supported rich result types, so the Rich Results Test may not detect Service markup even when it's valid. That's expected, not a sign something's broken. Check the syntax in the Schema Markup Validator instead, and watch Google Search Console for errors once it's live.
Other engines go further. Microsoft's Fabrice Canel confirmed in March 2025 that schema markup helps Microsoft's LLMs, the ones behind Bing and Copilot, understand content. Google engineer Ryan Levering has also said structured data is "computationally cheaper" for many of Google's systems.
My view: Service schema won't win you citations on its own. It does stop machines guessing. If your page says "we help growing firms across Kent with their books", a model has to work out if you're a bookkeeper, an accountant or a software vendor, and where Kent fits. The markup just says it: serviceType Bookkeeping, areaServed Kent, provider your firm. My JSON-LD structured data guide covers the wider picture.
How do Service, Organization, areaServed and offers fit together?
You define your business once as an Organization or LocalBusiness with a permanent @id. Each service page then describes one Service that points back to that @id through provider, with its own areaServed and offers. It's a small graph:
Which provider type you pick depends on how you work:
- Agency or consultancy with no walk-in customers: use
Organization. - Local trade or practice with an address customers know: use a
LocalBusinesssubtype such asPlumber,AccountingServiceorLegalService. Google's LocalBusiness documentation only requires name and address, but add phone, hours and geo-coordinates if you have them.
What does Service schema JSON-LD look like?
A complete Service schema is a JSON-LD @graph with three linked nodes: the Organization, the WebPage and the Service. This one is for a made-up agency that builds WordPress sites for UK and US clients. Every value is a placeholder. Swap in your own, and keep the @id values identical across the whole site.
{
"@context": "https://schema.org",
"@graph": [
{
"@type": "Organization",
"@id": "https://www.example.com/#organization",
"name": "Example Studio",
"url": "https://www.example.com/",
"logo": "https://www.example.com/logo.png",
"email": "hello@example.com",
"telephone": "+44 20 0000 0000",
"address": {
"@type": "PostalAddress",
"addressLocality": "London",
"addressCountry": "GB"
},
"sameAs": ["https://www.linkedin.com/company/example-studio"]
},
{
"@type": "WebPage",
"@id": "https://www.example.com/services/wordpress-development/#webpage",
"url": "https://www.example.com/services/wordpress-development/",
"name": "WordPress development for UK and US businesses",
"about": { "@id": "https://www.example.com/services/wordpress-development/#service" },
"publisher": { "@id": "https://www.example.com/#organization" }
},
{
"@type": "Service",
"@id": "https://www.example.com/services/wordpress-development/#service",
"name": "WordPress website development",
"serviceType": "WordPress development",
"description": "Custom WordPress websites built from your Figma design, with technical SEO and a hand-over session for your team.",
"url": "https://www.example.com/services/wordpress-development/",
"provider": { "@id": "https://www.example.com/#organization" },
"areaServed": [
{ "@type": "Country", "name": "United Kingdom" },
{ "@type": "Country", "name": "United States" }
],
"hasOfferCatalog": {
"@type": "OfferCatalog",
"name": "WordPress packages",
"itemListElement": [
{ "@type": "Offer", "itemOffered": { "@type": "Service", "name": "Brochure website" } },
{ "@type": "Offer", "itemOffered": { "@type": "Service", "name": "WooCommerce store build" } }
]
},
"offers": {
"@type": "Offer",
"priceCurrency": "GBP",
"url": "https://www.example.com/services/wordpress-development/#pricing"
}
}
]
}
A note on offers. If your page shows a "from" price, add a price field with that exact number. If you quote per project and show no price, leave price out. Schema.org doesn't require one for a service, and a number that isn't on the page goes against Google's general structured data guidelines.
Local variant: a service radius
For a trade or takeaway that covers a radius, swap the countries for a GeoCircle. geoRadius is in metres, so 16000 is roughly 10 miles:
"areaServed": {
"@type": "GeoCircle",
"geoMidpoint": { "@type": "GeoCoordinates", "latitude": 51.1279, "longitude": 1.3134 },
"geoRadius": 16000
}
I've worked with radius rules on a live store. For Whitfield Service Station in Dover, I built a custom WooCommerce plugin that checks delivery distance with the Google Maps API. The lesson carries over here: the radius in your markup should be the same one your checkout actually enforces.
Where should the markup go, and how do you add it?
One Service block on each service page, output from the server in a script tag of type application/ld+json, with every Service referencing a single sitewide Organization. This is the order I work in:
- 1
Define the business once
Output one Organization or LocalBusiness block with a fixed @id, ideally sitewide. If an SEO plugin already outputs one, reference its @id rather than creating a second.
- 2
One Service per service page
Each service page gets its own Service block. Don't stack every service on the homepage.
- 3
Pick an honest areaServed
Countries for remote agencies, cities or a GeoCircle for local trades. Only places you really cover.
- 4
Add offers that match the page
Currency always. A price only if the visitor can see that price.
- 5
Render it in the HTML
Output the JSON-LD from the server in a script tag of type application/ld+json, so every crawler gets it without running JavaScript.
- 6
Validate, then monitor
Check syntax in the Schema Markup Validator, then watch Search Console for errors after launch.
On WordPress, your SEO plugin probably already outputs an Organization and WebPage graph. Check if it adds a Service type too. If you hand-write one, hook it to the plugin's existing Organization @id. I usually build service pages from custom fields with ACF and custom post types, so the JSON-LD reads the same fields the page displays. Edit the page and the markup updates with it.
On Next.js, render the script tag in a server component, pulling from the same CMS entry as the page. Google can read structured data generated with JavaScript, but plenty of other crawlers don't run JavaScript. Vercel's research on AI crawlers found that OpenAI's and Anthropic's crawlers don't render it, so I don't rely on it.
What mistakes break Service schema?
The ones that come up most: self-written ratings, service areas you don't cover, prices that aren't on the page, duplicate Organization entities, and judging the markup by Google's Rich Results Test.
| Mistake | Why it hurts | Fix |
|---|---|---|
Adding aggregateRating from your own testimonials | Service isn't one of the item types Google's review snippet documentation supports, and the same rules exclude reviews a business publishes about itself | Leave ratings out. Collect reviews on your Business Profile |
| Listing 50 towns you don't serve | Markup that doesn't reflect the page goes against Google's guidelines and misleads AI answers | List real areas, or use one GeoCircle |
| Prices that aren't on the page | The markup and the page disagree | Show the price, or drop the field |
| Two Organization entities with different names | Machines can't tell which one is you | One @id, referenced everywhere |
| Judging it by the Rich Results Test | No Service rich result exists, so it may show nothing | Use the Schema Markup Validator |
Match your Business Profile
Use the same business name, phone, address and service areas in your schema as in your Google Business Profile. Google points to the profile as a source for local details in AI responses.
How do I generate Service schema without writing code?
The quickest route is my free Schema Markup Generator. Describe your business and the service in plain English and it returns JSON-LD that follows schema.org, ready to paste. No sign-up, 10 runs a day. Read the output before you publish it: check that areas and prices match the page, and replace any placeholder @id with your real URL.
While you're at it, check whether your robots.txt lets AI crawlers such as GPTBot, ClaudeBot and PerplexityBot in. My free AI Crawler Checker reports whether 14 AI crawlers may fetch your home page, and which robots.txt rule decides it. If a crawler is blocked, no amount of markup helps. And if you want a plain-text summary for AI tools, add an llms.txt file.
What should I ask a developer before they add it?
Ask if the JSON-LD is server-rendered, if it reads from the same fields as the page, and how they'll validate it. Pasting Service schema onto a few pages is a small job. Wiring it into templates so it stays accurate takes more care, and these questions show you quickly who's done it properly:
- Will the JSON-LD be in the server-rendered HTML? It should be.
- Does it read from the same fields as the page? Hard-coded markup goes stale the first time someone edits a price or service area.
- What happens to the Organization my SEO plugin already outputs? The right answer is "reference it", not "add another".
- How will you validate it? You want to hear Schema Markup Validator and Search Console, plus why the Rich Results Test may stay blank.
- Will you add ratings? If they're happy to add self-written reviews, walk away.
When I build service sites, such as Taxocity for a tax and compliance firm, I start with the basics: one page per service, clear headings, and leads that land somewhere useful. Structured data goes on top of that. It can't rescue thin pages.
How do I get Service schema added to my site?
Generate a draft for your main service page with the Schema Markup Generator and run it through the validator. If you'd rather have it built into your WordPress or Next.js templates along with the rest of your technical SEO, have a look at my technical SEO and Core Web Vitals service, or book a 20-minute call and send me the URL.



