[object Object]

← back to Prestige Car Wash

Path B: self-canonicalize to prestige.agentabrams.com (stop feeding GoDaddy) + ship guides

61afb843b80e4e99fce6ce8f7b8c92c3088b617c · 2026-07-26 21:19:32 -0700 · Steve Abrams

Steve chose B. New SITE_ORIGIN constant drives all self-referential SEO (canonical, og:url,
sitemap, article URLs, AutoWash.url) to prestige.agentabrams.com — the domain this app is
actually served from — instead of the apex prestigehandcarwash.com, which serves a SEPARATE
GoDaddy site. Resolves the contrarian NO-GO by its own stated A-grade bar. Also: og:type=article
on individual guide pages. Unblocks the held /guides deploy. Flip SITE_ORIGIN to the apex once
its DNS is cut over to Kamatera. (publisher.logo intentionally omitted — no real logo asset.)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

Files touched

Diff

commit 61afb843b80e4e99fce6ce8f7b8c92c3088b617c
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Sun Jul 26 21:19:32 2026 -0700

    Path B: self-canonicalize to prestige.agentabrams.com (stop feeding GoDaddy) + ship guides
    
    Steve chose B. New SITE_ORIGIN constant drives all self-referential SEO (canonical, og:url,
    sitemap, article URLs, AutoWash.url) to prestige.agentabrams.com — the domain this app is
    actually served from — instead of the apex prestigehandcarwash.com, which serves a SEPARATE
    GoDaddy site. Resolves the contrarian NO-GO by its own stated A-grade bar. Also: og:type=article
    on individual guide pages. Unblocks the held /guides deploy. Flip SITE_ORIGIN to the apex once
    its DNS is cut over to Kamatera. (publisher.logo intentionally omitted — no real logo asset.)
    Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---
 server.js | 20 +++++++++++++++-----
 1 file changed, 15 insertions(+), 5 deletions(-)

diff --git a/server.js b/server.js
index 068b93c..365dbb1 100644
--- a/server.js
+++ b/server.js
@@ -406,12 +406,20 @@ function parseHoursLine(line) {
   if (!days.length || !opens || !closes) return null;
   return { '@type': 'OpeningHoursSpecification', dayOfWeek: days.map(d => DOW[d]), opens, closes };
 }
+// Canonical serving origin (Path B, 2026-07-26). This app is actually served at
+// prestige.agentabrams.com, while the apex prestigehandcarwash.com still serves a SEPARATE
+// GoDaddy site. All self-referential SEO (canonical, og:url, sitemap, article URLs, entity
+// url) points HERE so we self-canonicalize to where the content really lives instead of
+// handing authority to GoDaddy. FLIP to 'https://prestigehandcarwash.com' (or '') once the
+// apex DNS is cut over to this app — one line, everything follows.
+const SITE_ORIGIN = 'https://prestige.agentabrams.com';
+function siteOrigin() { return (SITE_ORIGIN || '').replace(/\/$/, ''); }
 function buildJsonLd() {
   const p = places();
   if (!p || !p.name) return null;
   const ld = { '@context': 'https://schema.org', '@type': 'AutoWash', name: p.name };
   if (p.legal_name && p.legal_name !== p.name) ld.alternateName = p.legal_name;
-  if (p.website) ld.url = p.website;
+  if (siteOrigin()) ld.url = siteOrigin();
   if (p.phone) ld.telephone = p.phone;
   if (p.address) {
     const parts = p.address.split(',').map(s => s.trim());
@@ -670,7 +678,7 @@ function buildSocialTags(html, pagePath) {
   // file) so we never inject a duplicate that makes Facebook/Google flag the markup.
   if (/property=["']og:title["']/i.test(html) || /<link\b[^>]*\brel=["']canonical["']/i.test(html)) return '';
   const p = places() || {};
-  const base = (p.website || '').replace(/\/$/, '');
+  const base = siteOrigin();
   const url = base ? base + (pagePath || '') : '';   // page-specific canonical + og:url
   const title = (html.match(/<title>([^<]*)<\/title>/i) || [])[1] || p.name || 'Prestige Car Wash';
   // Attribute-order-independent description extraction, with a real fallback (never a
@@ -680,8 +688,10 @@ function buildSocialTags(html, pagePath) {
   const desc = (descMatch || [])[1] || `${p.name || 'Prestige Car Wash'} — no-pressure flat pricing, two-bucket hand wash, detailing & ceramic coating in the San Fernando Valley.`;
   const img = base ? base + '/media/svc-full-service.png' : '';
   const esc = s => String(s).replace(/&/g, '&amp;').replace(/"/g, '&quot;').replace(/</g, '&lt;');
+  // Individual guide articles are og:type "article"; everything else is a "website".
+  const ogType = /^\/guides\/.+/.test(pagePath || '') ? 'article' : 'website';
   const tags = [
-    ['og:type', 'website'], ['og:site_name', p.name || 'Prestige Car Wash'],
+    ['og:type', ogType], ['og:site_name', p.name || 'Prestige Car Wash'],
     ['og:title', title], ['og:description', desc], url && ['og:url', url], img && ['og:image', img],
     ['twitter:card', img ? 'summary_large_image' : 'summary'],
     ['twitter:title', title], ['twitter:description', desc], img && ['twitter:image', img]
@@ -759,7 +769,7 @@ app.get('/guides', (req, res) => {
 });
 app.get('/guides/:slug', (req, res) => {
   const g = guides().find(x => x.slug === req.params.slug);
-  const base = (((places() || {}).website) || '').replace(/\/$/, '');
+  const base = siteOrigin();
   if (!g) {
     const nf = guideLayout('Guide Not Found — Prestige Car Wash', 'That guide could not be found.',
       `<section class="section"><div class="wrap"><h1>Guide not found</h1><p class="sub">That guide may have moved. <a href="/guides">Browse all car-care guides →</a></p></div></section>`);
@@ -781,7 +791,7 @@ app.get('/guides/:slug', (req, res) => {
 
 // XML sitemap generated from the public URL — kept in one place, no static file to drift.
 app.get('/sitemap.xml', (req, res) => {
-  const base = ((places() || {}).website || '').replace(/\/$/, '');
+  const base = siteOrigin();
   if (!base) return res.status(404).end();
   const urls = ['/', '/services', '/contact', '/guides', ...guides().map(g => '/guides/' + g.slug)];
   const xml = '<?xml version="1.0" encoding="UTF-8"?>\n<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">\n' +

← 2cec353 Guides: evergreen car-care articles (/guides + 3 posts) — BU  ·  back to Prestige Car Wash  ·  Harden booking form: honeypot + validation + dupe-guard + re 7c66f9d →