Schema for Services, Prices and Service Areas
Most service businesses describe what they do in prose and leave it at that. A page says "We offer drain cleaning, water heater repair, and emergency plumbing across the greater Tucson area," and the owner assumes that's enough for a search engine to understand. It mostly is, for a human. But AI answer engines and Google's structured systems do better when the same facts are also provided in a machine-readable format. That's what schema markup does: it restates your services, prices, and coverage area in a vocabulary that software reads directly, without having to infer anything from your sentences.
This piece covers the three pieces that matter most for a local service business — the service itself, what it costs, and where you deliver it — with real JSON you can adapt.
What schema actually does for a service business
Schema is a shared vocabulary (schema.org) that lets you label the facts on a page. Instead of hoping a machine reads "starting at $89" and connects it to "drain cleaning," you put both inside a structured block that says: this is a Service, its name is Drain Cleaning, its provider is Acme Plumbing, its price starts at 89 USD, and the area served is Tucson, Arizona.
Two things happen when you do this well. Google can use it for rich results and to populate its understanding of your business. And AI assistants that summarize search results have a cleaner source to quote — they are less likely to guess or omit your pricing when it's stated plainly in markup.
Schema does not improve a page that has no real content. It describes what's already there. If your page doesn't mention a price, don't invent one in the markup — Google treats markup that contradicts visible content as a quality problem, and it can get your rich results suppressed.
Marking up a single service
The core type is Service. At minimum you want the service name, the provider, the area served, and — if you show it on the page — an offer with a price. Here is a worked example for a hypothetical plumbing company. (Format it as JSON-LD inside a script tag in your page head; the structure below shows the fields.)
- @type: Service
- name: "Drain Cleaning"
- serviceType: "Plumbing"
- provider: an object of @type LocalBusiness with your business name, phone, and address
- areaServed: "Tucson, AZ" (or a list — more on that below)
- offers: an Offer with price "89.00", priceCurrency "USD", and a note that this is a starting price
A few field choices trip people up. If your price is "from $89," don't use a flat price field, which implies a fixed cost. Use an AggregateOffer with lowPrice and highPrice, or set the price and clearly label it "starting at" in both the markup's description and the visible page. Honesty between the two matters.
How do I handle prices when every job is custom?
If you can't publish a fixed price, use a price range or omit the price field entirely rather than guessing. Many service jobs are quote-based, and that's fine. You have three reasonable options. First, publish a genuine range using AggregateOffer with lowPrice and highPrice — for example, "drain cleaning runs 89 to 350 depending on access and blockage." That range has to match whatever you say on the page. Second, publish a starting price with an Offer and a clear "starting at" label. Third, skip price markup and keep the rest of the Service schema — name, provider, area served. The last option is common for law firms, B2B software with sales-led pricing, and contractors who scope every project. You still benefit from marking up the service and coverage; you just don't fabricate a number. A vague placeholder like "$0" or "call for pricing" encoded as a price is worse than no price field at all, because it misrepresents the data.
Marking up your service area
The areaServed field tells search systems where you work. It accepts a few formats, and the right one depends on how you operate.
Is AI recommending you, or a competitor?
Send your email and website. We check how your business shows up for the questions buyers in your market ask, and send back a short snapshot.
- The real questions your buyers search before they call anyone
- Which of those questions your site answers today — and which it does not
- Who is capturing that traffic in your market right now
A single city or metro
Use a City or AdministrativeArea object with the place name. For a business that works one metro, "Tucson, Arizona" as a City is enough.
Multiple cities
areaServed accepts an array. List each city as its own entry. Suppose a contractor covers Tucson, Oro Valley, Marana, and Sahuarita — that's four City objects in the array. This is cleaner than cramming them into one string, because each is a distinct place a machine can match against a user's location.
A radius
If you work within a distance of your base, use a GeoCircle with a geoMidpoint (latitude and longitude) and a geoRadius in meters. A 40-mile radius is 64373 meters. This suits mobile businesses — mobile repair, equipment rental delivery, on-site services — better than a city list.
Whatever you choose, it should match your real coverage and the places named on the page. If your service-area page lists eight towns, your areaServed array should contain those same eight towns. Mismatches between visible content and markup are the most common reason this work produces nothing.
A build checklist you can hand to a developer
- On each service page, confirm the visible content names the service, states pricing (or explicitly says it's quote-based), and lists the coverage area.
- Add JSON-LD with @type Service for the primary service on that page. One main Service type per page keeps things clean.
- Nest the provider as your LocalBusiness, with name, telephone, and PostalAddress. Keep this identical across every page — the same name, the same phone, the same address.
- Set areaServed using the format that matches how you work: single City, array of Cities, or GeoCircle.
- If you show prices, add an Offer (fixed) or AggregateOffer (range). If not, leave price out.
- Validate with Google's Rich Results Test and the schema.org validator. Fix every error; review every warning.
- Re-check after any redesign — template changes silently strip markup more often than you'd expect.
Does schema markup guarantee rich results or AI citations?
No — valid markup makes you eligible for rich results and easier to parse, but it doesn't force Google or any AI engine to display or cite you. Google decides which rich results to show based on quality, relevance, and its own thresholds, and those decisions vary by query and region. AI answer engines similarly choose their sources. What markup reliably does is remove ambiguity: it ensures that when a system does read your page, it reads your price as a price and your service area as a place rather than guessing from prose. Think of it as making your facts legible, not as a ranking lever. Pages with clean markup, accurate content, and a real match to the searcher's intent tend to do better across both classic search and AI summaries — but no honest practitioner can promise a specific placement or citation.
Common mistakes that waste the effort
A few patterns show up repeatedly. Marking up a price that doesn't appear anywhere on the page. Using @type LocalBusiness when you mean Service, so the coverage and offer fields have nowhere sensible to live. Listing fifty cities in areaServed when you genuinely serve four — stuffing the field doesn't expand your reach, it just adds noise. Copying one page's markup to another without changing the service name. And leaving broken markup in place after a template change, which can trigger errors that suppress rich results sitewide.
If you'd rather not manage the markup and the content that justifies it yourself, that's part of what ClearPath Content handles inside its service-page programs — keeping the visible content and the structured data in agreement as pages change.
The takeaway: schema for services, prices, and service areas is a translation job, not a growth hack. Say what you do, what it costs, and where you do it — plainly, on the page — then restate those exact facts in markup so machines don't have to guess. Keep the two in sync, validate after every site change, and never encode a number you can't show a customer.
This is what we do, every week, on autopilot.
ClearPath Content runs the whole organic program — demand mapping, production, publication and interlinking — as a monthly subscription.
Book a 30-minute call