← back to Carmelwallpapers
seo: add per-page canonical + Open Graph + Twitter card (HTML_HEAD threads canonical+ogImage; index collapses facets to type per DTD-B, detail uses redacted product slug)
9753035ac930f7e610ba9ad40099ee35757f50af · 2026-06-04 08:06:22 -0700 · Steve
Files touched
Diff
commit 9753035ac930f7e610ba9ad40099ee35757f50af
Author: Steve <steve@designerwallcoverings.com>
Date: Thu Jun 4 08:06:22 2026 -0700
seo: add per-page canonical + Open Graph + Twitter card (HTML_HEAD threads canonical+ogImage; index collapses facets to type per DTD-B, detail uses redacted product slug)
---
server.js | 14 +++++++++++---
1 file changed, 11 insertions(+), 3 deletions(-)
diff --git a/server.js b/server.js
index 563e3c0..6c58a64 100644
--- a/server.js
+++ b/server.js
@@ -231,7 +231,7 @@ app.use(express.static(path.join(__dirname, 'public')));
IMGP.mount(app);
// ── HTML helpers ─────────────────────────────────────────────────────────────
-const HTML_HEAD = (title, desc) => `<!DOCTYPE html>
+const HTML_HEAD = (title, desc, canonical='', ogImage='') => `<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
@@ -242,6 +242,11 @@ const HTML_HEAD = (title, desc) => `<!DOCTYPE html>
<script>window.dataLayer=window.dataLayer||[];function gtag(){dataLayer.push(arguments);}gtag('js',new Date());gtag('config','G-ENN0QV40F8');</script>
<title>${title}</title>
<meta name="description" content="${desc}">
+${canonical?`<link rel="canonical" href="${canonical}">\n`:''}<meta property="og:type" content="website">
+<meta property="og:site_name" content="Carmel Wallpapers">
+<meta property="og:title" content="${title}">
+<meta property="og:description" content="${desc}">
+${canonical?`<meta property="og:url" content="${canonical}">\n`:''}${ogImage?`<meta property="og:image" content="${ogImage}">\n`:''}<meta name="twitter:card" content="${ogImage?'summary_large_image':'summary'}">
<meta name="theme-color" content="#f7f3ec" media="(prefers-color-scheme: light)">
<meta name="theme-color" content="#12100d" media="(prefers-color-scheme: dark)">
<link rel="preconnect" href="https://fonts.googleapis.com">
@@ -436,7 +441,8 @@ app.get('/p/:handle', (req, res) => {
const tags = (p.tags||[]).filter(t => !/^\d+$/.test(t));
- res.send(`${HTML_HEAD(title, desc)}
+ const canonical = `https://carmelwallpapers.com/p/${encodeURIComponent(redactVendorSlug(p.handle))}`;
+ res.send(`${HTML_HEAD(title, desc, canonical, imgs[0]||'')}
<body>
${HEADER_HTML()}
<main class="detail-wrap">
@@ -518,7 +524,9 @@ app.get('/', (req, res) => {
return `<a href="${href}" class="chip${active}">${a.charAt(0).toUpperCase()+a.slice(1)} <span class="chip-count">${aestheticCounts[a]}</span></a>`;
}).join('');
- res.send(`${HTML_HEAD(pageTitle, pageDesc)}
+ const canonical = 'https://carmelwallpapers.com/' + (type ? `?type=${encodeURIComponent(type)}` : '');
+ const ogImg = (PRODUCTS[0] && PRODUCTS[0].image_url) ? IMGP.proxyImg(PRODUCTS[0].image_url) : '';
+ res.send(`${HTML_HEAD(pageTitle, pageDesc, canonical, ogImg)}
<body>
${HEADER_HTML(q, sort, density)}
← 06b4f59 Scrub residual vendor names from products.json (title/vendor
·
back to Carmelwallpapers
·
carmelwallpapers: rails fire again — wire sliders + grid fil 69a8d92 →