Service schema markup: how to add it for a service business

Service schema markup in JSON-LD: link Service to your Organization, add areaServed and offers, with a copy-paste example and what it does for AI search.

Mohit Goyal10 min read
Service schema markup: how to add it for a service business

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:

PropertyWhat it tells machinesExample value
nameThe service as you name it on the pageWordPress website development
serviceTypeThe general categoryWordPress development
providerWho delivers itA reference to your Organization
areaServedWhere you offer itUnited Kingdom, or a 10-mile radius
offersCommercial terms, such as currency and priceAn Offer in GBP
hasOfferCatalogPackages or sub-servicesBrochure site, store build
urlThe canonical service pagehttps://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:

Rendering diagram…

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 LocalBusiness subtype such as Plumber, AccountingService or LegalService. 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.

json
{
  "@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:

json
"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. 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. 2

    One Service per service page

    Each service page gets its own Service block. Don't stack every service on the homepage.

  3. 3

    Pick an honest areaServed

    Countries for remote agencies, cities or a GeoCircle for local trades. Only places you really cover.

  4. 4

    Add offers that match the page

    Currency always. A price only if the visitor can see that price.

  5. 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. 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.

MistakeWhy it hurtsFix
Adding aggregateRating from your own testimonialsService isn't one of the item types Google's review snippet documentation supports, and the same rules exclude reviews a business publishes about itselfLeave ratings out. Collect reviews on your Business Profile
Listing 50 towns you don't serveMarkup that doesn't reflect the page goes against Google's guidelines and misleads AI answersList real areas, or use one GeoCircle
Prices that aren't on the pageThe markup and the page disagreeShow the price, or drop the field
Two Organization entities with different namesMachines can't tell which one is youOne @id, referenced everywhere
Judging it by the Rich Results TestNo Service rich result exists, so it may show nothingUse 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:

  1. Will the JSON-LD be in the server-rendered HTML? It should be.
  2. 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.
  3. What happens to the Organization my SEO plugin already outputs? The right answer is "reference it", not "add another".
  4. How will you validate it? You want to hear Schema Markup Validator and Search Console, plus why the Rich Results Test may stay blank.
  5. 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.

Frequently asked

What is the difference between Service schema and LocalBusiness schema?+

LocalBusiness schema describes the business itself: name, address, phone and opening hours. Service schema describes one thing that business sells and points back to the business through the provider property. Most service websites need both: one business entity, plus one Service block per service page.

Will Service schema give my website star ratings in Google?+

No. Service isn't one of the schema types Google supports for review snippets, and Google doesn't show stars for reviews a business publishes about itself. Leave aggregateRating out of Service markup.

Should I use ProfessionalService or Service schema?+

Use the Service type for the thing you sell. For the business itself, use Organization or a specific LocalBusiness subtype such as AccountingService or Plumber. Schema.org lists ProfessionalService as deprecated because it was confused with Service.

How do I mark up a service area like a 10-mile radius in schema?+

Set areaServed to a GeoCircle with a geoMidpoint (latitude and longitude) and a geoRadius in metres, so 16000 is roughly 10 miles. You can also list the towns as City entries. Only include places the business actually covers.

Does Service schema help ChatGPT or Google AI Overviews cite my website?+

Service schema helps machines read a page accurately, and Microsoft has said schema markup helps its LLMs in Bing and Copilot. But Google says no special markup is needed for its AI features, so clear, useful page content still decides whether a site gets cited.

Why does Google's Rich Results Test show nothing for my Service schema?+

Google has no Service rich result, so the Rich Results Test may detect no items even when Service markup is valid. Use the Schema Markup Validator to check the syntax and Google Search Console to watch for errors after launch.

Mohit Goyal

Written by Mohit Goyal

Senior Web Developer in Gurugram, India. 100+ fast, SEO-friendly sites shipped in 4+ years with Next.js, React and WordPress, including the procol.ai rebuild. Send me your next project.

Keep reading

Can you add JSON-LD with Google Tag Manager?

Yes, you can add JSON-LD with Google Tag Manager, but most AI crawlers won't see it. When GTM is fine and when schema belongs in your HTML.

10 min read

Does FAQ schema still help SEO and AI search in 2026?

Google stopped showing FAQ rich results on 7 May 2026. Here's what FAQ schema still does for AI search, and how to add it in WordPress and Next.js.

11 min read

Let's build

Have a site that needs to be fast, rank and convert?

Open to Work. Usually replies within a day.