Schema markup

Schema markup for home service websites

Schema is the code that tells Google, in plain labels, that your site belongs to a plumber in Dallas who answers the phone at 2 a.m. Here is what local business schema does, what it doesn’t, and a working example you can hand to whoever runs your website.

Short answerLocal business schema is code on your website, usually JSON-LD, that labels your business facts for search engines: your trade, name, phone, hours, service area and services. For contractors, that means using the most specific schema.org type, such as Plumber or RoofingContractor, and matching your Google Business Profile exactly.

Most contractor websites either have no local business schema at all or have a generic block a plugin added years ago, still listing an old phone number. Neither one will sink you. But schema is one of the few technical jobs that costs an afternoon, not a month, and it removes guesswork about who you are for Google and for the AI tools that now answer homeowner questions. This guide covers the basics, the right type for your trade, a full example for a service-area contractor, and the mistakes we see most on DFW contractor sites.

What is schema markup?

Schema markup is structured data: a block of code that describes the facts on a page in a fixed vocabulary that machines read without guessing. The vocabulary is published at schema.org, a shared vocabulary backed by Google, Microsoft, Yahoo and Yandex. It defines types (LocalBusiness, Service, FAQPage) and properties (name, telephone, areaServed, openingHoursSpecification).

A human reading your homepage sees a logo, a phone number in the header and “Serving Dallas, Garland and Mesquite” in the footer. Google sees text and has to infer which number is yours and which cities matter. Schema states it outright: this is a Plumber, this is its telephone, these are the cities it serves.

There are three formats, but Google’s “Introduction to structured data markup in Google Search” (Google Search Central) recommends JSON-LD, a script block that sits in the page code and doesn’t touch your visible design. Every example on this page uses JSON-LD.

What local business schema does, and what it doesn’t

Be clear-eyed about this, because plenty of agencies oversell it.

  • It helps Google understand the page. That’s Google’s own description of structured data in its Search Central documentation.
  • It can make a page eligible for rich results. Eligible, not entitled. Google’s “General structured data guidelines” say plainly that using structured data doesn’t guarantee a rich result will appear.
  • It does not put you in the map pack. The Maps 3-pack (the three businesses Google shows on the map) is driven by your Google Business Profile, your reviews and your distance from the searcher. Schema on your website supports that profile. It doesn’t replace it.
  • It is not a shortcut to page one. Google doesn’t describe structured data as a ranking boost. Treat it as making your facts unambiguous, not as a lever.

Good schema doesn’t win you jobs on its own. Wrong schema, like an old phone number or a city you stopped serving, quietly tells Google the opposite of your profile. Accuracy beats volume.

Which schema.org type fits your trade

Google’s “Local business (LocalBusiness) structured data” documentation asks you to use the most specific LocalBusiness subtype that fits. For the trades, most of those sit under HomeAndConstructionBusiness on schema.org. Where your trade has no dedicated type, use the closest parent rather than inventing one.

Your tradeschema.org type to use
PlumbingPlumber
Heating and airHVACBusiness
ElectricalElectrician
RoofingRoofingContractor
PaintingHousePainter
Remodeling, general contractingGeneralContractor
Landscaping, pest control, garage doors, cleaningHomeAndConstructionBusiness (no narrower type exists)

If you run two trades, say plumbing and HVAC, you can list both types in an array ("@type": ["Plumber", "HVACBusiness"]). Only do that if both are real lines of work you’d want calls for.

A local business schema example for a service-area contractor

Below is a complete example for a made-up company, Example Plumbing Co. The phone number uses the 555 range reserved for fiction and the website is example.com. Swap in your own details, and make sure every value matches what customers see on your site and your Google Business Profile.

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "Plumber",
  "@id": "https://www.example.com/#business",
  "name": "Example Plumbing Co.",
  "url": "https://www.example.com/",
  "logo": "https://www.example.com/images/logo.png",
  "image": "https://www.example.com/images/service-van.jpg",
  "telephone": "+1-214-555-0147",
  "description": "Residential plumbing repair, drain cleaning and water heater installation in Dallas and nearby cities.",
  "address": {
    "@type": "PostalAddress",
    "addressLocality": "Dallas",
    "addressRegion": "TX",
    "postalCode": "75238",
    "addressCountry": "US"
  },
  "areaServed": [
    { "@type": "City", "name": "Dallas" },
    { "@type": "City", "name": "Garland" },
    { "@type": "City", "name": "Richardson" },
    { "@type": "City", "name": "Mesquite" }
  ],
  "openingHoursSpecification": [
    {
      "@type": "OpeningHoursSpecification",
      "dayOfWeek": ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"],
      "opens": "00:00",
      "closes": "23:59"
    }
  ],
  "hasOfferCatalog": {
    "@type": "OfferCatalog",
    "name": "Plumbing services",
    "itemListElement": [
      { "@type": "Offer", "itemOffered": { "@type": "Service", "name": "Drain cleaning" } },
      { "@type": "Offer", "itemOffered": { "@type": "Service", "name": "Water heater installation" } },
      { "@type": "Offer", "itemOffered": { "@type": "Service", "name": "Slab leak repair" } }
    ]
  },
  "sameAs": [
    "https://www.facebook.com/exampleplumbingco",
    "https://www.yelp.com/biz/example-plumbing-co"
  ]
}
</script>

What each part is doing:

  • @type and @id. The type says what you are. The @id gives the business one permanent identifier, so other markup on the site (like the Service example below) can point back to it instead of repeating everything.
  • name, telephone, url. Use the exact business name from your profile, not a keyword-stuffed version. Use the number that rings your office or dispatcher, written in international format.
  • address. Google’s local business documentation lists address as a required property and says to include as many of its fields as you can. A service-area business that hides its street address on Google can still give city, state, ZIP and country. Don’t publish in schema an address you’ve hidden everywhere else. Our guide on setting up a service-area business on Google explains why that address is hidden in the first place.
  • areaServed. The cities you actually work in, ideally the same list as your profile’s service areas. Older guides use a property called serviceArea; schema.org has replaced it with areaServed.
  • openingHoursSpecification. Google’s documentation says to show a business open 24 hours with opens “00:00” and closes “23:59”. If you only take calls 7 to 6, say so.
  • hasOfferCatalog. The services you sell. Keep it to real services with real pages.
  • sameAs. Links to your official profiles elsewhere, which helps tie your website to the same business on other sites.

Why there’s no rating in the example

You’ll see plenty of templates with an aggregateRating block that pulls in star ratings. Leave it out. In September 2019, Google announced in a Search Central Blog post, “Making Review Rich Results more helpful,” that it stopped showing review stars for reviews a LocalBusiness or Organization publishes about itself. Self-added ratings won’t earn stars and can look like an attempt to game results. Your stars belong on your Google Business Profile, earned from real customers. If you need more of them, read how to get more Google reviews.

Why there’s no priceRange or geo

Both appear in Google’s list of recommended properties, so add them only when they’re true and public. A priceRange you made up for the markup is worse than none. Geo coordinates for a hidden home address put back the very thing you chose to hide.

Service schema on your service pages

The business block above belongs on your homepage or contact page. Your individual service pages can carry a smaller Service block that points back to the business by its @id:

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "Service",
  "name": "Drain cleaning",
  "serviceType": "Drain cleaning",
  "provider": { "@id": "https://www.example.com/#business" },
  "areaServed": { "@type": "City", "name": "Dallas" },
  "url": "https://www.example.com/drain-cleaning/"
}
</script>

Google doesn’t show a special search feature for Service markup. It’s still useful: it tells search engines and AI tools which page answers which job, and it connects that page to your business entity.

Schema markup for contractors: the mistakes we see most

When Digital Ducats audits a contractor site, the same problems come up again and again.

  1. Duplicate business blocks. The theme adds one, the SEO plugin adds another, a page builder adds a third. Three blocks with three slightly different names confuse more than they help. Pick one source.
  2. Stale details. The old phone number, a closed office, a city you stopped serving. Schema is invisible on the page, so nobody notices when it goes out of date.
  3. Markup for things the page doesn’t show. Google’s general structured data guidelines say markup should describe content that’s visible to users. Hidden FAQ answers or services you don’t mention on the page break that rule.
  4. Every city page claiming to be a separate business. One company, one business block. City pages can carry Service markup with a different areaServed, but they shouldn’t each declare a new LocalBusiness with a fake local address.
  5. Expecting FAQ rich results. In August 2023 Google said on its Search Central Blog (“Changes to HowTo and FAQ rich results”) that FAQ rich results would show mainly for well-known, authoritative government and health sites. FAQ markup is still valid schema, but a contractor shouldn’t expect the expandable questions to appear under its listing.

How to add schema and test it

On WordPress, most SEO plugins, including Yoast and Rank Math, generate some structured data on their own. Check what yours already outputs before you paste anything in, or you’ll create the duplicate problem above. Many themes and plugins also let you set the business type and details in their settings rather than in raw code.

Then test every change with two free tools:

  • Google’s Rich Results Test shows whether Google can read the markup and whether the page is eligible for any rich results.
  • The Schema Markup Validator at validator.schema.org checks the code against the full schema.org vocabulary, including types like Service that Google’s test won’t comment on.

After it’s live, Google Search Console reports structured data errors for the rich result types Google supports. Schema is one item in a wider technical checklist; our technical SEO service covers it along with crawling, indexing and redirects, and our guide to Core Web Vitals covers the speed side.

Does schema help with AI search?

Honestly, nobody outside Google, OpenAI or Microsoft knows exactly how much. None of them publish how their AI answers weigh structured data. What we can say is that schema makes your core facts consistent and machine-readable, and consistent facts across your site, your profile and your listings are what every system, old or new, depends on. It’s one input in generative engine optimization, not the whole of it.

What to do next

Run your homepage through the Rich Results Test today. If nothing shows up, or the name, phone or cities don’t match your Google Business Profile, that’s your fix list. More guides live in our local SEO resource library. If you’d rather have someone check your markup and clean it up, contact us and we’ll look at it with you.

Local business schema questions

Is schema markup a ranking factor?

Not in the way people hope. Google describes structured data as a way to understand a page and to make it eligible for rich results, and it doesn’t promise a rankings boost. The real value for a contractor is clarity: your trade, phone, hours and service area stated the same way everywhere, with no guessing.

Do I need schema if I already have a Google Business Profile?

Your profile matters more for the map pack, so fix it first. Schema does a different job: it describes the business on your own website, so Google can connect your site to your profile. It takes an afternoon to set up properly, so it’s worth doing once the profile is in good shape.

Should I add review stars to my schema?

No. Google said in 2019 that it no longer shows review stars for reviews a local business publishes about itself, so self-added ratings won’t earn stars in search. Leave aggregateRating out and put your effort into earning real reviews on your Google Business Profile, where homeowners actually read them.

Can I add local business schema myself on WordPress?

Yes. Many SEO plugins let you set your business type, name, phone and hours in their settings. Check what your theme and plugins already output first, so you don’t end up with duplicate blocks, then test the page with Google’s Rich Results Test and the Schema Markup Validator.

Ready when you are

Let's get your phone ringing.