Just some notes:
Questions
- How do we add schema per page?
Local/Contact info: use our Schema Generator: https://hub.ampv.com/schema/
- Should be listed on homepage and all main landing pages
Areas Served
- Should be loaded on geolocation pages.
Reviews
- Not sure?
FAQs
- Should be added to all pages with FAQs.
1. Purpose & Scope
This SOP standardizes how we implement JSON-LD structured data (schema markup) for home service clients — plumbers, electricians, HVAC companies, roofers, general contractors, landscapers, pest control, locksmiths, movers, and similar trades. Consistent schema helps these sites:
- Qualify for rich results (star ratings, FAQ dropdowns, breadcrumbs) in search
- Reinforce local relevance signals that support Google Business Profile and local pack rankings
- Give search engines an unambiguous read on what the business is, what it does, where it serves, and what customers say about it
This SOP covers five schema types, which together handle the vast majority of home service sites:
- LocalBusiness (trade-specific subtype) — the business entity itself
- Service — individual service offerings
- FAQPage — Q&A content blocks
- BreadcrumbList — site navigation hierarchy
- Review / AggregateRating — customer feedback signals
Use the companion Schema Generator Tool (schema-generator.html) to produce the actual JSON-LD for each client — this SOP explains what data to collect, where each schema type goes, and how to QA it before it ships.
2. Before You Start: Information to Collect
Gather this from the client intake form, their Google Business Profile, and the live site. Missing or inconsistent data here is the #1 cause of rework later.
Business identity
- Legal/DBA business name (exactly as it appears on GBP and the site footer)
- Primary phone number (in the format the site displays it)
- Website URL (canonical, with correct protocol/www preference)
- Logo file (square, min 112x112px, hosted on their domain)
- Year founded / founder name (optional but useful for
Organizationfields)
Address & service area
- Most home service clients have both a public storefront/office address and a service area wider than that one location (e.g. an office in Mesa that also services Gilbert, Chandler, and Tempe). This is the default case — collect both:
- Physical address (street, city, state, zip) if there’s a public storefront/office
- Full list of cities/counties/zip codes actually served, even if it extends well beyond the office’s city
- Only omit the address if the business is a genuine service-area business (SAB) with no public storefront (mobile-only operations, or a client who has intentionally hidden their address on Google Business Profile for privacy/safety). In that case do not publish a street address in schema — use
areaServedonly, matching what’s hidden/shown on GBP - When in doubt, check the client’s Google Business Profile: if GBP shows a public address, schema should include it; if GBP has the address hidden and only shows a service area, schema should match that
- Geo coordinates (lat/long) if a physical location is being disclosed
Hours & category
- Hours of operation per day (including 24/7 emergency service flags, common for plumbing/HVAC/restoration)
- The most specific matching Schema.org business type (see Section 3 table) — avoid generic
LocalBusinesswhen a trade-specific type exists
Services
- Full list of services offered, each with a short description
- Whether pricing is public (if so, note
priceRange, e.g.,$$) - Service area per service, if it differs from the general business service area
Reviews
- Aggregate rating value and review count (pulled from Google, or from a review platform the client has rights to display)
Never fabricate or estimate ratings. Only mark up reviews that genuinely exist and are visible/verifiable on the page. Marking up reviews not visible on the page violates Google’s structured data guidelines and risks a manual action.
FAQ content
- Actual FAQ copy already on (or being added to) the page. Schema must mirror visible on-page content word-for-word — no hidden or invented Q&A.
Site structure
- Breadcrumb trail for each page type (Home > Services > [Service] > [City], etc.)
3. Choosing the Right Schema.org Type
Always use the most specific type available. Schema.org’s LocalBusiness hierarchy includes purpose-built subtypes for most trades — using them (instead of generic LocalBusiness) gives search engines a clearer signal and is a best practice we apply by default.
| Trade | Recommended @type |
|---|---|
| Plumbing | Plumber |
| Electrical | Electrician |
| HVAC | HVACBusiness |
| Roofing | RoofingContractor |
| General contracting / remodeling | GeneralContractor |
| Painting | HousePainter |
| Locksmith | Locksmith |
| Moving | MovingCompany |
| Pest control | PestControl (fallback: HomeAndConstructionBusiness) |
| Landscaping / lawn care | HomeAndConstructionBusiness (no more specific subtype exists) |
| Cleaning services | HomeAndConstructionBusiness (or LocalBusiness if not construction-adjacent) |
| Garage doors, flooring, fencing, etc. (no exact subtype) | HomeAndConstructionBusiness |
If none of Schema.org’s subtypes match the trade, fall back to HomeAndConstructionBusiness, then to LocalBusiness as a last resort. All of these subtypes inherit LocalBusiness properties, so address, telephone, openingHoursSpecification, areaServed, aggregateRating, etc. all still apply.
4. Implementation by Page Type
4.1 Homepage
- One
LocalBusiness(trade-specific subtype) block with full business details aggregateRatingnested inside it if reviews are displayed on the homepageBreadcrumbListonly if the homepage itself shows a breadcrumb (usually not needed)
4.2 Service Pages (e.g., “Drain Cleaning,” “AC Repair”)
- One
Serviceblock per page:serviceType(plain-language name)providerreferencing the business (either repeat keyLocalBusinessfields or use an@idreference — see Section 6)areaServedfor that specific servicedescriptionmatching the visible page copy
BreadcrumbListreflecting Home > Services > [Service Name]- If the page has an FAQ section, add
FAQPagematching that section exactly
4.3 Location / Service-Area Pages (e.g., “Plumber in Mesa, AZ”)
- Reuse the main
LocalBusinessschema, adjustingareaServedto the specific city/region if the page is genuinely dedicated to that area BreadcrumbList: Home > Service Areas > [City]- Do not create a duplicate
LocalBusinessentity per city page unless the client has a legitimately separate branch/location with its own address — doing so for a single business (storefront or SAB) creates duplicate/conflicting entity signals. One business, oneLocalBusinessentity, withareaServedcovering every city it works in.
4.4 About / Contact Pages
LocalBusiness(or reference the same entity via@id) with full NAP (name, address/service area, phone) and hoursBreadcrumbList: Home > About / Home > Contact
4.5 Blog / Resource Pages (if applicable)
- Not covered by the core toolkit above; flag to Nick if a client needs
Article/BlogPostingschema and we’ll extend the SOP
5. Step-by-Step Process
- Intake — Collect all data from Section 2. Confirm whether the client has a public address, a service area, or (most commonly) both — this determines which fields get published, and whether
areaServedneeds to cover cities beyond the storefront’s own city. - Choose type — Pick the correct
@typeper Section 3. - Generate — Open https://hub.ampv.com/schema/, fill in the relevant tab(s) for the page you’re marking up, and copy the generated JSON-LD.
- Place the code — Insert each JSON-LD block inside a
<script type="application/ld+json">tag in the<head>(preferred) or before</body>of the relevant page. Do not stack unrelated schema types into a single<script>tag unless using@graph(see Section 6) — keep them as separate script blocks for clarity unless a graph is intentional. - Cross-check against visible content — Every fact in the schema (name, phone, hours, FAQ text, review count) must match what a visitor actually sees on that page. This is the single most common cause of Google Search Console errors and spam flags.
- Validate — Run every page through:Fix all errors and review all warnings before publishing.
- Publish — Push to staging first if the client’s workflow supports it; otherwise deploy directly and re-validate on the live URL.
- Log it — Note the pages updated, schema types added, and date in ClickUp.
- Monitor — Check Google Search Console’s “Enhancements” reports (or equivalent, e.g. “Unparsable structured data,” “Reviews snippet,” “FAQ”) 1–2 weeks after publishing and again at the next reporting cycle.
6. Technical Notes & Best Practices
- One entity, one
@id. When a business appears in multiple schema blocks on the same page (e.g.,LocalBusinessandService.provider), use@idanchors (e.g.,"@id": "https://example.com/#business") and reference them instead of repeating full data, to avoid duplicate/inconsistent entity signals across a page. @graphfor multi-type pages. When a single page legitimately needs more than one schema type (e.g.,Service+FAQPage+BreadcrumbList), combine them under one@grapharray in a single script block rather than three disconnected blocks — this makes the entity relationships explicit.- NAP consistency. Name, Address, Phone in schema must match the site footer, Google Business Profile, and any directory listings exactly (same formatting, abbreviations, etc.).
- Address and service area aren’t mutually exclusive. Most home service businesses have a real office/storefront and serve a much wider area — include both
addressandareaServedin that case. Only dropaddressentirely for a genuine SAB where Google Business Profile also has the address hidden; in that case useareaServedwith aGeoCircleor a list ofCity/AdministrativeAreaentities instead of a street address. - Don’t mark up reviews you don’t have rights to display, and don’t aggregate third-party reviews (e.g., Google reviews) into your own
AggregateRatingunless you have a legitimate mechanism (like a widget with a valid license/API) — for most clients, embed only reviews genuinely shown on the page. - Keep FAQ schema in sync with content edits. If a client’s team edits FAQ copy on the page without telling us, the schema goes stale and Google can flag it as unrepresentative. Add a reminder in the client’s editorial workflow.
- Avoid schema spam. Don’t add types the page doesn’t substantively support (e.g.,
HowToon a page with no actual steps) purely to chase rich results — Google’s spam policies explicitly cover this and it can trigger manual actions.
7. QA Checklist (complete before marking a schema task “done”)
- Correct, most-specific
@typeused for the business - Address and/or
areaServedcorrectly reflect the client’s actual footprint (both included when the business has a storefront that also serves a wider area; address omitted only for a genuine SAB with no public address) - NAP matches GBP, footer, and directories exactly
- Hours match what’s posted on GBP and the site
- All FAQ schema text matches visible on-page text verbatim
- All review/rating data is real, current, and visible on the page
- Breadcrumb trail matches the actual site navigation/URL structure
- No orphaned or duplicate
LocalBusinessentities across pages (use@idreferences) - Passes Google Rich Results Test with zero errors
- Passes Schema.org Validator with zero errors
- Screenshot or note saved of validator pass for the client file
- Change logged in client tracking sheet with date and pages affected
8. Maintenance Cadence
| Trigger | Action |
|---|---|
| Client rebrands, changes phone/address, or adds a location | Update schema same week |
| New service added to site | Add corresponding Service schema at launch |
| FAQ content edited | Re-sync FAQPage schema immediately |
| Quarterly account review | Re-run Rich Results Test on top 5 pages per client |
| Google structured data guideline changes | Re-review this SOP and update as needed (flagged in the SEO Decision Log) |
9. Appendix: Field Reference
LocalBusiness (and trade subtypes)
@type, name, image, @id, url, telephone, priceRange, address (omit only for a pure SAB), geo, openingHoursSpecification, areaServed (include alongside address whenever the service area extends beyond the storefront’s city), aggregateRating, review, sameAs (social/directory profile URLs)
Service
@type: Service, serviceType, name, description, provider (@id reference to the business), areaServed, url
FAQPage
@type: FAQPage, mainEntity (array of Question objects, each with name and an acceptedAnswer of @type: Answer with text)
BreadcrumbList
@type: BreadcrumbList, itemListElement (array of ListItem objects, each with position, name, item URL)
AggregateRating / Review
AggregateRating: ratingValue, reviewCount (or ratingCount), bestRating, worstRatingReview: author (Person), reviewRating (ratingValue), reviewBody, datePublished
Use schema-generator.html to produce compliant JSON-LD for all five types above without hand-writing code. See that tool for field-by-field generation.
