← back to Wallco Ai
wallco.ai · OG/Twitter enrich — og:type=product on /design/:id + image:alt + product:* tags
284e3ddbf2c97206144f28ddb269f88251cd390d · 2026-05-12 06:21:38 -0700 · SteveStudio2
htmlHead() already emitted basic OG + Twitter. Three gaps closed:
1. og:type was hardcoded "website" everywhere → now per-route param.
/design/:id passes ogType:'product' so Facebook/Pinterest treat shares
as product pins (richer card layout, "in stock" badge, brand label).
2. og:image:alt + twitter:image:alt missing → now built from hue + category
+ motifs, e.g. "Rose Origin No.72 — rose mixed wallpaper pattern
featuring floral, peony, rose, leaf" (accessibility + LinkedIn pull).
3. og:image:secure_url + og:locale added (LinkedIn/Slack expects them).
Facebook product-OG namespace: product:availability="in stock",
product:retailer_item_id, product:brand, product:category — drops in
automatically when productOG arg present.
Non-design pages unchanged (default ogType="website", no product:* tags).
Reversible: signature backwards-compatible (all new params default null).
Files touched
Diff
commit 284e3ddbf2c97206144f28ddb269f88251cd390d
Author: SteveStudio2 <stevestudio2@SteveStacStudio.lan>
Date: Tue May 12 06:21:38 2026 -0700
wallco.ai · OG/Twitter enrich — og:type=product on /design/:id + image:alt + product:* tags
htmlHead() already emitted basic OG + Twitter. Three gaps closed:
1. og:type was hardcoded "website" everywhere → now per-route param.
/design/:id passes ogType:'product' so Facebook/Pinterest treat shares
as product pins (richer card layout, "in stock" badge, brand label).
2. og:image:alt + twitter:image:alt missing → now built from hue + category
+ motifs, e.g. "Rose Origin No.72 — rose mixed wallpaper pattern
featuring floral, peony, rose, leaf" (accessibility + LinkedIn pull).
3. og:image:secure_url + og:locale added (LinkedIn/Slack expects them).
Facebook product-OG namespace: product:availability="in stock",
product:retailer_item_id, product:brand, product:category — drops in
automatically when productOG arg present.
Non-design pages unchanged (default ogType="website", no product:* tags).
Reversible: signature backwards-compatible (all new params default null).
---
server.js | 30 +++++++++++++++++++++++++++---
1 file changed, 27 insertions(+), 3 deletions(-)
diff --git a/server.js b/server.js
index 68f4d76..6a91e8d 100644
--- a/server.js
+++ b/server.js
@@ -491,9 +491,20 @@ const GTAG = GA4_ID ? `
gtag('config', '${GA4_ID}');
</script>` : '';
-function htmlHead({ title, description, canonical, ogImage = '' }) {
+function htmlHead({ title, description, canonical, ogImage = '', ogType = 'website', ogImageAlt = '', productOG = null }) {
const siteUrl = `https://${SITE}`;
const ogImg = ogImage || `${siteUrl}/og-default.png`;
+ const imgAlt = ogImageAlt || title;
+ // product:* tags add Facebook/Pinterest product-pin metadata when ogType==='product'.
+ // productOG = { availability, price, currency, retailer_item_id } — all optional.
+ const productTags = ogType === 'product' && productOG ? [
+ productOG.availability && `<meta property="product:availability" content="${productOG.availability}">`,
+ productOG.retailer_item_id && `<meta property="product:retailer_item_id" content="${productOG.retailer_item_id}">`,
+ productOG.price && productOG.currency && `<meta property="product:price:amount" content="${productOG.price}">`,
+ productOG.price && productOG.currency && `<meta property="product:price:currency" content="${productOG.currency}">`,
+ productOG.brand && `<meta property="product:brand" content="${productOG.brand}">`,
+ productOG.category && `<meta property="product:category" content="${productOG.category}">`
+ ].filter(Boolean).join('\n') : '';
return `<!doctype html>
<html lang="en">
<head>
@@ -503,17 +514,22 @@ function htmlHead({ title, description, canonical, ogImage = '' }) {
<meta name="description" content="${description}">
<link rel="canonical" href="${canonical}">
<!-- Open Graph -->
-<meta property="og:type" content="website">
+<meta property="og:type" content="${ogType}">
<meta property="og:site_name" content="wallco.ai">
<meta property="og:title" content="${title}">
<meta property="og:description" content="${description}">
<meta property="og:url" content="${canonical}">
<meta property="og:image" content="${ogImg}">
+<meta property="og:image:secure_url" content="${ogImg}">
+<meta property="og:image:alt" content="${imgAlt}">
+<meta property="og:locale" content="en_US">
+${productTags}
<!-- Twitter Card -->
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:title" content="${title}">
<meta name="twitter:description" content="${description}">
<meta name="twitter:image" content="${ogImg}">
+<meta name="twitter:image:alt" content="${imgAlt}">
${GTAG}
<!-- Dark/Light anti-flash + Age-band early apply (must be first JS in <head>) -->
<script>
@@ -2524,7 +2540,15 @@ app.get('/design/:id', (req, res) => {
title: `${design.title} — wallco.ai`,
description: `wallco.ai original ${design.category} wallpaper. Pattern No.${design.id} — hand-curated, unique, never repeated. Free sample available.`,
canonical: `https://wallco.ai/design/${design.id}`,
- ogImage: `https://wallco.ai${design.image_url}`
+ ogImage: `https://wallco.ai${design.image_url}`,
+ ogType: 'product',
+ ogImageAlt: `${design.title} — ${_hueName} ${design.category} wallpaper pattern${_motifList ? ' featuring ' + _motifList : ''}`,
+ productOG: {
+ availability: 'in stock',
+ retailer_item_id: design.handle || `wallco-${String(design.id).padStart(4,'0')}`,
+ brand: 'wallco.ai',
+ category: design.category
+ }
})}
<body>
${htmlHeader('/designs')}
← 149bfe0 wallco.ai · /design/:id JSON-LD — enriched Product schema wi
·
back to Wallco Ai
·
security — close path traversal + shell injection in /api/st 70b4570 →