← back to Prestige Car Wash
Discovery: honest 'find us & review' trust block (real off-site profiles)
d13f501084cf3de48b44b8cf3b9171bc8286d765 · 2026-07-26 20:50:10 -0700 · Steve Abrams
DTD A (4/4 valid). Server-renders REAL Google Maps + Yelp + Instagram links from places()
into the homepage; no star number reproduced on-page (routes to live profile — no drift).
Contrarian FIX-FIRST: (1) review-solicitation CTA gated on a verified Google place_id and
routes to Google's writereview dialog — NOT Yelp (Yelp filters solicited reviews); currently
place_id is empty so the CTA is inert until set. (2) whole section stripped server-side if no
real profiles (no floating heading). rel=noopener (follow, for sameAs authority).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Files touched
M public/index.htmlM server.js
Diff
commit d13f501084cf3de48b44b8cf3b9171bc8286d765
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Sun Jul 26 20:50:10 2026 -0700
Discovery: honest 'find us & review' trust block (real off-site profiles)
DTD A (4/4 valid). Server-renders REAL Google Maps + Yelp + Instagram links from places()
into the homepage; no star number reproduced on-page (routes to live profile — no drift).
Contrarian FIX-FIRST: (1) review-solicitation CTA gated on a verified Google place_id and
routes to Google's writereview dialog — NOT Yelp (Yelp filters solicited reviews); currently
place_id is empty so the CTA is inert until set. (2) whole section stripped server-side if no
real profiles (no floating heading). rel=noopener (follow, for sameAs authority).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---
public/index.html | 7 +++++++
server.js | 38 ++++++++++++++++++++++++++++++++++++++
2 files changed, 45 insertions(+)
diff --git a/public/index.html b/public/index.html
index 69c2d0d..e997d86 100644
--- a/public/index.html
+++ b/public/index.html
@@ -86,6 +86,13 @@ fetch('/api/wait').then(r=>r.json()).then(w=>{const el=document.getElementById('
<div class="grid" id="locPhotos" style="--cols:6;margin-top:16px"></div>
</div></section>
+<section class="section" id="findreview"><div class="wrap">
+ <h2>Find us — and tell the Valley</h2>
+ <p class="sub">We're a real, family-run shop. Look us up, get directions, and if we did right by your car, a review means the world.</p>
+ <!-- Links rendered server-side into #findReview from the REAL places() profiles; no star
+ numbers are reproduced on-page (they'd drift) — the live profile is the source of truth. -->
+ <div id="findReview" style="max-width:820px"></div>
+</div></section>
<style>
#faq summary::-webkit-details-marker{display:none}
#faq summary{list-style:none}
diff --git a/server.js b/server.js
index 4ffc727..f0311c6 100644
--- a/server.js
+++ b/server.js
@@ -491,6 +491,36 @@ function mobileBar(pagePath) {
}</style>
<div class="mbar" aria-label="Quick actions">${call}<a class="mbar-btn book" href="${bookHref}">Book a Wash →</a></div>`;
}
+// Honest "find & review us" trust block — links to the REAL, verified off-site profiles
+// from places() (Google Maps, Yelp, Instagram). Deliberately shows NO star number: ratings
+// drift and would go stale on-page, so we route to the authoritative live profile instead
+// (data-honesty rule — never display a number we can't keep verifiably current). Only a
+// profile with a real non-empty value is rendered (no dead links). Server-rendered so the
+// off-site authority links ship in the crawler HTML.
+function trustBlockHtml() {
+ const p = places() || {};
+ const esc = s => String(s == null ? '' : s).replace(/&/g, '&').replace(/"/g, '"').replace(/</g, '<').replace(/>/g, '>');
+ const btn = (href, label, cls) => href
+ ? `<a class="${cls}" href="${esc(href)}" target="_blank" rel="noopener" style="text-decoration:none">${esc(label)}</a>` : '';
+ const igHandle = p.instagram ? '@' + String(p.instagram).replace(/^https?:\/\/(www\.)?instagram\.com\//i, '').replace(/\/+$/, '').replace(/^@/, '') : '';
+ const igUrl = p.instagram ? (/^https?:\/\//.test(p.instagram) ? p.instagram : 'https://instagram.com/' + String(p.instagram).replace(/^@/, '')) : '';
+ const links = [
+ btn(p.maps_query, '📍 Find us on Google Maps', 'btn'),
+ btn(p.yelp_url, '⭐ Read reviews on Yelp', 'btn ghost'),
+ btn(igUrl, '📸 ' + igHandle, 'btn ghost')
+ ].filter(Boolean);
+ if (!links.length) return '';
+ // Review-SOLICITATION CTA routes to Google's write-review dialog — and ONLY when a real
+ // Google place_id is present (currently empty). We deliberately do NOT solicit on Yelp
+ // (Yelp's "Don't Ask for Reviews" policy filters solicited reviews into "not recommended",
+ // burying exactly what we'd be trying to grow), and we never point "leave a review" at a
+ // bare search URL or a guessed id. So the CTA stays gated on a verified place_id and simply
+ // appears once it's set — the "Read reviews on Yelp" link above stays (finding ≠ soliciting).
+ const pid = /^[A-Za-z0-9_-]{20,}$/.test(String(p.place_id || '')) ? p.place_id : '';
+ const reviewHref = pid ? `https://search.google.com/local/writereview?placeid=${encodeURIComponent(pid)}` : '';
+ const cta = reviewHref ? `<div style="margin-top:16px">${btn(reviewHref, 'Leave us a review on Google →', 'btn')}</div>` : '';
+ return `<div style="display:flex;flex-wrap:wrap;gap:12px;align-items:center">${links.join('')}</div>${cta}`;
+}
function buildFaqLd() {
const list = faqs();
if (!list.length) return null;
@@ -563,6 +593,14 @@ function pageHtml(file, pagePath, ld) {
if (html.includes('id="faqList"')) {
html = html.replace(/(<div id="faqList"[^>]*>)\s*(<\/div>)/, (m, open, close) => open + faqHtml() + close);
}
+ // Fill the honest find-&-review trust block server-side (real off-site profile links).
+ // If there are no real profiles to show, strip the WHOLE section so a heading never floats
+ // over an empty body (graceful degradation, per contrarian).
+ if (html.includes('id="findReview"')) {
+ const tb = trustBlockHtml();
+ if (tb) html = html.replace(/(<div id="findReview"[^>]*>)\s*(<\/div>)/, (m, open, close) => open + tb + close);
+ else html = html.replace(/<section class="section" id="findreview">[\s\S]*?<\/section>/, '');
+ }
// Persistent mobile Book/Call bar on every customer page (guard against double-inject).
if (!/class="mbar"/.test(html)) html = html.replace('</body>', mobileBar(pagePath) + '\n</body>');
let inject = buildSocialTags(html, pagePath);
← 9d17487 Services: per-service 'Book this' deep-links pre-select the
·
back to Prestige Car Wash
·
Guides: evergreen car-care articles (/guides + 3 posts) — BU 2cec353 →