Schema Markup for Local Service Businesses: A Trade-by-Trade Guide
Schema markup tells Google exactly what your local service business does, where you serve, and when you're open. Here's how to implement it, trade by trade.
Most plumbers, HVAC contractors, and electricians have a website. Very few have schema markup on it. That gap matters because schema markup is how a local service business tells Google what it actually does, not just what its homepage text says. Google reads it, pulls the structured data, and uses it to populate Knowledge Panels, star ratings in search results, and the service area on Maps.
This guide covers which schema types to use for each trade, which fields actually matter, and how to add it without a developer.
What Schema Markup Does for a Local Service Business
When you search "emergency plumber Austin TX," you see business names, star ratings, review counts, and sometimes hours before you click anything. That information comes from two places: your Google Business Profile and structured data on your website. The schema markup on your site reinforces and extends what your GBP communicates.
Without it, Google infers what your business does from page text alone. With schema markup, a local service business gives Google explicit machine-readable data. The difference shows up in rich results: star ratings, hours, and service area details can appear directly in search results rather than only inside your GBP listing.
20-30%
Typical CTR increase from rich results for local service businesses (SEMrush, 2024)
The impact is not guaranteed, and schema is not a direct ranking factor. But businesses with validated structured data get more surface area in search results, and that increases clicks even when rankings stay the same.
Which Schema Type to Use for Your Trade
Schema.org defines specific subtypes for home service businesses under HomeAndConstructionBusiness. Each one maps to a trade. Use the most specific type that matches your work.
@type: LocalBusiness (generic, misses trade context, Google treats it the same as a restaurant or salon)
@type: Plumber (trade-specific, matches Google's indexing categories for home service searches)
| Trade | Schema.org Type | Parent Type |
|---|---|---|
| Plumber | Plumber | HomeAndConstructionBusiness |
| HVAC contractor | HVACBusiness | HomeAndConstructionBusiness |
| Electrician | Electrician | HomeAndConstructionBusiness |
| Roofer | RoofingContractor | HomeAndConstructionBusiness |
| House painter | HousePainter | HomeAndConstructionBusiness |
| General contractor | GeneralContractor | HomeAndConstructionBusiness |
| Pest control | PestControlService | LocalBusiness |
| Cleaning service | HouseholdService | LocalBusiness |
| Locksmith | Locksmith | HomeAndConstructionBusiness |
Using LocalBusiness for a roofing company is not wrong. Google will still index it. But it is less precise, and you miss the type-specific signals that help Google categorize your business correctly when someone searches for your trade.
You can also use an array if your business covers multiple trades: "@type": ["Electrician", "GeneralContractor"]. This is valid schema.org syntax.
The full list of subtypes is on schema.org/HomeAndConstructionBusiness.
The Fields That Actually Appear in Search Results
Not all schema properties are equal. These are the ones Google actually uses to build rich results and Knowledge Panel data.
@type: Your trade-specific type from the table above.
name: Your business name exactly as it appears on your Google Business Profile. No keyword stuffing. "Austin Plumbing Pros 24/7 Emergency Plumber" will likely cause a NAP conflict, not a ranking boost.
address: A full PostalAddress block with streetAddress, addressLocality, addressRegion, postalCode, and addressCountry. This must match your GBP listing exactly. Inconsistencies in your schema markup versus your local service business profile confuse Google's local index. Before you implement schema, audit your NAP data first. This guide explains why mismatched addresses cause ranking problems and how to fix them.
telephone: Your primary business number in international format (+1-512-555-0100).
openingHoursSpecification: Hours by day. This is what drives "open now" and "closes at 5pm" labels in search results.
aggregateRating: Your review average and total count. This creates the star ratings visible in search. You need to keep this updated, either manually or through a plugin.
url: Your canonical homepage URL.
geo: Latitude and longitude. Used for proximity calculations when Google determines which businesses to show for a location query.
If you serve multiple cities from one address, add areaServed as a list of city or region objects. Without it, Google may only associate your business with searches near your physical address, which is a problem for trade contractors who drive to customers.
Service-Area Businesses: The Property Most Contractors Miss
Plumbers do not serve one address. They cover a metro area or a zip code cluster. This is the key difference between a trade contractor and a retail business for schema purposes, and it is where most local service business schema markup implementations fall short.
Use areaServed to list the specific cities or counties you serve. You can pair it with a serviceArea pointing to a GeoCircle to define a radius in meters from your base location.
Here is what a roofer covering a 30-mile radius around Nashville would include:
{
"@context": "https://schema.org",
"@type": "RoofingContractor",
"name": "Summit Roofing",
"telephone": "+1-615-555-0188",
"url": "https://summitroofing.com",
"areaServed": [
{ "@type": "City", "name": "Nashville", "sameAs": "https://en.wikipedia.org/wiki/Nashville,_Tennessee" },
{ "@type": "City", "name": "Brentwood" },
{ "@type": "City", "name": "Franklin" },
{ "@type": "City", "name": "Murfreesboro" }
],
"serviceArea": {
"@type": "GeoCircle",
"geoMidpoint": {
"@type": "GeoCoordinates",
"latitude": 36.1627,
"longitude": -86.7816
},
"geoRadius": "48000"
}
}This tells Google both the named service cities and the geographic reach. If you only list your office address, Google may only serve you in searches near that address and ignore the rest of your coverage.
How to Implement Schema Markup for Your Service Business
Google recommends JSON-LD, embedded in a <script type="application/ld+json"> tag inside the <head> of your page. Add it to your homepage at minimum. If you have dedicated city pages or service pages, add trade-specific or location-specific schema blocks there too.
On WordPress: RankMath and Yoast SEO both have local business schema modules. RankMath Pro's schema builder lets you set trade type, service areas, and hours through a UI, no code required.
On a custom or agency-built site: Your developer adds the JSON-LD block to the page template. It takes about 20 minutes with a generator tool.
To build the JSON-LD: Merkle's Schema Markup Generator (free, search for it) outputs a complete block based on form inputs. You paste the output into your site.
To validate it: Use Google's Rich Results Test. Paste your URL or the raw JSON-LD and Google shows you which properties it detected and whether the markup passes validation.
Do not fabricate aggregate ratings in your schema. If you add a aggregateRating block with a score not based on actual customer reviews, Google will revoke your rich result eligibility for that property. It checks review counts against sources like Google Reviews and third-party review platforms.
Common Schema Markup Mistakes for Local Service Businesses
Using LocalBusiness when a specific type exists. Most schema generators default to the generic type. Check the table in this post and override it.
NAP mismatch between schema and GBP. "St." vs. "Street," or a suite number in one and not the other, creates a conflict. Character-for-character consistency matters.
No areaServed. Service-area businesses that skip this property lose the geographic association Google needs to rank them in outlying cities. The address alone only anchors you to one location.
Stale hours. Holiday schedules or seasonal changes that do not get reflected in your schema can cause Google to show "closed" when you are actually open. This directly affects "open now" filtered searches.
No validation after updates. A missing comma in JSON-LD silently breaks the entire block. Any time you edit schema markup, run the Rich Results Test again.
The schema markup for a local service business takes 30 to 45 minutes to set up if you have your NAP data ready and use a generator. After that, the only ongoing work is updating hours and your aggregate rating count as reviews come in.
Want to build something like this?
We design and ship AI products, automation systems, and custom software.
Get in touch