Drain Cleaning
Clears clogs fast with HD camera inspection and honest written estimate.
Learn More →Everything you need to design the BSP location-page template: strategy, competitor intel, 10x local-SEO moves, 14-section architecture, 8-layer schema stack, per-city differentiation pattern, 15-city tier order, brand tokens, Figma specs, asset manifest. Mobile-first. One template multiplies to 45 indexable pages (15 cities × 3 services). Inherits 100% from the Homepage Redesign Playbook design system.
Skip the strategic / API sections for Phase 1 design. Here is the shortest path from zero to a production-ready Figma frame.
If you see [City] in any spec, it is a placeholder substituted from the city data object at build time. Use Overland Park for every Phase 1 Figma frame.
Audrey designs the 20% that carries the brand (hero, Why BSP). Bricks AI generates the 80% (trust bar, map, service grid, reviews grid, FAQ, CTA). Naming convention for Figma frames: NN_type_descriptor aligned with the § number in each section spec (e.g. 01_section_hero, 04_section_services_grid).
Header + Footer are off-limits for Audrey. Global Bricks components already ship on every page. She does not design them in Figma. Numbering starts at the first content section.
Prompt modes: Per-Section (one frame at a time) or Whole-Page Prompt Pack (all sections bundled, Figma-flagged frames marked “drop your Figma export, do not regenerate”).
→ Open the full 3-tool workflow diagram + 5 wiring steps
Audrey hands Figma to Robert. Robert manually assembles the location-page template in Bricks, wires city-data JSON loop, Google Maps iframe, live fleet badge. Same process as the existing /sewer-camera-inspection/ page.
| First template build | 3 to 4 hours |
| Each additional city | 15 to 20 min copy via city-data JSON |
| Tool cost | $0 |
| Approval | Already approved (default) |
| Risk | Known. Same pattern as existing sewer-camera-inspection build. |
| Robert availability | Blocks other work for the sprint week |
Audrey designs the hero + unique 20% in Figma. Robert prompts Bricks AI Studio for the repeating 80% (trust bar, map, service grid, reviews grid, FAQ, CTA). Claude Design handles the Stephanie weekly deck. City-data JSON loop unchanged.
| First template build | ~1.5 hours |
| Each additional city | 5 min copy via city-data JSON |
| Tool cost | $40 / month (cancel-safe monthly) |
| Approval | Pending — Stephanie yes/no |
| Risk | Bricks AI Studio is live but third-party. Revert to A if output fails Audrey review on Tuesday pilot. |
| Robert availability | Keeps ~22 hrs this sprint for Smart Bidding, Daniel fixes, ST attribution |
| Switch | Trigger | What happens to already-shipped city pages |
|---|---|---|
| Stay A all week | No approval received | Everything manual. Sprint may miss end-of-next-week goal. Default path, no action needed. |
| All B from Tuesday | Stephanie greenlights Monday night or Tuesday AM | Cities shipped Monday stay as A. Everything Tuesday onward flips to B. |
| A to B mid-week | Approval arrives mid-week | Keep cities shipped on A. Remaining cities flip to B. No rebuild of shipped work. |
| B to A mid-week | Bricks AI output fails Audrey quality gate Tuesday EOD | Cancel $40 sub. Revert all subsequent cities to manual. Shipped hybrid cities stay live. |
GViYd2jKWUEpLbz1lWghby, mobile 722:55, desktop 707:14). Don’t patch a warped tree. If a Bricks template drifts from the Figma spec, rebuild that section from Figma, do not keep patching. This is why the sewer camera page hit 5 rebuild cycles before v6 matched 1:1.
Location pages are not homepage clones with the city swapped. They are local-SEO weapons. Google rewards pages that prove the business serves a specific place: city in H1, neighborhoods in body, landmarks in copy, reviews filtered by city, schema with areaServed + GeoCircle, and differentiation that reads like a human who lives there wrote it. Phase 1 ships 4 T1 cities with 1 service each (4 pages). Phase 2 multiplies to 45 (15 cities × 3 services).
Location-page traffic is 70%+ mobile (Emergency Eric searches on a phone, standing over a leak). Every section is designed at 375 px first. If it does not work one-handed in a dark basement at 11 PM, it does not ship.
| Name | Range | Figma frame | Location-page notes |
|---|---|---|---|
| 📱 Mobile S | 320–477 px | 375 × 812 | Primary design target. Emergency stack (sticky bar, hero CTA, trust bar, availability) must fit in 2 viewports. |
| 📲 Mobile L | 478–767 px | 414 × 896 | Identical to S, wave divider on. |
| 📐 Tablet | 768–991 px | 768 × 1024 | 2-col neighborhoods grid, still hamburger. |
| 💻 Desktop | 992+ px | 1440 × 8500 | Embedded map + neighborhoods side-by-side, 3-col before/after. |
See Homepage Playbook § Figma Guide for full specs — H1 32/48 · H2 26/36 · H3 20/24 · Body 16/18 · 8-px spacing base · the same 8 Figma symbols (Primary CTA, Secondary CTA, Phone CTA, Service Card, Review Card, Trust Chip, FAQ Row, Wave Divider). Location pages add 2 new components:
Fourteen reusable components that power every section of the Location Pages template. Each spec is self-contained: purpose, anatomy, variants, responsive sizes, tokens, motion, accessibility, exact Figma component name Audrey will publish, which sections consume it, the build-side HTML pattern Robert ships, and the CSS custom-property values. If a section needs something, it pulls from this catalog. No one-off styling. Phase 1 = must-ship on the first 4 T1 pages. Phase 2 = polish or data-driven layer.
--blue #30C5FF, color --navy #1D1760, shadow cta, radius 8, hover bg darkens to #27AEDE#FFEA00 + 2px offsetrole="button" implicit on <button>. Keyboard Enter/Space. prefers-reduced-motion: no transform, opacity only.Button/Primary/Default, Button/Primary/Hover, Button/Primary/Pressed, Button/Primary/Disabled, Button/Primary/Focus, Button/Primary/Loading<a class="btn btn--primary" href="/book/?city=overland-park">Book Now →</a>--btn-primary-bg: #30C5FF; --btn-primary-color: #1D1760; --btn-primary-radius: 8px; --btn-primary-shadow: 0 4px 4px rgba(0,0,0,0.15); --btn-primary-pad: 12px 20px;transparent, color --navy, border 1.5px #1D1760; inverted bg transparent, color --white, border 1.5px #FFFFFF--navy + color flip to white, 150ms ease-out · focus ring 2px #FFEA00 + 2px offsetButton/Secondary/Default, Button/Secondary/Hover, Button/Secondary/Inverted, Button/Secondary/Focus<a class="btn btn--secondary" href="#daniel">Chat with Daniel</a>--btn-secondary-border: 1.5px solid #1D1760; --btn-secondary-color: #1D1760; --btn-secondary-hover-bg: #1D1760; --btn-secondary-hover-color: #FFFFFF;--yellow #FFEA00, color --navy #1D1760, shadow cta, radius 8, hover darkens to #E6D300#1D1760<a href="tel:..."> for dial on mobile. aria-label "Call Bright Side Plumbing at 9 1 3, 9 6 3, 1 0 2 9." Keyboard Enter.Button/Phone/Default, Button/Phone/Hover, Button/Phone/Compact, Button/Phone/Pulse<a class="btn btn--phone" href="tel:+19139631029" data-gtm="phone-cta-hero">📞 (913) 963-1029</a>--btn-phone-bg: #FFEA00; --btn-phone-color: #1D1760; --btn-phone-radius: 8px; --btn-phone-font: 17px/1 'Inter', sans-serif; --btn-phone-weight: 800;--ivory #F8FAFC, border 1px #E5E7EB, radius 12, shadow-rest 0 2px 8px rgba(0,0,0,0.04), shadow-hover 0 8px 24px rgba(29,23,96,0.12)Card/Service/Icon, Card/Service/Photo, Card/Service/Badge, Card/Service/Featured, Card/Service/Hover<article class="service-card service-card--featured"><span class="service-card__badge">Most Requested</span><img class="service-card__icon" .../><h3>Sewer Repair</h3><p>...</p><a>Learn More →</a></article>--card-bg: #F8FAFC; --card-border: 1px solid #E5E7EB; --card-radius: 12px; --card-pad: 20px; --card-shadow-rest: 0 2px 8px rgba(0,0,0,0.04); --card-shadow-hover: 0 8px 24px rgba(29,23,96,0.12);Camera inspection first, trenchless when we can, always a written quote.
Learn More →Repair or replacement, tank or tankless, with same-day service in KC metro.
Learn More →--ivory, border 1px #E5E7EB, radius 12, stars color #FFB800, quote mark opacity 0.08 navyCard/Review/Google, Card/Review/Yelp, Card/Review/Angi, Card/Review/BBB, Card/Review/Featured<article class="review-card review-card--google"><span class="review-card__badge">Google</span><div class="review-card__stars">★★★★★</div><p>...</p><footer><b>Sarah M.</b> · <span class="chip chip--city">Overland Park</span></footer></article>--review-bg: #F8FAFC; --review-radius: 12px; --review-star-color: #FFB800; --review-badge-google: #4285F4; --review-badge-yelp: #D32323; --review-badge-angi: #A3D65C;Not enough kind words for these gentlemen who worked on our new sewer line. Chris, Bradley, and Trevor were exceptional. Would hire again in a heartbeat.
--ivory, border 1px rgba(29,23,96,0.08), radius 8, icon bg solid #1D1760 (default) / #30C5FF (accent-blue) / #FFEA00 (accent-yellow) / #22C55E (accent-green). No gradients — Kalen preference lock Apr 21.aria-hidden="true". Title and body text are the semantic content. Keyboard-navigable only if card is a link.Card/Reveal/Default, Card/Reveal/Hover, Card/Reveal/Blue, Card/Reveal/Yellow, Card/Reveal/Green<div class="reveal reveal--blue"><span class="reveal__icon">🛡️</span><div class="reveal__text"><h4>Licensed & Insured</h4><p>...</p></div></div>--reveal-bg: #F8FAFC; --reveal-radius: 8px; --reveal-pad: 12px; --reveal-icon-size: 32px; --reveal-icon-bg: #1D1760; --reveal-icon-bg-blue: #30C5FF; --reveal-icon-bg-yellow: #FFEA00; --reveal-icon-bg-green: #22C55E; --reveal-gap: 12px;KCMO + Johnson County plumbing licenses, full liability coverage.
Book before 2 PM, we are there today. Overland Park, Olathe, Lenexa, Shawnee.
Burst pipe at 2 AM? We dispatch in 5 minutes, on-site in 60.
We are late, you are paid. Plus $200 clean-tech guarantee every visit.
rgba(48,197,255,0.12), color --navy, border 1px #30C5FF; inverted bg rgba(255,255,255,0.12), color --white, border 1px rgba(255,255,255,0.4)Chip/Trust/Default, Chip/Trust/Inverted, Chip/Trust/Yellow, Chip/Trust/Green<span class="chip chip--trust">⭐ 4.9 Google (384+)</span>--chip-trust-bg: rgba(48,197,255,0.12); --chip-trust-color: #1D1760; --chip-trust-border: 1px solid #30C5FF; --chip-trust-radius: 4px; --chip-trust-pad: 4px 10px;rgba(48,197,255,0.12), border 1px solid #30C5FF, color --navy #1D1760, radius 999px#30C5FF, color #FFFFFF, translateY(-1px), transition 150ms ease-out#1D1760, color #FFFFFF, border 1px solid #1D1760 (you-are-here signal)#22C55E with 1.2s pulse, plus "45m" 11w700 text right of dot#FFEA00 + 2px offsetChip/City/Default, Chip/City/Hover, Chip/City/Current, Chip/City/Available, Chip/City/Visited, Chip/City/Focus<a class="chip chip--city" href="/plumber/overland-park/" data-city="overland-park">📍 Overland Park</a>--chip-city-bg: rgba(48,197,255,0.12); --chip-city-border: 1px solid #30C5FF; --chip-city-color: #1D1760; --chip-city-radius: 999px; --chip-city-pad: 4px 12px; --chip-city-hover-bg: #30C5FF; --chip-city-hover-color: #FFFFFF; --chip-city-current-bg: #1D1760; --chip-city-current-color: #FFFFFF; --chip-city-available-dot: #22C55E;--white, border-bottom 1px #E5E7EB, question color --navy, answer color #475569, icon color --blueFAQ/Row/Collapsed, FAQ/Row/Expanded, FAQ/Row/Hover, FAQ/Row/Focus<details class="faq-row"><summary>How fast can you get to Overland Park?</summary><div class="faq-row__body">Same-day service, averaging 45 minutes...</div></details>--faq-bg: #FFFFFF; --faq-border: 1px solid #E5E7EB; --faq-q-color: #1D1760; --faq-a-color: #475569; --faq-icon-color: #30C5FF; --faq-pad: 16px; --faq-transition: 220ms ease-in-out;aria-hidden="true". No semantic value. Do not use as a heading separator.Divider/Wave/Top, Divider/Wave/Bottom, Divider/Wave/Full, Divider/Wave/Navy, Divider/Wave/Ivory<svg class="wave wave--bottom" viewBox="0 0 1440 80" preserveAspectRatio="none" aria-hidden="true"><path d="M0,40 C360,80 1080,0 1440,40 L1440,80 L0,80 Z" fill="#F8FAFC"/></svg>--wave-h-mobile: 40px; --wave-h-tablet: 60px; --wave-h-desktop: 80px; --wave-fill: inherit;transform:scaleY(-1) for convex-up variant.--navy, number color --yellow, title color --navy, body color #475569, connector 2px dashed #1D1760Tile/Step/Default, Tile/Step/Active, Tile/Step/Complete, Tile/Step/WithImage<li class="step-tile step-tile--active"><span class="step-tile__num">1</span><h4>Call or book online</h4><p>...</p></li>--step-circle-size: 48px; --step-circle-bg: #1D1760; --step-circle-color: #FFEA00; --step-title-color: #1D1760; --step-body-color: #475569; --step-gap: 16px;Daniel or our office answers in 15 seconds. Book a slot same-day.
Licensed tech on the road in 5 minutes. You see live ETA on the map.
Written estimate before we touch anything. No surprises. No upsell.
--navy, phone bg --yellow, book bg --blue, both text color --navy, radius 0 (full-bleed bar)env(safe-area-inset-bottom) for iPhone home bar. Each CTA aria-labeled. Hidden from screen readers when off-screen via aria-hidden toggle. Keyboard Tab reaches both CTAs.Bar/Sticky/Mobile/Default, Bar/Sticky/Mobile/Emergency, Bar/Sticky/Mobile/Hidden<aside class="sticky-bar"><a class="sticky-bar__phone" href="tel:...">📞 Call</a><a class="sticky-bar__book" href="/book/">📅 Book</a></aside>--sticky-bar-bg: #1D1760; --sticky-bar-height: 64px; --sticky-bar-safe: env(safe-area-inset-bottom); --sticky-bar-z: 100; --sticky-bar-shadow: 0 -4px 12px rgba(0,0,0,0.12);#30C5FF · white droplet icon 💧 32×32 centered · subtle pulse ring every 8s · optional red notification badge top-right--blue, icon --white, pulse ring rgba(48,197,255,0.4), panel header --navy, message area --ivory, user bubble --blue, AI bubble --white w/ bordere2920d04 · phone line (913) 963-9817 · webhook /api/daniel/book on VM · storm-alerts Slack DM to Ashton (10s SLA)Widget/Daniel/Bubble, Widget/Daniel/Panel/Open, Widget/Daniel/Panel/Typing, Widget/Daniel/Panel/Offline, Widget/Daniel/Mobile/Fullscreen<div id="daniel-widget" data-vapi-assistant="e2920d04" data-city="overland-park"></div> (hydrated by JS)--daniel-bubble-bg: #30C5FF; --daniel-bubble-size: 64px; --daniel-panel-w: 380px; --daniel-panel-h: 560px; --daniel-header-bg: #1D1760; --daniel-msg-bg: #F8FAFC; --daniel-pulse: rgba(48,197,255,0.4);e2920d04 hydrated on mount. aria-live="polite" on message area for screen readers. Respects prefers-reduced-motion.1px #CBD5E1, active border 1.5px #30C5FF, completed border 1.5px #22C55E, error border 1.5px #EF4444, radius 8, bg --white, text --navyForm/Field/Idle, Form/Field/Active, Form/Field/Completed, Form/Field/Error, Form/Field/Select, Form/Field/Textarea<div class="field field--active"><label for="phone">Phone</label><input id="phone" type="tel" autocomplete="tel" placeholder="(913) 555-0123"><span class="field__valid">✓</span></div>--field-h: 48px; --field-radius: 8px; --field-bg: #FFFFFF; --field-border-idle: 1px solid #CBD5E1; --field-border-active: 1.5px solid #30C5FF; --field-border-done: 1.5px solid #22C55E; --field-border-err: 1.5px solid #EF4444; --field-label-color: #1D1760;Which component shows up in which location-page section. Audrey uses this to confirm every section has its components inventoried; Robert uses this to confirm every build task pulls from the library (not from scratch).
| Section | Primary components | Supporting |
|---|---|---|
| § 01 Sticky Emergency Bar | Phone CTA (compact) | Trust Chip (city name) |
| § 02 City Hero | Primary CTA · Phone CTA · Secondary CTA | Trust Chip · Reveal Card (availability) |
| § 03 Embedded Map | — | Wave Divider |
| § 04 Trust Bar | Trust Chip (×6) | — |
| § 05 Live Availability | Reveal Card (green accent) | Phone CTA · City Chip (available variant) |
| § 06 Services in [City] | Service Card (featured + 5 default) | Wave Divider |
| § 07 City-Filtered Reviews | Review Card (Google · Yelp · Angi) | City Chip (in review footer) |
| § 08 How It Works | Step Tile (×3) | — |
| § 09 Neighborhoods Served | City Chip (neighborhood variant, 8–12) | — |
| § 10 Local Landmarks | Reveal Card (optional) | — |
| § 11 Before/After Gallery (P2) | Service Card (photo variant) | City Chip (street/city tag) |
| § 12 Financing + Guarantees | Reveal Card (guarantees ×3) | Primary CTA (Apply) |
| § 13 City FAQ | FAQ Accordion Row (×6) | — |
| § 14 Nearby Cities | City Chip (×5-6, clickable) | — |
| § 15 Final CTA + Form | Multi-Step Form Field · Primary CTA · Phone CTA | Wave Divider |
| Floating (all pages) | Sticky Mobile Call Bar · Daniel AI Chat Widget | — |
prefers-reduced-motion — disable transform, keep opacity onlyMobile scroll flow. Every section does ONE job and serves at least one of the 10 ranking signals. Visitor lands, sees emergency proof, scrolls sales conversation, closes. Each section is labeled with which persona it targets primarily.
File: /opt/nexus/nexus/scripts/output/location_library.json (single source of truth). Consumed by the build pipeline at Zone A (prep) to populate city-specific slots in the cloned template.
overland-park (the gold standard). Every field is required; do not leave any blank.location_library.json, and runs the schema-lint before commit.(target_post_id, city_slug). 30–60 min end-to-end.{
"slug": "overland-park",
"name": "Overland Park",
"state": "KS",
"lat": 38.9822,
"lng": -94.6708,
"zip_primary": "66213",
"zip_range": ["66204", "66206", "66207", "66210", "66211", "66212", "66213", "66214", "66221", "66223", "66224", "66251"],
"tier": 1,
"neighborhoods": [
"Blue Valley", "Corporate Woods", "Deer Creek", "Indian Hills",
"Leabrooke", "Nottingham", "Oak Park", "Sycamore Hills",
"The Village", "Wilshire Farms"
],
"landmarks": [
"Oak Park Mall",
"Deanna Rose Children's Farmstead",
"Overland Park Arboretum",
"Corporate Woods",
"Town Center Plaza"
],
"housing_stock_note": "Homes along 151st and Metcalf are often built on Kansas clay soil that shifts enough to crack old cast iron sewer lines.",
"common_issue": "Slow-draining sewers from root intrusion in older cast iron.",
"hero_image_asset_id": 1234,
"nearby_cities": ["leawood", "prairie-village", "lenexa", "olathe"],
"review_filter_patterns": [
"overland park", "op", "blue valley", "corporate woods", "deer creek",
"indian hills", "leabrooke", "oak park", "town center", "arboretum"
],
"meta_title": "Plumber in Overland Park KS | Sewer Repair | Bright Side Plumbing",
"meta_desc": "Sewer repair, drain cleaning, water heater service in Overland Park KS. 5th-generation family plumber. Same-day. Call (913) 963-1029.",
"phase": 1
}
Field rules: neighborhoods must be 8–12 real entries (Google checks). landmarks 3–5 recognizable places. review_filter_patterns case-insensitive regex patterns that catch real review mentions. hero_image_asset_id is the WP media ID after Audrey's hero photo is uploaded (Figma export → WP /wp/v2/media).
Every spec below pulls from this data object. When Audrey sees [City] in a spec, it's a placeholder substituted from data.name. When she sees [Landmark X], it's data.landmarks[N].
Per-section brief. Audrey reads this and designs knowing purpose, KPI, copy, mobile layout, desktop layout, components used, phase, inheritance. Cross-references the Homepage Playbook for shared components.
Same-day service across Overland Park and nearby. Licensed, insured, family-owned since the 1800s.
Same-day service across Overland Park and nearby. Licensed, insured, family-owned since the 1800s.
GeoCircle.Serving all of Overland Park and surrounding neighborhoods.
data-availability-city="..." Overland Park homes along 151st and Metcalf sit on Kansas clay that shifts enough to crack old cast iron. We’ve run trenchless inspections from Oak Park Mall to the newer builds south of 179th…
Overland Park homes, especially along 151st and Metcalf, are often built on clay soil that shifts and cracks old cast iron lines...
[city name] OR any of the 8–12 neighborhood names OR any of the 3–5 landmark names from the data object. Case-insensitive.service_page_reviews_apply.py extended to accept --filter-city=[city] arg From Blue Valley to Wilshire Farms, we’ve fixed pipes on every side of Overland Park.
From Blue Valley to Wilshire Farms, we’ve fixed pipes on every side of Overland Park.
Whether you’re near Oak Park Mall, around Deanna Rose Children’s Farmstead, or out by the Overland Park Arboretum, our crew knows the streets. We’ve pulled roots out of sewer lines from the older trees around Corporate Woods and swapped water heaters in the new construction off 179th.
nearby_cities[]. Example (Overland Park): Olathe · Lenexa · Leawood · Shawnee · Prairie Village · MissionAlso serving Overland Park’s neighbors:
Each chip links to its own /plumber-in-[slug]/ URL — exact-match anchor text for internal link equity.
Location pages inherit from two sources: the Homepage Playbook (design system) and the live Sewer-Camera Inspection page (component patterns). This playbook does NOT redefine shared tokens. It adds only location-specific additions.
| Component / Pattern | Source | Use here |
|---|---|---|
| Trust Bar (6 chips) | Homepage Playbook § 02 | § 04 verbatim |
| Service Card (icon + H3 + body + link) | Homepage Playbook § 04 | § 06 verbatim |
| Financing Card | Homepage Playbook § 05 | § 12 verbatim |
| Review Card + live Google Reviews API | Homepage Playbook § 10 + sewer page | § 07 plus city regex filter |
| Step Tile 3-step "How It Works" | Homepage Playbook § 07 | § 08 verbatim |
| Guarantee Tile (3-up) | Homepage Playbook § 11 | § 12 verbatim |
| FAQ Accordion Row | Homepage Playbook § 12 / sewer page 601ec0 | § 13 with city-specific questions |
| Multi-Step Form + wave-to-footer | Homepage Playbook § 13 | § 15 with city pre-filled |
| Footer (global, shipped Apr 17) | Homepage Playbook § 14 | Auto-inherits, no work |
| Daniel AI Chat Widget (floating) | Homepage Playbook floating | Same |
| Mobile Sticky Call Bar | Homepage Playbook floating | Same |
| Type scale, spacing scale, color tokens, motion | Homepage Playbook § Figma Guide + § Tokens | Identical |
| Element | Bricks ID | Use here |
|---|---|---|
| Hero subtitle band + underline doodle scheduling | herosub1, f97bb8, 6365c4, 37fbb3, 221286 | § 02 H1 underline behind "Plumber in [City]" |
| Process-steps wave-bg block | #brxe-5a5ec7 | § 08 How It Works background |
| Review card anatomy (F8FAFC / 422h / 5-star 120×30) | #brxe-172d71, #brxe-5202df | § 07 Review grid |
| FAQ accordion pattern | #brxe-601ec0 | § 13 FAQ |
| Final-CTA wave-to-footer transition | sewer page § 09 | § 15 wave |
Each T1 city gets a dedicated shoot slot. Fallbacks use generic KC-metro imagery with alt text specifying the city context until real shoots happen.
| # | Shot per city | Format | Where it goes |
|---|---|---|---|
| 1 | Branded BSP truck on a real street in the city | 2560×1440 + 768×1024 crop | § 02 hero bg |
| 2 | Landmark shot (Oak Park Mall for OP, Olathe Community Center for Olathe, etc.) | 1600×1200 | § 10 landmark block (optional) |
| 3 | Tech performing sewer camera inspection in a recognizable city home | 1600×1200 | § 06 services card · § 11 gallery |
| 4 | Before/after pair from a real job in the city (×3 per city minimum) | 1200×1200 each | § 11 gallery (Phase 2) |
| 5 | Neighborhood street identifier (Blue Valley sign, etc.) | 1200×800 | § 09 neighborhoods grid (optional) |
Same 4 personas from the Homepage Playbook (derived from 301+ reviews across 6 platforms). Location pages skew even harder toward Emergency Eric because that traffic is keyword-triggered by panic ("emergency plumber Olathe," "sewer repair Overland Park now") and almost always mobile. Rachel and Bob land here too via research queries. Mike lands here when Google serves the "nearest plumber" answer for his neighborhood.
| Persona | Location-Page Share | State of Mind | Design Implication |
|---|---|---|---|
| 🚨 Emergency Eric/Erica | 60%+ of location-page traffic | Panic, same-day, mobile, 11 PM searches, pipe is leaking right now | Sticky emergency bar at top · phone number above fold · "techs available in [city] today" live module · 45-min response time prominent |
| 🏗️ Renovation Rachel/Ryan | 20% of traffic | Researches contractors in their specific neighborhood, wants local proof | City-filtered reviews · before/after gallery geotagged · neighborhood list visible · FAQ with city-specific pricing |
| 🏢 Business Owner Bob/Barbara | 5–8% of traffic | Commercial property in specific city, zero disruption | Commercial badge · "licensed in [city]" permit proof · SLA language in FAQ |
| 🔁 Maintenance Mike/Maria | 10–12% of traffic | Discovers us via "plumber in [neighborhood]" then books routine work | Nearby-city links at bottom for return visits · financing card · neighborhood list triggers recognition |
| Problem | Impact | Severity |
|---|---|---|
| 📍 No city-specific landing pages exist today | Anthony / Roto / BenFranklin capture 100% of "plumber in [city]" traffic | 🔴 Critical |
| 👤 Service Areas section on homepage = chip grid with no landing targets | Kills the Phase 2 play before it starts | 🔴 Critical |
🧮 No Plumber schema with areaServed + GeoCircle | Google cannot confirm geographic service radius per city | 🟡 High |
🏛️ No sameAs Wikidata linking to OP / Olathe / Lenexa entities | Missing entity-based AI-search signal | 🟡 High |
| 📷 No city-filtered reviews | Generic review pool ignores local specificity Google rewards | 🟡 High |
| 📋 No FAQ per city | No rich-result FAQPage real estate per location | 🟡 High |
Analyzed April 17, 2026. Focus is the location-page layer specifically: do they have per-city pages, do they use Plumber schema with areaServed, do they filter reviews by city, do they use landmark-anchored copy. Anything I can't verify with source I mark as unknown rather than invent.
| Competitor | Has City Pages? | Schema | Landmark Copy? | Weakness we exploit |
|---|---|---|---|---|
| Anthony PHC | ✅ /service-areas/* (one per KC metro city) | LocalBusiness generic, no areaServed GeoCircle verified | ❌ Generic corporate copy swapped per city | Template-feel, no family faces, no landmark anchors |
| Benjamin Franklin KC | ✅ Franchise city list, thin pages | Standard franchise LocalBusiness schema | ❌ None — boilerplate national copy | Franchise feel, cookie-cutter, no real neighborhood names |
| Roto-Rooter KC | ✅ Massive location directory | LocalBusiness + coverage list (scale) | ❌ No — faceless national strings | Zero local story, no crew photos, generic reviews |
| Kevin Ginnings | ❌ Homepage only, no city pages confirmed | Unknown / weak | ❌ | No structural presence — free real estate for us |
| Inception Plumbing | ⚠️ Partial — a few service-area URLs, unclear depth | Unknown — not verified this session | ❌ Not observed | "Truly local" brand voice without the schema or per-city depth to back it up |
| Signal | Anthony | BenFrank | Roto | Ginnings | Inception | BSP target |
|---|---|---|---|---|---|---|
| Per-city landing page | ✅ | ✅ | ✅ | ❌ | ⚠️ | ✅ P1 ship |
Plumber schema + areaServed + GeoCircle | ⚠️ | ⚠️ | ⚠︐ | ❌ | ❌ | ✅ MOAT — 8-layer stack |
sameAs Wikidata city linking | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ 10x MOAT |
knowsAbout specialty signals | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ 10x MOAT |
| City-filtered reviews | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ MOAT |
| Landmark-anchored opener copy | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ MOAT |
| Live "techs available in [city]" module | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ 10x MOAT |
| Before/after gallery with street name | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ P2 10x |
| Neighborhood grid (8–12 names per page) | ⚠️ generic | ❌ | ⚠︐ generic | ❌ | ❌ | ✅ P1 ship |
| City-specific FAQPage schema | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ P1 ship |
These are the signals the template must hardcode. Every section the designer ships maps to at least one of these signals. If a section doesn't serve a signal, it doesn't exist.
| # | Signal | Where the template proves it |
|---|---|---|
| 1 | 📍 GBP claimed, categorized, active | Off-page — Robert maintains GBP. Page links to GBP profile in footer and embed. |
| 2 | 📎 NAP consistency (Name / Address / Phone) | Header + footer + schema all reference 12022 Blue Valley Pkwy, Overland Park, KS 66213 / (913) 963-1029. No variants. |
| 3 | ⭐ Reviews containing city + keyword | § 05 pulls reviews where body contains [city] OR [service keyword], regex filter via live Google Reviews API. |
| 4 | 💬 Reviews with owner responses | Review card includes owner-response field when present. Signal that BSP actually engages. |
| 5 | 📄 On-page keyword + city in title, meta, H1, H2, body | Title "Plumber in [City] KS | Sewer Repair | Bright Side Plumbing" · H1 "[Service] in [City]" · H2s repeat city naturally. |
| 6 | 🧮 Schema (LocalBusiness/Plumber + Service + FAQ + Breadcrumb) | 8-layer stack in § Schema section of this playbook. |
| 7 | 📱 Mobile-first + Core Web Vitals LCP < 2.5s | All imagery lazy, hero as <img> with srcset, no CSS-bg hero, CLS < 0.1. |
| 8 | 🔗 Domain authority + inbound links | Off-page — but "Linktations" (civic sponsorship) is the Phase 2 play. Template provides stable URLs worth linking to. |
| 9 | 📡 Local inbound links with city+keyword anchor text | Chamber, BBB, partnerships, civic sponsorships — each can point anchor "plumber in Overland Park" to /plumber-in-overland-park/. |
| 10 | 📍 Proximity (GBP + NAP reinforcement) | Schema's GeoCircle geoRadius matches GBP service area. Consistency tells Google the business is real here. |
| # | 10x Play | Why it beats every KC competitor | BSP Asset |
|---|---|---|---|
| 1 | 🔗 Wikidata sameAs entity linking per city | Every city has a Wikidata ID (Overland Park = Q2030450, Olathe = Q1131380). Google connects our page to the city entity. Nobody else does this. | Schema layer — zero cost, 100% lift. |
| 2 | 🧠 knowsAbout specialty declarations | Declares Plumber knowsAbout Trenchless, Hydro-Jetting, Backflow. AI search (Gemini, Perplexity) reads this directly. | Schema layer — future-proof for LLM search. |
| 3 | 🌁️ Live availability module | "Techs available in Olathe today · 45-min avg response." Pulls from ServiceTitan dispatch. No competitor shows this. | ST dispatch API feasible — placeholder in template for Phase 2. |
| 4 | 🎥 Reviews filtered by city + keyword | Competitors show the same 3 reviews on every city page. Ours pulls reviews whose body contains the city or neighborhood name. | service_page_reviews_apply.py already wired. |
| 5 | 🏛️ Landmark-anchored copy | Opening paragraph references real places (e.g., "from the shops at Oak Park Mall to the homes along 151st Street"). No competitor does this at scale. | Per-city data object — 3–5 landmarks each. |
| 6 | 📥 Service × city matrix (45-page build) | Phase 2 multiplies to 15 cities × 3 services. Anthony has service-area pages but NOT service × city permutations. | Template driven by city-data + service-data objects. |
| 7 | 🪙 "Linktations" via civic sponsorship | Chamber memberships, Little League sponsorship, civic donations each yield an inbound link with city+keyword anchor. | Stephanie's relationships — Phase 2 outreach. |
| 8 | 🚨 Emergency conversion stack in first 2 viewports | Sticky red bar + availability + response time + financing + guarantee visible before any scroll. Competitors bury these. | Figma design spec in Section 01–05. |
| 9 | 📷 Before/after gallery with street names | Each photo tagged with neighborhood. Proof the crew has literally been on this street. Nobody does this. | HCP / ServiceTitan photo pull — Phase 2. |
| 10 | 📍 GBP per-city areaServed + GeoCircle alignment | Page schema GeoCircle matches GBP service area polygon. Tight consistency = strong proximity signal. | Robert wires Schema — zero design work. |
Every city page carries one small chip near the hero: green dot, city name, approximate ETA, crew count. That chip is the conversion hinge for Emergency Eric. This section shows the data sources, APIs, privacy rules, 3-rung ladder, component spec, cost ceiling, rollout phases, KPIs, and risk mitigation that make it real. Treat it as a standalone strategic brief inside the playbook.
Each signal a user sees on a city page needs the right grain. Too coarse and the badge feels fake. Too precise and we expose technician location, which breaks privacy and invites stalking risk.
| Signal shown on city page | Precision required | Privacy risk |
|---|---|---|
| "Is a crew working in this city today?" | Binary yes/no | None |
| "Approx ETA to this city from current fleet" | ±10–15 min buckets | None if grain-blurred |
| "Crews active in your territory" | Rough count (1, 2, 3+) | None |
| "Live map pin of a truck" | True GPS coordinates | HIGH, never render on public page |
Each rung unlocks more precision. Each one also costs more to operate. Ship Rung 1 immediately; earn the right to Rung 2 by proving conversion lift; earn Rung 3 only if dispatch desk demands a real-time operator view.
Three data sources feed one cron, which writes one JSON, which fans out to four consumers. Everything is cached aggressively so Google Maps API spend is bounded.
rgba(255,255,255,0.06), border 1px rgba(48,197,255,0.25), radius 999, text --white, eta text --blue-soft, dot-green #22C55E, dot-amber #F59E0B, dot-red #EF4444Chip/City/Available, Chip/City/Limited, Chip/City/BookedOut, Chip/City/Stale, Chip/City/AfterHours<a class="chip chip--city chip--available" href="/plumber/overland-park/"><span class="chip-dot"></span>Overland Park<span class="chip-eta">~45 min</span></a>--chip-bg: rgba(255,255,255,0.06); --chip-border: 1px solid rgba(48,197,255,0.25); --chip-radius: 999px; --chip-dot-green: #22C55E; --chip-dot-amber: #F59E0B; --chip-dot-red: #EF4444; --chip-pulse-ms: 2400ms;/api/fleet/availability/{city-slug}. 60s browser cache. If response stale (>2h) or error, falls back to "stale" variant automatically.| Rung | One-time build | Monthly run-rate | Year 1 total | Includes |
|---|---|---|---|---|
| Rung 1 ST schedule | ~8 hrs Robert | $0 | $0 new cash | Cron + endpoint + chip hydration, reuses existing ST API access |
| Rung 2 Tech PWA + Maps | ~40 hrs Robert | $40–$80 API + $8 PWA hosting | ~$600–$1,050 | PWA build, Distance Matrix, Geocoding, cache layer, fallback logic |
| Rung 3 Hardware GPS | ~60 hrs + $15–$30/truck | $8–$15/vehicle + $20 server | ~$1,800–$3,000 (8 trucks) | Sinotrack or Traccar units, install, Traccar server, dispatch console UI |
| 3-year ceiling (all rungs active, 8 trucks) | – | ~$200/mo | ~$2,400/yr | Hard cap on ongoing Google Maps spend from cache model |
| Metric | Baseline | Phase 2 target | How measured |
|---|---|---|---|
| City-page click-to-call rate | ~6–10% industry avg | +15–25% lift | GA4 phone_click event per city slug |
| Form submit from city pages | baseline TBD, first 14 days | +20% lift | WP form submit + GCLID capture per city |
| "Available now" badge exposure | 0 | 100% of city page visits | /api/fleet/availability served count per slug |
| Badge accuracy | n/a | ≥85% true positives | Ashton weekly audit of 20 random claims vs ST jobs |
| Stale-fallback rate | n/a | <5% of serves | Count of stale-variant serves / total serves |
| Risk | Severity | Mitigation |
|---|---|---|
| Badge says "available," no one shows | HIGH trust | Stale-data detection: if feed >2h old, auto-fall-back to "Available today" generic variant (no ETA shown) |
| Tech privacy concern (GPS exposure) | MED | City-grain only on public surface. Coordinates never rendered. Internal tech PWA requires explicit opt-in per shift. |
| Google Maps API cost spike | LOW | 30-day origin–destination cache + $148/mo hard cap. If cap hit, script silently falls back to ST-schedule-only mode. |
| iOS background geolocation flaky | MED | Hybrid model: PWA foreground-only for Rung 2, ST schedule fallback always. Never depend on iOS background. |
| Kalen rejects GPS hardware | LOW | Rung 1 works without any hardware. Kalen does not need to be involved until Rung 3 is proposed. |
| Competitor clones the badge | LOW | Moat is the full pipeline (ST + Maps + cache + dispatch), not the UI. Copying the chip without the backend shows a fake green dot, which users catch fast. |
Each of these APIs is free or near-free and enriches the city page without any additional paid infrastructure. They plug into the same availability surface.
| API | What it gives | BSP use on location pages |
|---|---|---|
| NWS (weather.gov) | Active alerts + forecasts per ZIP, free, no key | "Freeze warning tonight in Olathe, book a pipe-inspection now" banner · Weather bidding ties back |
| Google Business Profile API | Live reviews, star avg, photos, special hours | City-filtered review pull for § 07 · auto-match GBP service area to GeoCircle schema |
| OSM Overpass | Landmarks, schools, parks, shopping centers by bbox | Auto-populate "from the shops at Oak Park Mall to…" landmark copy per city |
| USGS Water Services | Real-time stream gauges + flood alerts | "Brush Creek gauge at 5.2 ft, call about basement backup risk" dynamic alert |
| Census ACS | Housing age, median home value per tract | "Median home in Olathe is 1998, pipes from that era often…" targeted content |
/opt/nexus/titan/fleet_availability.py cron. Reads ServiceTitan jobs API (today's bookings, crew assignments, arrival windows). Buckets per city slug. Writes /opt/nexus/nexus/scripts/output/fleet_availability.json. 5-min cron. Stale-flag if >2h old./api/fleet/availability/{city-slug} and /api/fleet/status endpoints on the existing port 8765 nexus API. Response includes: state (available/limited/booked-out/stale), eta_minutes, crew_count, updated_at, fallback_reason.fleet_chip_view event per render. KPI dashboard reads the number day 1.Prior Live Fleet analysis covered Distance Matrix and Geocoding only. That was the blindspot. The full Google stack breaks into 7 categories spanning 22 APIs. Grouped below by impact per dollar for BSP's Location Pages specifically, not by Google's own taxonomy. The rule: anything free or inside Google's $200/month Maps credit that touches conversion, data quality, or SEO measurement ships in Tier A. Anything strategic but deferrable waits for Phase 3 or Phase 4.
Every API below is pre-ranked by when it earns a slot in the build. Tier A rides with the Rung 1 Fleet Badge. Tier B stacks on the Tech PWA in Phase 3. Tier C is the compounding strategic layer.
| API | Free tier | BSP Location Page use |
|---|---|---|
| Routes API v2 | 40k/mo | Traffic-aware ETA for Live Fleet Availability, replaces Distance Matrix for new builds |
| Maps JavaScript API | $200/mo credit (~28k loads) | Embed interactive service-area map per city page |
| Maps Static API | $200/mo credit | Server-render static city map image, no JS, fast LCP, stack on every City Hero |
| Places API (New) | $200/mo credit | Auto-populate landmarks and neighborhoods per city: "near Oak Park Mall, Deanna Rose, Sprint Campus" copy |
| Places Autocomplete | $200/mo credit | Customer types address, Google autocompletes, faster form conversion |
| Place Details API | $200/mo credit | Rich data about BSP GBP and competitor GBPs for competitive intel |
| Street View Static API | $200/mo credit | Show customer street: "we have been to your neighborhood" trust signal |
| Address Validation API | 10k free/mo | USPS-grade validation at form submit, catches typos, cleans ST data |
| Roads API | $200/mo credit | Snap tech PWA GPS to nearest road plus speed limit |
| API | BSP Location Page use |
|---|---|
| GBP Performance API | Per-listing impressions, searches, calls, direction requests over 90-day window. Goldmine for per-city SEO tuning |
| GBP Reviews API | Live monitor and programmatic response. Feeds City Review Card |
| GBP Q&A API | Answer "do you serve Olathe?" automatically, flag edge cases for Ashton |
| GBP Posts API | Push city-specific special offers to GBP ($25 off in Overland Park) |
| GBP Attributes API | Programmatically toggle women-owned, 24/7, accepts credit cards, and similar |
| GBP Verifications API | Manage multi-location verification when BSP opens a second location |
| API | BSP Location Page use |
|---|---|
| Search Analytics API | Which queries drive clicks to each city URL, position, CTR. Feeds H1 and meta optimization |
| URL Inspection API | Check if a city page is indexed. Detect crawl errors per slug |
| Sitemap API | Auto-submit programmatic location-page sitemaps when 45 pages ship |
| API | BSP Location Page use |
|---|---|
| GA4 Data API | Measure per-city-page conversion. Proves whether the Live Fleet badge works. Click-to-call lift per slug |
| GA4 Realtime API | Live traffic on location pages. Dispatcher sees surge and routes extra tech |
| Google Ads API | Per-campaign per-city conversion data. Best-performing cities, bid strategy |
| Google Ads Keyword Planner API | Per-city keyword volume to prioritize T1 / T2 / T3 city build order |
| API | BSP Location Page use |
|---|---|
| Gemini API | Generate unique city-page openers grounded in real soil, housing, and common-issue data. Unblocks programmatic 15-city ramp |
| Cloud Translation API | Spanish-language city pages at /es/plumber/[city]/. Feb 2026 CSV documented 2 Spanish-speaking customers lost |
| Vision API | Auto-tag plumbing job photos for city gallery (before / after classification) |
| Cloud Natural Language API | Sentiment analysis on reviews. Auto-surface 5-star reviews with specific city praise for hero testimonial placement |
| API | BSP Location Page use |
|---|---|
| YouTube Data API | Embed city-specific BSP videos on location pages (sewer camera footage, testimonials) |
| YouTube Analytics API | Which videos convert per city, inform per-city content strategy |
| API | Free tier | BSP Location Page use |
|---|---|---|
| reCAPTCHA Enterprise | 1M assessments/mo free | Form spam protection on location-page CTAs |
How the 22 APIs stack with the Live Fleet system already specced in the previous section. Every arrow is an existing or planned feed.
Conservative worst-case run cost across the 22-API stack at BSP's current scale. Assumes no special enterprise contracts, no volume commitments.
| Bucket | Monthly run cost | Year 1 worst case |
|---|---|---|
| Tier A (ships with Rung 1) | Free to ~$30/mo | ~$360 |
| Tier B (Phase 3 with Tech PWA) | +~$50/mo | +$600 |
| Tier C (Phase 4 compounding) | +~$50/mo | +$600 |
| Total stack | ~$130/mo | ~$1,560 |
Use this flow any time a new Google API surfaces in a roadmap conversation.
Every location page ships with all 8 layers. Robert wires the JSON-LD in the Bricks template. Audrey doesn't design this but must know it exists so Phase 2 animations and components don't break the structured data. Each layer below includes an example snippet Audrey (or anyone) can reference.
Plumber (not generic LocalBusiness)// Plumber is a more specific subtype than LocalBusiness. Google prefers specificity. { "@context": "https://schema.org", "@type": "Plumber", "name": "Bright Side Plumbing", "telephone": "+19139631029", "url": "https://callbrightside.com/plumber-in-overland-park/", "priceRange": "$$" }
areaServed + GeoCircle{
"areaServed": {
"@type": "GeoCircle",
"geoMidpoint": {
"@type": "GeoCoordinates",
"latitude": 38.9822, // from city data object
"longitude": -94.6708
},
"geoRadius": "10000" // meters — must match GBP service area
}
}
sameAs → Wikidata entity{
// This is the 10x MOAT: Google connects our page to the Wikidata city entity.
"sameAs": [
"https://www.wikidata.org/wiki/Q2030450", // Overland Park
"https://en.wikipedia.org/wiki/Overland_Park,_Kansas"
]
}
hasOfferCatalog{
"hasOfferCatalog": {
"@type": "OfferCatalog",
"name": "Plumbing Services in Overland Park",
"itemListElement": [
{ "@type": "Offer", "itemOffered": { "@type": "Service", "name": "Sewer Repair" } },
{ "@type": "Offer", "itemOffered": { "@type": "Service", "name": "Drain Cleaning" } },
{ "@type": "Offer", "itemOffered": { "@type": "Service", "name": "Water Heater Service" } }
]
}
}
knowsAbout (AI-search signal){
// Tells Gemini / Perplexity / ChatGPT what BSP is an expert at.
"knowsAbout": [
"Trenchless Sewer Repair",
"Hydro-Jetting",
"Backflow Prevention",
"Sewer Camera Inspection",
"Tankless Water Heater Installation"
]
}
FAQPage{
"@context": "https://schema.org",
"@type": "FAQPage",
"mainEntity": [
{
"@type": "Question",
"name": "How much does sewer repair cost in Overland Park?",
"acceptedAnswer": {
"@type": "Answer",
"text": "Sewer repair in Overland Park typically ranges from $3,000 to $15,000..."
}
}
// ... 5 more questions minimum
]
}
AggregateRating + Review{
"aggregateRating": {
"@type": "AggregateRating",
"ratingValue": "4.9",
"reviewCount": "384"
},
"review": [
{
"@type": "Review",
"author": { "@type": "Person", "name": "Homeowner in Blue Valley" },
"reviewRating": { "@type": "Rating", "ratingValue": "5" },
"reviewBody": "Called at 10 PM, they were out to Overland Park by 11..."
}
]
}
BreadcrumbList{
"@context": "https://schema.org",
"@type": "BreadcrumbList",
"itemListElement": [
{ "@type": "ListItem", "position": 1, "name": "Home", "item": "https://callbrightside.com/" },
{ "@type": "ListItem", "position": 2, "name": "Service Areas", "item": "https://callbrightside.com/service-areas/" },
{ "@type": "ListItem", "position": 3, "name": "Overland Park", "item": "https://callbrightside.com/plumber-in-overland-park/" }
]
}
Each city has one data object. The Bricks template consumes it and renders a full page. Audrey designs the template ONCE — this is how 1 template becomes 15 (Phase 1–2) or 45 pages (Phase 2 full multiplication).
{
"slug": "overland-park",
"name": "Overland Park",
"state": "KS",
"tier": 1,
"wikidata_id": "Q2030450",
"wikipedia_url": "https://en.wikipedia.org/wiki/Overland_Park,_Kansas",
"lat": 38.9822,
"lng": -94.6708,
"geo_radius_m": 10000,
"h1": "Sewer Repair in Overland Park — 5th-Generation Master Plumbers",
"meta_title": "Plumber in Overland Park KS | Sewer Repair | Bright Side Plumbing",
"meta_desc": "Sewer repair, drain cleaning, water heater service in Overland Park KS. 5th-gen family plumber. Same-day. Call (913) 963-1029.",
"opener_paragraph": "Overland Park homes, especially along 151st and Metcalf, are often built on...",
"neighborhoods": [
"Blue Valley", "Corporate Woods", "Deer Creek", "Indian Hills",
"Leabrooke", "Nottingham", "Oak Park", "Sycamore Hills",
"The Village", "Wilshire Farms"
],
"landmarks": [
"Oak Park Mall", "Deanna Rose Farmstead",
"Corporate Woods", "Overland Park Arboretum",
"Scheels Overland Park Soccer Complex"
],
"housing_stock_note": "Mix of 1970s-era tree-lined subdivisions north of I-435 and new construction south of 159th.",
"soil_note": "Kansas clay; expansive soil that shifts with moisture, stressing older cast iron sewer lines.",
"common_issue": "Tree-root intrusion into clay/cast iron sewer lines; water heater sediment from hard municipal water.",
"response_time_minutes": 45,
"nearby_cities": ["olathe", "lenexa", "leawood", "shawnee", "prairie-village", "mission"],
"review_filter_terms": [
"overland park", "op ", "blue valley", "oak park mall",
"151st", "metcalf", "corporate woods"
],
"faq": [
{
"q": "How much does sewer repair cost in Overland Park?",
"a": "Sewer repair in Overland Park typically ranges from $3,000 to $15,000 depending on line length, depth, and method (traditional dig vs. trenchless). Most of the older neighborhoods north of College Blvd see higher costs because of mature trees and cast iron pipe age. We give free on-site estimates."
},
{ // ... 5 more FAQ entries per Section 13 required types }
],
"photo_set": {
"hero": "/images/cities/overland-park/hero.jpg",
"landmark": "/images/cities/overland-park/oak-park-mall.jpg",
"neighborhood": "/images/cities/overland-park/blue-valley.jpg",
"before_after": [
{ "before": "...", "after": "...", "street": "W 151st St", "date": "2026-03-15" }
]
}
}
Phase 1 ships T1 (4 cities). Phase 2 adds T2 (5 cities). Phase 3 adds T3 (6 cities). Tier order follows search volume, revenue density, and proximity to BSP HQ.
| Tier | City | Slug | Why in this tier |
|---|---|---|---|
| T1 | Overland Park | overland-park | BSP HQ city · highest search volume · highest revenue density |
| T1 | Olathe | olathe | Second-largest KS metro population · heavy emergency-plumber search |
| T1 | Lenexa | lenexa | Adjacent to HQ · commercial + residential mix · strong GBP proximity |
| T1 | Shawnee | shawnee | Older housing stock · sewer-repair heavy · close to HQ |
| T2 | Leawood | leawood | High-income · larger ticket sizes · premium positioning city |
| T2 | Prairie Village | prairie-village | 1950s/60s housing · heavy old-cast-iron sewer work |
| T2 | Kansas City KS | kansas-city-ks | Large metro · cross-state demand · volume play |
| T2 | Gardner | gardner | Growing exurb · new construction · water heater heavy |
| T2 | Spring Hill | spring-hill | Edge-of-metro expansion · less competitor presence |
| T3 | Merriam | merriam | Smaller city · filler for cluster coverage |
| T3 | Mission | mission | Small population · cluster link equity |
| T3 | Roeland Park | roeland-park | Tight cluster around PV · internal link play |
| T3 | De Soto | de-soto | Low competition · rural-edge sewer pumps |
| T3 | Bonner Springs | bonner-springs | Western metro edge · filler |
| T3 | Edwardsville | edwardsville | Western edge · filler |
§ {section}. {element} · {city-variant} · {breakpoint}tel: link firesGeoCircle matches GBP service area polygonsameAs Wikidata URL resolves (no 404)loading="lazy" on all below-fold images| Location | URL / Path |
|---|---|
| 📚 Live playbook (this doc) | morpheus.callbrightside.com/documents/BSP_Location_Pages_Playbook.html |
| 📚 Parent playbook | BSP_Homepage_Redesign_Playbook.html |
| 📁 Local source folder | C:/Users/dovew/Documents/Clients/BrightSidePlumbing/BSP_Location_Pages/ |
| 🎨 Figma reference | Sewer Camera Inspection Landing Page + Homepage Redesign frames (Audrey's file) |
| 🧪 Live template to inherit | bricks.callbrightside.com/sewer-camera-inspection/ |
| 📚 Master History log | BSP_Master_Session_History.html |
| Asset type | Format | Why |
|---|---|---|
| Service icons (sewer, drain, water heater, gas line, camera, emergency) | SVG | Crisp at any size, tiny weight, recolorable via CSS fill: currentColor |
| Step icons (phone, truck, wrench) | SVG | Same reason — geometric shapes belong in SVG |
| Trust chip icons (BBB badge, 5-Gen, license, check) | SVG | Scale for retina, theme-tint via CSS |
| Guarantee icons (shield, clock, dollar) | SVG | Sharp on all displays |
| Hero image (plumber + customer, truck, job site) | WebP q85 + JPG fallback | Photographic, 30-40% smaller than JPG, browser support > 97% |
| Landmark photos (Oak Park Mall, Deanna Rose, Arboretum) | WebP q80 | Lazy-loaded, quality can be lower |
| Before/After photos (§11) | WebP q80 | Real job photography, lazy-loaded below fold |
| Technician headshots | WebP q85 | Small square, quality matters for trust |
| Logos (BSP logo, partner brands) | SVG | Brand assets must never pixelate |
| Wave dividers + decorative shapes | Inline SVG | Goes in HTML directly, no file round-trip, fill color tints with theme |
| Star ratings (⭐⭐⭐⭐⭐) | Unicode ★ | No image at all — HTML entity, CSS-styled color |
| Phone/email/chat glyphs in CTAs | Unicode emoji (📞 📧 💬) | Free, accessible, consistent |
| Google Map embed | iframe | Live Google service, not a static image |
| Location | Mobile size | Desktop size | SVG viewBox | Fill color |
|---|---|---|---|---|
| Service card icon (§06) | 56 × 56 | 64 × 64 | 0 0 24 24 | #1D1760 |
| Step icon (§08 How It Works) | 40 × 40 | 48 × 48 | 0 0 24 24 | #30C5FF |
| Trust chip icon (§04) | 18 × 18 | 20 × 20 | 0 0 24 24 | #30C5FF |
| Guarantee icon (§12) | 48 × 48 | 56 × 56 | 0 0 24 24 | #22C55E |
| Financing card icon (§12) | 40 × 40 | 48 × 48 | 0 0 24 24 | #1D1760 |
| FAQ chevron (§13) | 18 × 18 | 20 × 20 | 0 0 24 24 | #30C5FF |
| CTA button glyph (phone/book) | 16 × 16 | 18 × 18 | 0 0 24 24 | currentColor |
"Middle" = everything between the Hero (§02) and the Final CTA (§15). Hero dimensions are separate (see Hero Image section). Mobile-first widths; heights are fixed to keep content vertically predictable.
| Image type | Mobile (390 w) | Tablet (768 w) | Desktop (1440 w) | Aspect | Format |
|---|---|---|---|---|---|
| Google Map (§03) | 350 × 280 | 720 × 360 | 1160 × 400 | 2 : 1 (wide) | iframe |
| Service card icon (§06, ×6) | 56 × 56 | 60 × 60 | 64 × 64 | 1 : 1 | SVG |
| Review card (§07, no image, text only) | — (text card) | — | — | — | — |
| Step icon (§08, ×3) | 40 × 40 | 44 × 44 | 48 × 48 | 1 : 1 | SVG |
| Landmark photo (§10, optional ×3-5) | 350 × 230 | 360 × 240 | 380 × 250 | 3 : 2 | WebP q80 |
| Before photo (§11, ×3-4) | 350 × 260 | 360 × 270 | 480 × 320 | 3 : 2 | WebP q80 |
| After photo (§11, ×3-4) | 350 × 260 | 360 × 270 | 480 × 320 | 3 : 2 | WebP q80 |
| Financing card icon (§12) | 40 × 40 | 44 × 44 | 48 × 48 | 1 : 1 | SVG |
| Guarantee tile icon (§12, ×3) | 48 × 48 | 52 × 52 | 56 × 56 | 1 : 1 | SVG |
| Wave divider (§15 transition) | full-width × 60 | full-width × 80 | full-width × 100 | — | inline SVG |
FORMAT: bsp_loc_[city-slug]_[section]_[what]_[viewport]_[wxh]@[density].[ext] EXAMPLES: bsp_loc_overland-park_hero_main_desktop_1440x720@2x.webp bsp_loc_overland-park_hero_main_mobile_390x520@2x.webp bsp_loc_overland-park_landmark_01_oak-park-mall_desktop_380x250@2x.webp bsp_loc_overland-park_beforeafter_01_before_main-line_desktop_480x320@2x.webp bsp_loc_overland-park_beforeafter_01_after_main-line_desktop_480x320@2x.webp ICONS (shared across cities, no city slug): bsp_icon_sewer.svg bsp_icon_drain.svg bsp_icon_water-heater.svg bsp_icon_gas-line.svg bsp_icon_camera.svg bsp_icon_emergency.svg bsp_icon_step-call.svg bsp_icon_step-truck.svg bsp_icon_step-fix.svg bsp_icon_guarantee-uptime.svg bsp_icon_guarantee-warranty.svg bsp_icon_guarantee-pricing.svg bsp_icon_financing-card.svg bsp_icon_chevron-down.svg
overland-park, water-heater).bsp_loc_overland-park_hero).@2x is literal — not _2x or x2.Copy these layer names into Figma verbatim. [city-slug] is replaced per-city at build time. Top-level Figma page: BSP Location Pages - [City Name].
Frame: sec-01_emergency_bar_mobile (390 × 48)
sec-01_emergency_bar_desktop (1440 × 40)
Layers:
bar_container (Auto Layout H, red fill #EF4444, fixed top)
bar_icon_siren (SVG 16×16 — uses 🚨 emoji or custom SVG)
bar_label_emergency (text: "Emergency?")
bar_phone_link (text: "(913) 963-1029", yellow #FFEA00, underlined)
bar_divider_dot (text: "·", static separator)
bar_service_note (text: "Same-day service in [City]")
bar_live_badge (optional — "LIVE" pill on right, only if Phase 2)
Frame: sec-02_hero_mobile (390 × 520)
sec-02_hero_desktop (1440 × 720)
Layers:
hero_container (Auto Layout V, navy bg #1D1760)
hero_image (WebP — see Hero Image Dimensions section for exact px)
hero_gradient_overlay (linear-gradient navy → transparent, for H1 readability)
hero_h1 (text: "Plumber in [City]", 46px desktop / 32px mobile, white)
hero_subhead (text: "5th-generation family plumber · Same-day dispatch")
hero_trust_chip_row (Auto Layout H, wrap)
chip_rating (⭐ 4.9 / 5)
chip_reviews (384+ reviews)
chip_years (Since 1952)
chip_licensed (Licensed + Insured)
hero_cta_group (Auto Layout H)
cta_phone (📞 Call · yellow bg #FFEA00, navy text)
cta_book (📅 Book · blue bg #30C5FF, white text)
cta_chat (💬 Chat · outline navy border)
Frame: sec-03_map_mobile (350 × 280)
sec-03_map_desktop (1160 × 400)
Layers:
map_container (Auto Layout V)
map_embed_placeholder (dashed border 2px #30C5FF — shows iframe location)
map_pin (BSP pin SVG, centered on city lat/lng)
map_caption (text: "Serving [City] and surrounding areas")
map_address_line (text: 12022 Blue Valley Pkwy, Overland Park, KS 66213)
Frame: sec-04_trust_bar_mobile (full-width × ~120 wrap)
sec-04_trust_bar_desktop (full-width × 56)
Layers:
trust_bar_container (Auto Layout H, wrap, gap 8 mobile / 12 desktop)
trust_chip_rating (⭐ 4.9 / 5)
trust_chip_bbb (BBB A+)
trust_chip_5gen (5-Generation Family)
trust_chip_sameday (Same-Day Service)
trust_chip_licensed (Licensed + Insured)
trust_chip_estimate (Free Estimate)
Each chip = Auto Layout H with:
chip_icon (SVG 18×18)
chip_label (text, Inter 13px semibold)
Frame: sec-05_availability_mobile (full-width × 160)
sec-05_availability_desktop (full-width × 140)
Layers:
availability_container (Auto Layout V, green tint bg)
availability_dot_pulse (12×12 green circle #22C55E with CSS pulse animation)
availability_label (text: "Techs available in [City] today")
availability_eta (text: "45-min avg response time")
availability_city_chip ([City] name pill, outlined blue)
availability_cta_call (📞 Call now CTA, secondary style)
Phase 1 = static "45-min avg". Phase 2 = pulls from ST dispatch.
Frame: sec-06_services_mobile (full-width × auto)
sec-06_services_desktop (full-width × auto)
Layers:
services_container (Auto Layout V)
services_h2 (text: "Plumbing Services in [City]", 32px / 24px)
services_intro (1-paragraph intro that references local soil, pipe age, a landmark)
services_grid (Auto Layout H, 1-col mobile / 2-col tablet / 3-col desktop, wrap)
service_card_01_sewer ← SEWER FIRST (highest intent)
service_icon_01 (SVG 56/64, #1D1760 on #FFEA00 circle)
service_card_title_01 (text: "Sewer Repair in [City]")
service_card_body_01 (30-50 word blurb)
service_card_link_01 (→ "Get a free estimate")
service_card_02_drain
service_card_03_water-heater
service_card_04_gas-line
service_card_05_camera
service_card_06_emergency
Frame: sec-07_reviews_mobile (full-width × auto)
sec-07_reviews_desktop (full-width × auto)
Layers:
reviews_container (Auto Layout V)
reviews_h2 (text: "What [City] Homeowners Say")
reviews_stats_row (⭐ 4.9 · 384 reviews · pull from Google)
reviews_grid (Auto Layout V mobile / H 2-col desktop)
review_card_01
review_card_stars (Unicode ★★★★★, yellow #FFEA00)
review_card_quote (text, italic, max 4 lines)
review_card_author_row
review_author_name (text, Inter 13px bold)
review_author_badge_city (text: "· Overland Park", blue chip)
review_source_chip (Google logo SVG 14×14)
review_card_02
review_card_03
review_card_04
Live: pulls from Google Places API, regex-filter by [city] or neighborhood names.
Frame: sec-08_howitworks_mobile (full-width × auto)
sec-08_howitworks_desktop (full-width × auto)
Layers:
howitworks_container (Auto Layout V, wave-bg optional)
howitworks_h2 (text: "How We Get You Fixed in [City]")
howitworks_steps (Auto Layout V mobile / H 3-col desktop)
step_01_call
step_number_01 (text "01" — large, navy, outlined)
step_icon_01 (SVG 40/48 — phone icon, #30C5FF)
step_title_01 (text: "Call")
step_body_01 (1-sentence explanation)
step_02_arrive
step_number_02
step_icon_02 (truck icon)
step_title_02 ("We Arrive Same-Day")
step_body_02
step_03_fix
step_number_03
step_icon_03 (wrench icon)
step_title_03 ("Fixed Right")
step_body_03
Phase 2: add live crew ETA map below step 02.
Frame: sec-09_neighborhoods_mobile (full-width × auto)
sec-09_neighborhoods_desktop (full-width × auto)
Layers:
neighborhoods_container (Auto Layout V)
neighborhoods_h2 (text: "We Fix Plumbing Across [City]")
neighborhoods_copy_block (1 paragraph: "from Blue Valley to Corporate Woods...")
neighborhoods_chip_grid (Auto Layout H, wrap, gap 8 mobile / 10 desktop)
neighborhood_chip_01 (text-only pill, no icon — outlined blue #30C5FF)
neighborhood_chip_02
...
neighborhood_chip_12 (last — pulls from city data object)
Per-city data object supplies names (Blue Valley, Corporate Woods, Deer Creek, etc.).
Frame: sec-10_landmarks_mobile (full-width × auto)
sec-10_landmarks_desktop (full-width × auto)
Layers:
landmarks_container (Auto Layout V, amber ivory bg #FFFBEB)
landmarks_h3 (optional subhead)
landmarks_copy (1-paragraph referencing 3-5 landmarks naturally —
"From Oak Park Mall to the homes off 151st...")
landmarks_photo_row (Phase 2 optional, Auto Layout H wrap)
landmark_photo_01 (WebP 380×250)
landmark_caption_01 (text: "Oak Park Mall, Overland Park")
landmark_photo_02
landmark_photo_03
Phase 1: text-only. Phase 2: add photo row.
Frame: sec-11_beforeafter_mobile (full-width × auto)
sec-11_beforeafter_desktop (full-width × auto)
Layers:
beforeafter_container (Auto Layout V)
beforeafter_h2 (text: "Real Jobs Near You")
beforeafter_grid (Auto Layout H wrap 1-col mobile / 2-col desktop)
beforeafter_01
beforeafter_01_pair (Auto Layout H, gap 8)
beforeafter_01_before (WebP 480×320)
beforeafter_01_before_label ("BEFORE" pill, top-left overlay)
beforeafter_01_after (WebP 480×320)
beforeafter_01_after_label ("AFTER" pill, top-left overlay)
beforeafter_01_caption (text: "Main line replacement · 117th & Metcalf · 2h")
beforeafter_02
beforeafter_03
beforeafter_04
Phase 1: dashed-border placeholder frames only, copy reads "Gallery coming soon."
Phase 2: real photos pulled from ST job library tagged by street.
Frame: sec-12_financing_guarantees_mobile (full-width × auto)
sec-12_financing_guarantees_desktop (full-width × auto)
Layers:
fg_container (Auto Layout V, light bg #F8FAFC)
// Financing subgroup
financing_card (Auto Layout H, Wisetack card)
financing_icon_card (SVG 40/48 — credit card glyph)
financing_body (text: "Approved in 30 seconds. 0% APR options.")
financing_cta (→ "See financing options")
// Guarantees subgroup
guarantees_h3 (text: "Our Promise")
guarantees_tiles (Auto Layout H 1-col mobile / 3-col desktop)
guarantee_01_uptime
guarantee_icon_01 (SVG clock, 48/56, green #22C55E)
guarantee_title_01 ("On Time or It's Free")
guarantee_body_01 (1-sentence)
guarantee_02_warranty
guarantee_icon_02 (SVG shield)
guarantee_title_02 ("Lifetime Parts Warranty")
guarantee_03_pricing
guarantee_icon_03 (SVG dollar)
guarantee_title_03 ("Upfront Pricing, No Surprises")
Frame: sec-13_faq_mobile (full-width × auto)
sec-13_faq_desktop (max-width 800, centered × auto)
Layers:
faq_container (Auto Layout V)
faq_h2 (text: "[City] Plumbing FAQ")
faq_accordion (Auto Layout V, gap 0 — rows stack with bottom borders)
faq_row_01_pricing (expanded in Figma for preview)
faq_question_01 (text: "How much does sewer repair cost in [City]?")
faq_chevron_01 (SVG 18/20, rotates on expand)
faq_answer_01 (text, 40-80 words, always mentions [City])
faq_row_02_response (collapsed in Figma)
faq_row_03_area
faq_row_04_emergency
faq_row_05_financing
faq_row_06_trust
Frame: sec-14_nearby_mobile (full-width × auto)
sec-14_nearby_desktop (full-width × auto)
Layers:
nearby_container (Auto Layout V, centered)
nearby_intro (text: "Also serving [City]'s neighbors:")
nearby_chip_grid (Auto Layout H, wrap, gap 8 mobile / 10 desktop)
nearby_chip_01_olathe (pill: "📍 Plumber in Olathe")
nearby_chip_02_lenexa
nearby_chip_03_leawood
nearby_chip_04_shawnee
nearby_chip_05_prairie-village
nearby_chip_06_mission
Each chip = clickable, routes to /plumber-in-[slug]/
Frame: sec-15_final_cta_mobile (full-width × auto, ~680 content)
sec-15_final_cta_desktop (full-width, centered card 640 wide × auto)
Layers:
final_cta_container (Auto Layout V, wave-to-footer bg transition)
wave_divider_top (inline SVG, navy fill, 100px tall desktop / 60 mobile)
cta_card (Auto Layout V, navy fill #1D1760, white text)
cta_h2 (text: "Ready to fix it right in [City]?")
cta_subhead (text: "Call Kansas City's 5th-generation plumbing family.")
cta_button_trio (Auto Layout H, wrap 1-col mobile / 3-col desktop)
cta_call (📞 Call button — yellow primary)
cta_book (📅 Book button — blue secondary)
cta_chat (💬 Chat button — outline)
cta_form (Auto Layout V, multi-step)
form_progress_dots (3 dots, current highlighted)
form_step_01_service (What service? Sewer/Drain/WH/Other)
form_step_02_urgency (When? Emergency/Today/This week/Flexible)
form_step_03_contact (Name, Phone, Address, ZIP — city pre-selected)
form_submit_button (Continue → arrow)
footer_global (inherits from homepage playbook §14 — no design work)
[City], [Neighborhood], [Landmark] in all template text layersSource: BSP_Location_Pages_Playbook.html (fetched 2026-05-01). Pattern applies to every /service-areas/{slug} page. Phase 1 covers 14 cities: Overland Park, Olathe, Lenexa, Shawnee, Leawood, Prairie Village, Mission, Kansas City MO, Lee's Summit, Blue Springs, Independence, Gladstone, Liberty, Raytown.
Variables in {curly braces} are filled per city from the data object.
H1 formula: {Service} in {City}. 5th-Generation Master Plumbers.
Subhead formula: Same-day service across {City} and nearby. Licensed, insured, family-owned since 1940.
Meta title (50-60 chars): Plumber in {City} KS | Sewer Repair | Bright Side Plumbing Meta description (150-160 chars): Sewer repair, drain cleaning, water heater service in {City} KS. 5th-generation family plumber. Same-day. Call (913) 963-1029.
Sticky emergency bar (top of page): Emergency? Call (913) 963-1029. Same-day service in {City}.
4.9 Google (384+) · BBB A+ · 5 Generations · Same-Day · Licensed and Insured · Free Estimates
Availability chip line: Techs available in {City} today. 45-min average response time.
Two short paragraphs, voice anchored in city name.
¶1. We have been fixing plumbing in {City} for decades. Our crew is the same family that has run trucks across the KC metro since 1940, and {City} homes have been on our route from day one.
¶2. We dispatch licensed plumbers with same-day availability across {City}. Sewer line breaks, drain backups, water heater swaps, and slab leaks. We answer the phone, we show up in the window, and we charge the price we quoted.
120-160 words drawn from the city data object: housing_stock_note + common_issue.
Overland Park sample: Overland Park homes, especially along 151st and Metcalf, are often built on Kansas clay soil that shifts enough to crack old cast-iron sewer lines. We have run trenchless camera inspections from Oak Park Mall to newer builds south of 179th, and we know which subdivisions have the original 1970s pipe still in the ground. If you are seeing slow drains in multiple fixtures, smelling sewer in the basement, or hearing gurgling in the toilet when the dishwasher runs, you are likely looking at a sewer line problem. We can pull a camera through your line for free with any sewer repair $500 or over and tell you in plain English whether you need a spot repair, a trenchless reline, or a full replacement.
Pattern reuse: Each city gets its own version. Reference 2-3 real streets, neighborhoods, or commercial landmarks. Reference the typical housing-stock issue (clay soil, mature trees, old galvanized lines, post-1990 PVC, etc).
H2: What {City} Homeowners Say
Filter logic: regex match on review body for {city name} OR any 8-12 neighborhood names OR any 3-5 landmark names (case-insensitive).
Fallback when fewer than 2 city-specific reviews surface: show "near {City}" reviews from adjacent neighborhoods with caption "Reviews from the KC metro nearby."
Intro line: From {Neighborhood A} to {Neighborhood Z}, we have fixed pipes on every side of {City}.
Overland Park sample intro: From Blue Valley to Wilshire Farms, we have fixed pipes on every side of Overland Park.
8-12 real neighborhood names per city, rendered as pill chips. Phase 1 chips are non-clickable. Phase 2 wires each chip to a /service-areas/{city}/{neighborhood} page if volume merits.
3-5 landmarks woven naturally into a paragraph. Never force all 5 if it sounds spammy.
Pattern: Whether you are near {Landmark A}, around {Landmark B}, or out by {Landmark C}, our crew knows the streets. We have pulled roots out of sewer lines from the older trees around {Landmark D} and swapped water heaters in new construction off {Landmark E}.
See faq_seed.md. Six required topics: pricing, response time, area specificity, emergency, financing, trust. Each answer mentions {City} at least once.
Headline: Ready to fix it right in {City}? Sub: Call Kansas City's 5th-generation plumbing family.
Multi-step form. City pre-selected from URL slug.
Option A (playbook canonical, recommended) H1: Sewer Repair in {City}. 5th-Generation Master Plumbers. Sub: Same-day service across {City} and nearby. Licensed, insured, family-owned since 1940. Option B (broader plumbing service hero) H1: {City} Plumbing. Same-Day Service from a 5th-Generation KC Family. Sub: Sewer, drain, and water heater experts. Licensed and insured. Option C (urgency-first, Emergency Eric lead) H1: Emergency Plumber in {City}. Same-Day Sewer, Drain, and Water Heater Service. Sub: Five generations of Kansas City plumbing. Family-owned since 1940. Option D (problem-first, mirror persona) H1: Sewer Backup in {City}? Our Crew Is in Your Neighborhood Today. Sub: 5th-generation Kansas City plumbers. Same-day. Free camera inspection with any sewer repair. Option E (heritage anchor, Maintenance Mike lead) H1: {City}'s 5th-Generation Plumbing Family. Sewer, Drain, and Water Heater Experts. Sub: Same-day service. Two-year warranty. Family-owned since 1940.
H1: Sewer Repair in Overland Park. 5th-Generation Master Plumbers. Sub: Same-day service across Overland Park and nearby. Licensed, insured, family-owned since 1940. H1 alt for water heater landing: Water Heater Service in Overland Park. 5th-Generation Master Plumbers. H1 alt for drain landing: Drain Cleaning in Overland Park. From $99. 5th-Generation Master Plumbers.
Use Option A as the default formula and swap the lead service to match the page intent (sewer / water heater / drain / leak). Hold Option D as a paid-traffic emergency variant.
Emergency? Call (913) 963-1029. Same-day service in {City}.
Primary: Call (913) 963-1029 (yellow #FFEA00) Variant: Call Now. Same-Day in {City}. Secondary: Book Online (blue outline) Variant: Schedule a {City} Plumber Tertiary: Chat with Daniel (text link)
After Reviews block. Read All Reviews from {City} (text link, #30C5FF) After Neighborhoods chips. See If We Cover Your Block (blue outline) After Landmarks paragraph. Get a Free Sewer Camera Inspection (yellow button, links to coupons)
Headline: Ready to fix it right in {City}? Sub: Call Kansas City's 5th-generation plumbing family. Three buttons.
Multi-step form. City pre-selected from URL slug. Step 1: Service type (Sewer / Drain / Water Heater / Other). Step 2: Timing (Emergency now / Today / This week / Flexible). Step 3: Name / Phone / Address / ZIP.
Replace {City} with "Overland Park" and {Neighborhood A/B/C} with Blue Valley, Wilshire Farms, Indian Creek.
Replace {City} with "Olathe" and {Neighborhood A/B/C} with Stonebridge, Cedar Creek, Forest View.
Primary source: BSP_Location_Pages_Playbook.html (fetched 2026-05-01). Brand canon: CLAUDE.md.
| Element | Source | Notes | |---|---|---| | H1 formula "{Service} in {City}. {Credential}" | Playbook §Hero Pattern | Verbatim formula. | | Subhead with "Same-day service across {City}" | Playbook §Hero Pattern | Verbatim. | | Meta title formula | Playbook §Hero Pattern | 50-60 char target. | | Meta description formula | Playbook §Hero Pattern | 150-160 char target. | | Trust bar 6 chips | Playbook §Local Trust Elements | Reused from homepage. | | Sticky emergency bar | Playbook §Local Trust Elements | Verbatim copy. | | Availability chip "Techs available in {City} today, 45-min average response time" | Playbook §Local Trust Elements | Verbatim. | | 120-160 word services opener | Playbook §06 Services Section Opener | Pattern + Overland Park sample. | | Overland Park sample 151st/Metcalf/Oak Park Mall/179th | Playbook §06 worked example | Verbatim guidance. | | Reviews filter logic | Playbook §07 Review Filtering | Regex on city + neighborhoods + landmarks. | | Neighborhoods intro line | Playbook §09 Neighborhoods | "From {Neighborhood A} to {Neighborhood Z}..." | | Landmarks paragraph pattern | Playbook §10 Landmarks Copy Block | 3-5 landmarks, never spammy. | | 6 FAQ types | Playbook §13 FAQ Pattern | pricing/response/area/emergency/financing/trust. | | Final CTA "Ready to fix it right in {City}?" | Playbook §15 Final CTA | Verbatim headline. | | Multi-step form spec | Playbook §15 Final CTA | 3-step. | | Tone rules (local ownership, emergency-first, family credential) | Playbook §Tone & Voice Rules | Verbatim. | | 14-city Phase 1 list | Homepage Playbook §09 Service Areas | Phase 1 scope. | | NAP block | CLAUDE.md BSP Core Facts + Playbook §NAP Consistency | Header/footer/schema canonical. | | Hours 8 AM to 9 PM Mon-Sat | Contact Playbook | Hard rule, applies to FAQ Q4. | | No em dashes / no emojis | CLAUDE.md + Playbook | Voice rule. |