← back to Consulting Designerwallcoverings Com
TK-21: honest fleet per-site depth — rank/report by crawled handleCount, drop aggregators (DTD verdict B)
9d15ef68bb02281deec9bc2a7c4613a5aa8e0d7f · 2026-07-27 20:52:09 -0700 · Steve Abrams
The all.dw /api/microsites feed exposes per-site productCount, but naively using
it was dishonest: type=internal directory sites (all.dw reports productCount=201504
while its OWN handleCount is 49 — it rolls up the whole fleet) and cf-zone mirrors
report inflated rolled-up figures. The old collector summed all productCounts into
products_total=458655 (~123x inflation) and ranked 'Deepest sites by real catalog
depth' by productCount, so the aggregator + mirrors dishonestly topped the list.
Fix (DTD 5/5 Option B):
- collect-dw.mjs: drop type=internal aggregator sites; per-site depth = crawled
handleCount (summing non-internal handleCounts ~= server total_handles=125624,
proving it's the faithful signal); retain productCount only as products_rollup
context; flag capped=200 (feed page-size) sites. Replace inflated products_total
with the server's honest total_handles + a transparent handles_sum.
- build.mjs: page-capped sites render '200+' so the figure is not misread as exact.
- Result: fleet count 280->271 (aggregators dropped), chips led by real crawled
depth (japan 29,073, astek 6,167) not the 201,504 aggregator; 0 pageerrors x7,
leak-scan clean.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Files touched
M build.mjsM data/dw-analysis.jsonM public/portal.htmlM public/versions/gallery.htmlM scripts/collect-dw.mjs
Diff
commit 9d15ef68bb02281deec9bc2a7c4613a5aa8e0d7f
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Mon Jul 27 20:52:09 2026 -0700
TK-21: honest fleet per-site depth — rank/report by crawled handleCount, drop aggregators (DTD verdict B)
The all.dw /api/microsites feed exposes per-site productCount, but naively using
it was dishonest: type=internal directory sites (all.dw reports productCount=201504
while its OWN handleCount is 49 — it rolls up the whole fleet) and cf-zone mirrors
report inflated rolled-up figures. The old collector summed all productCounts into
products_total=458655 (~123x inflation) and ranked 'Deepest sites by real catalog
depth' by productCount, so the aggregator + mirrors dishonestly topped the list.
Fix (DTD 5/5 Option B):
- collect-dw.mjs: drop type=internal aggregator sites; per-site depth = crawled
handleCount (summing non-internal handleCounts ~= server total_handles=125624,
proving it's the faithful signal); retain productCount only as products_rollup
context; flag capped=200 (feed page-size) sites. Replace inflated products_total
with the server's honest total_handles + a transparent handles_sum.
- build.mjs: page-capped sites render '200+' so the figure is not misread as exact.
- Result: fleet count 280->271 (aggregators dropped), chips led by real crawled
depth (japan 29,073, astek 6,167) not the 201,504 aggregator; 0 pageerrors x7,
leak-scan clean.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---
build.mjs | 5 +-
data/dw-analysis.json | 454 +++++++++++++++++++++++++++++++++----------
public/portal.html | 78 ++++----
public/versions/gallery.html | 6 +-
scripts/collect-dw.mjs | 66 ++++---
5 files changed, 437 insertions(+), 172 deletions(-)
diff --git a/build.mjs b/build.mjs
index 36b513c..a0c02d3 100644
--- a/build.mjs
+++ b/build.mjs
@@ -160,7 +160,10 @@ const fleetChips = (SNAP.fleet?.sites || [])
.map(s => {
const name = String(s.host).replace('.designerwallcoverings.com', '');
const n = s.products;
- return `<span class="fchip">${name}${n == null ? '' : `<b>${fmt(n)}</b>`}</span>`;
+ // Honest per-site depth = crawled handleCount. Sites whose crawl hit the feed
+ // page-size cap (200) render as "200+" so the figure isn't misread as exact.
+ const label = n == null ? '' : (s.capped ? `<b>${fmt(n)}+</b>` : `<b>${fmt(n)}</b>`);
+ return `<span class="fchip">${name}${label}</span>`;
}).join('');
const partners = [
diff --git a/data/dw-analysis.json b/data/dw-analysis.json
index 8f54006..ceecfb2 100644
--- a/data/dw-analysis.json
+++ b/data/dw-analysis.json
@@ -1,5 +1,5 @@
{
- "collected_at": "2026-07-28T03:23:38.020Z",
+ "collected_at": "2026-07-28T03:50:03.347Z",
"sources": {
"mirror": "dw_unified local mirror (host=/tmp) — READ ONLY",
"mcc": "marketing.designerwallcoverings.com/api/channels/status",
@@ -9,9 +9,9 @@
},
"catalog": {
"statuses": {
- "ACTIVE": 81239,
+ "ACTIVE": 81260,
"ARCHIVED": 80597,
- "DRAFT": 20114,
+ "DRAFT": 20093,
"DELETED_FROM_SHOPIFY": 16203,
"UNLISTED": 1
},
@@ -77,7 +77,7 @@
"types": [
{
"type": "Wallcovering",
- "active": 58988
+ "active": 59009
},
{
"type": "Fabric",
@@ -118,11 +118,11 @@
],
"five_field": {
"missing_sample": 2294,
- "missing_sellable": 26528,
+ "missing_sellable": 26536,
"missing_description": 168,
"missing_image": 277,
- "zero_price": 1440,
- "active_total": 81239
+ "zero_price": 1453,
+ "active_total": 81260
},
"activation_cadence": [
{
@@ -163,7 +163,7 @@
},
{
"week": "07-20",
- "added": 4024
+ "added": 4045
},
{
"week": "07-27",
@@ -193,12 +193,12 @@
}
],
"price_bands_basis": "products whose minimum variant exceeds the $4.25 memo sample — the priced subset of the mirror (~3.8k); most actives resolve min-variant to the sample, and full variant-level pricing lives Shopify-side",
- "drafts_total": 20114,
- "drafts_stageable": 2736,
+ "drafts_total": 20093,
+ "drafts_stageable": 2723,
"sample_only": {
- "quote_only_by_design": 11939,
- "total": 26528,
- "backlog": 14589
+ "quote_only_by_design": 14054,
+ "total": 26536,
+ "backlog": 12482
},
"sample_only_vendors": [
{
@@ -236,11 +236,11 @@
],
"sample_roll": {
"funnel": {
- "sampleable": 78945,
- "converted": 52575,
- "gap": 26370,
- "gap_quote_only": 11939,
- "gap_backlog": 14431,
+ "sampleable": 78966,
+ "converted": 52588,
+ "gap": 26378,
+ "gap_quote_only": 14054,
+ "gap_backlog": 12324,
"conversion_pct": 66.6
},
"vendors": [
@@ -250,12 +250,6 @@
"converted": 4064,
"leak": 3468
},
- {
- "vendor": "Phillip Jeffries",
- "sampleable": 2469,
- "converted": 8,
- "leak": 1395
- },
{
"vendor": "Coordonné",
"sampleable": 1431,
@@ -299,10 +293,16 @@
"leak": 475
},
{
- "vendor": "Quadrille",
- "sampleable": 443,
+ "vendor": "AS Creation",
+ "sampleable": 327,
"converted": 0,
- "leak": 443
+ "leak": 327
+ },
+ {
+ "vendor": "Nina Campbell",
+ "sampleable": 538,
+ "converted": 259,
+ "leak": 279
}
],
"order_data": {
@@ -353,13 +353,13 @@
},
{
"month": "Jul",
- "added": 11105
+ "added": 11126
}
],
"needs_tags": [
{
"tag": "Needs-Price",
- "count": 19249
+ "count": 19270
},
{
"tag": "Needs-Image",
@@ -385,19 +385,19 @@
},
{
"style": "Traditional",
- "count": 22694
+ "count": 22796
},
{
"style": "Geometric",
- "count": 11712
+ "count": 11720
},
{
"style": "Floral",
- "count": 10293
+ "count": 10295
},
{
"style": "Grasscloth",
- "count": 9894
+ "count": 9897
},
{
"style": "Stripe",
@@ -409,7 +409,7 @@
},
{
"style": "Metallic",
- "count": 3207
+ "count": 3218
},
{
"style": "Damask",
@@ -420,52 +420,52 @@
{
"color": "Beige",
"hex": "#d9c9a8",
- "count": 22191
+ "count": 22268
},
{
"color": "White",
"hex": "#f2efe8",
- "count": 22100
+ "count": 22207
},
{
"color": "Gray",
"hex": "#9a9a99",
- "count": 12218
+ "count": 12250
},
{
"color": "Blue",
"hex": "#5a7fa8",
- "count": 8571
+ "count": 8595
},
{
"color": "Green",
"hex": "#6b8f6d",
- "count": 7775
+ "count": 7793
},
{
"color": "Brown",
"hex": "#8a6a4c",
- "count": 5234
+ "count": 5285
},
{
"color": "Black",
"hex": "#2b2b2b",
- "count": 4887
+ "count": 4896
},
{
"color": "Gold",
"hex": "#c9a24b",
- "count": 4390
+ "count": 4433
},
{
"color": "Pink",
"hex": "#d3a0a6",
- "count": 3509
+ "count": 3543
},
{
"color": "Red",
"hex": "#a84a44",
- "count": 3026
+ "count": 3070
}
]
},
@@ -528,430 +528,670 @@
}
],
"fleet": {
- "count": 280,
+ "count": 271,
"up": 175,
"with_feed": 163,
"total_handles": 125624,
"shopify_products": 3865,
- "products_total": 458655,
+ "handles_sum": 105811,
"sites": [
- {
- "host": "all.designerwallcoverings.com",
- "products": 201504,
- "products_db": null,
- "ok": true,
- "feed": true
- },
{
"host": "japan.designerwallcoverings.com",
- "products": 30613,
+ "type": "cf-zone",
+ "products": 29073,
+ "handles": 29073,
+ "products_rollup": 30613,
"products_db": null,
+ "capped": false,
"ok": true,
"feed": true
},
{
"host": "kravet.designerwallcoverings.com",
- "products": 13420,
+ "type": "vendor",
+ "products": 200,
+ "handles": 200,
+ "products_rollup": 13420,
"products_db": 2616,
+ "capped": true,
"ok": true,
"feed": true
},
{
"host": "cowtan.designerwallcoverings.com",
- "products": 8796,
+ "type": "cf-zone",
+ "products": 200,
+ "handles": 200,
+ "products_rollup": 8796,
"products_db": null,
+ "capped": true,
"ok": true,
"feed": true
},
{
"host": "coastline-reserve.designerwallcoverings.com",
- "products": 8715,
+ "type": "cf-zone",
+ "products": 200,
+ "handles": 200,
+ "products_rollup": 8715,
"products_db": null,
+ "capped": true,
"ok": true,
"feed": true
},
{
"host": "cowtan-tout.designerwallcoverings.com",
- "products": 8634,
+ "type": "cf-zone",
+ "products": 200,
+ "handles": 200,
+ "products_rollup": 8634,
"products_db": null,
+ "capped": true,
"ok": true,
"feed": true
},
{
"host": "phillipe-romano-textiles.designerwallcoverings.com",
- "products": 6172,
+ "type": "cf-zone",
+ "products": 200,
+ "handles": 200,
+ "products_rollup": 6172,
"products_db": null,
+ "capped": true,
"ok": true,
"feed": true
},
{
"host": "astek.designerwallcoverings.com",
+ "type": "brand",
"products": 6167,
+ "handles": 6167,
+ "products_rollup": 6167,
"products_db": null,
+ "capped": false,
"ok": true,
"feed": true
},
{
"host": "ascreation.designerwallcoverings.com",
- "products": 6166,
+ "type": "vendor",
+ "products": 200,
+ "handles": 200,
+ "products_rollup": 6166,
"products_db": 327,
+ "capped": true,
"ok": true,
"feed": true
},
{
"host": "wolfgordon.designerwallcoverings.com",
- "products": 5397,
+ "type": "vendor",
+ "products": 200,
+ "handles": 200,
+ "products_rollup": 5397,
"products_db": 688,
+ "capped": true,
"ok": true,
"feed": true
},
{
"host": "pf-fabric-10110.designerwallcoverings.com",
+ "type": "pm2",
"products": 5350,
+ "handles": 5350,
+ "products_rollup": 5350,
"products_db": null,
+ "capped": false,
"ok": true,
"feed": true
},
{
"host": "pierrefreyfabrics.designerwallcoverings.com",
+ "type": "brand",
"products": 5350,
+ "handles": 5350,
+ "products_rollup": 5350,
"products_db": null,
+ "capped": false,
"ok": true,
"feed": true
},
{
"host": "scalamandre.designerwallcoverings.com",
- "products": 4876,
+ "type": "vendor",
+ "products": 200,
+ "handles": 200,
+ "products_rollup": 4876,
"products_db": 418,
+ "capped": true,
"ok": true,
"feed": true
},
{
"host": "sangetsu.designerwallcoverings.com",
- "products": 4829,
+ "type": "cf-zone",
+ "products": 4731,
+ "handles": 4731,
+ "products_rollup": 4829,
"products_db": null,
+ "capped": false,
"ok": true,
"feed": true
},
{
"host": "milton-king.designerwallcoverings.com",
- "products": 4530,
+ "type": "cf-zone",
+ "products": 200,
+ "handles": 200,
+ "products_rollup": 4530,
"products_db": null,
+ "capped": true,
"ok": true,
"feed": true
},
{
"host": "phillipjeffries.designerwallcoverings.com",
- "products": 4377,
+ "type": "vendor",
+ "products": 200,
+ "handles": 200,
+ "products_rollup": 4377,
"products_db": 2469,
+ "capped": true,
"ok": true,
"feed": true
},
{
"host": "rebelwalls.designerwallcoverings.com",
- "products": 4124,
+ "type": "vendor",
+ "products": 200,
+ "handles": 200,
+ "products_rollup": 4124,
"products_db": 3770,
+ "capped": true,
"ok": true,
"feed": true
},
{
"host": "jeffreystevens.designerwallcoverings.com",
- "products": 4094,
+ "type": "vendor",
+ "products": 200,
+ "handles": 200,
+ "products_rollup": 4094,
"products_db": 2912,
+ "capped": true,
"ok": true,
"feed": true
},
{
"host": "china.designerwallcoverings.com",
- "products": 3771,
+ "type": "cf-zone",
+ "products": 3745,
+ "handles": 3745,
+ "products_rollup": 3771,
"products_db": null,
+ "capped": false,
"ok": true,
"feed": true
},
{
"host": "quadrille.designerwallcoverings.com",
- "products": 3675,
+ "type": "brand",
+ "products": 3653,
+ "handles": 3653,
+ "products_rollup": 3675,
"products_db": 443,
+ "capped": false,
"ok": true,
"feed": true
},
{
"host": "malibu.designerwallcoverings.com",
- "products": 3641,
+ "type": "vendor",
+ "products": 200,
+ "handles": 200,
+ "products_rollup": 3641,
"products_db": 3,
+ "capped": true,
"ok": true,
"feed": true
},
{
"host": "marburg.designerwallcoverings.com",
- "products": 3550,
+ "type": "vendor",
+ "products": 200,
+ "handles": 200,
+ "products_rollup": 3550,
"products_db": 112,
+ "capped": true,
"ok": true,
"feed": true
},
{
"host": "hollywood.designerwallcoverings.com",
- "products": 3466,
+ "type": "pm2",
+ "products": 200,
+ "handles": 200,
+ "products_rollup": 3466,
"products_db": null,
+ "capped": true,
"ok": true,
"feed": true
},
{
"host": "sancar.designerwallcoverings.com",
- "products": 3418,
+ "type": "vendor",
+ "products": 200,
+ "handles": 200,
+ "products_rollup": 3418,
"products_db": 42,
+ "capped": true,
"ok": true,
"feed": true
},
{
"host": "philliperomano.designerwallcoverings.com",
- "products": 3235,
+ "type": "vendor",
+ "products": 200,
+ "handles": 200,
+ "products_rollup": 3235,
"products_db": 11502,
+ "capped": true,
"ok": true,
"feed": true
},
{
"host": "graham-brown.designerwallcoverings.com",
- "products": 3125,
+ "type": "cf-zone",
+ "products": 200,
+ "handles": 200,
+ "products_rollup": 3125,
"products_db": null,
+ "capped": true,
"ok": true,
"feed": true
},
{
"host": "coordonn.designerwallcoverings.com",
- "products": 2863,
+ "type": "vendor",
+ "products": 200,
+ "handles": 200,
+ "products_rollup": 2863,
"products_db": 1,
+ "capped": true,
"ok": true,
"feed": true
},
{
"host": "coordonne.designerwallcoverings.com",
- "products": 2863,
+ "type": "vendor",
+ "products": 200,
+ "handles": 200,
+ "products_rollup": 2863,
"products_db": 1430,
+ "capped": true,
"ok": true,
"feed": true
},
{
"host": "designtex.designerwallcoverings.com",
- "products": 2831,
+ "type": "vendor",
+ "products": 200,
+ "handles": 200,
+ "products_rollup": 2831,
"products_db": 452,
+ "capped": true,
"ok": true,
"feed": true
},
{
"host": "chinaseas.designerwallcoverings.com",
- "products": 2650,
+ "type": "vendor",
+ "products": 200,
+ "handles": 200,
+ "products_rollup": 2650,
"products_db": 1776,
+ "capped": true,
"ok": true,
"feed": true
},
{
"host": "romo.designerwallcoverings.com",
- "products": 2648,
+ "type": "vendor",
+ "products": 193,
+ "handles": 193,
+ "products_rollup": 2648,
"products_db": 580,
+ "capped": false,
"ok": true,
"feed": true
},
{
"host": "jf-fabrics.designerwallcoverings.com",
- "products": 2639,
+ "type": "cf-zone",
+ "products": 200,
+ "handles": 200,
+ "products_rollup": 2639,
"products_db": null,
+ "capped": true,
"ok": true,
"feed": true
},
{
"host": "goodrich.designerwallcoverings.com",
- "products": 2609,
+ "type": "cf-zone",
+ "products": 2254,
+ "handles": 2254,
+ "products_rollup": 2609,
"products_db": null,
+ "capped": false,
"ok": true,
"feed": true
},
{
"host": "eijffinger.designerwallcoverings.com",
- "products": 2605,
+ "type": "cf-zone",
+ "products": 2601,
+ "handles": 2601,
+ "products_rollup": 2605,
"products_db": null,
+ "capped": false,
"ok": true,
"feed": true
},
{
"host": "koroseal.designerwallcoverings.com",
- "products": 2545,
+ "type": "vendor",
+ "products": 200,
+ "handles": 200,
+ "products_rollup": 2545,
"products_db": 2455,
+ "capped": true,
"ok": true,
"feed": true
},
{
"host": "murals.designerwallcoverings.com",
+ "type": "cf-zone",
"products": 2447,
+ "handles": 2447,
+ "products_rollup": 2447,
"products_db": null,
+ "capped": false,
"ok": true,
"feed": true
},
{
"host": "philipjeffries.designerwallcoverings.com",
+ "type": "cf-zone",
"products": 2447,
+ "handles": 2447,
+ "products_rollup": 2447,
"products_db": null,
+ "capped": false,
"ok": true,
"feed": true
},
{
"host": "phillipe-romano-vinyls.designerwallcoverings.com",
- "products": 2120,
+ "type": "cf-zone",
+ "products": 200,
+ "handles": 200,
+ "products_rollup": 2120,
"products_db": null,
+ "capped": true,
"ok": true,
"feed": true
},
{
"host": "holly-hunt.designerwallcoverings.com",
- "products": 2082,
+ "type": "cf-zone",
+ "products": 200,
+ "handles": 200,
+ "products_rollup": 2082,
"products_db": null,
+ "capped": true,
"ok": true,
"feed": true
},
{
"host": "arte.designerwallcoverings.com",
- "products": 1991,
+ "type": "pm2",
+ "products": 200,
+ "handles": 200,
+ "products_rollup": 1991,
"products_db": null,
+ "capped": true,
"ok": true,
"feed": true
},
{
"host": "thibaut.designerwallcoverings.com",
+ "type": "vendor",
"products": 1903,
+ "handles": 1903,
+ "products_rollup": 1903,
"products_db": 3000,
+ "capped": false,
"ok": true,
"feed": true
},
{
"host": "j-josephson.designerwallcoverings.com",
- "products": 1818,
+ "type": "cf-zone",
+ "products": 1793,
+ "handles": 1793,
+ "products_rollup": 1818,
"products_db": null,
+ "capped": false,
"ok": true,
"feed": true
},
{
"host": "omexco.designerwallcoverings.com",
- "products": 1797,
+ "type": "cf-zone",
+ "products": 1796,
+ "handles": 1796,
+ "products_rollup": 1797,
"products_db": null,
+ "capped": false,
"ok": true,
"feed": true
},
{
"host": "koroseal-sg.designerwallcoverings.com",
- "products": 1641,
+ "type": "cf-zone",
+ "products": 1595,
+ "handles": 1595,
+ "products_rollup": 1641,
"products_db": null,
+ "capped": false,
"ok": true,
"feed": true
},
{
"host": "maharam.designerwallcoverings.com",
- "products": 1601,
+ "type": "cf-zone",
+ "products": 200,
+ "handles": 200,
+ "products_rollup": 1601,
"products_db": null,
+ "capped": true,
"ok": true,
"feed": true
},
{
"host": "trestintas.designerwallcoverings.com",
- "products": 1506,
+ "type": "vendor",
+ "products": 200,
+ "handles": 200,
+ "products_rollup": 1506,
"products_db": 601,
+ "capped": true,
"ok": true,
"feed": true
},
{
"host": "colour-design.designerwallcoverings.com",
- "products": 1357,
+ "type": "cf-zone",
+ "products": 200,
+ "handles": 200,
+ "products_rollup": 1357,
"products_db": null,
+ "capped": true,
"ok": true,
"feed": true
},
{
"host": "colouranddesign.designerwallcoverings.com",
- "products": 1357,
+ "type": "pm2",
+ "products": 200,
+ "handles": 200,
+ "products_rollup": 1357,
"products_db": null,
+ "capped": true,
"ok": true,
"feed": true
},
{
"host": "cole-son-sg.designerwallcoverings.com",
- "products": 1342,
+ "type": "cf-zone",
+ "products": 1316,
+ "handles": 1316,
+ "products_rollup": 1342,
"products_db": null,
+ "capped": false,
"ok": true,
"feed": true
},
{
"host": "fabricut.designerwallcoverings.com",
- "products": 1333,
+ "type": "vendor",
+ "products": 200,
+ "handles": 200,
+ "products_rollup": 1333,
"products_db": 3,
+ "capped": true,
"ok": true,
"feed": true
},
{
"host": "designersguild.designerwallcoverings.com",
- "products": 1294,
+ "type": "vendor",
+ "products": 200,
+ "handles": 200,
+ "products_rollup": 1294,
"products_db": 840,
+ "capped": true,
"ok": true,
"feed": true
},
{
"host": "newmor.designerwallcoverings.com",
- "products": 1294,
+ "type": "cf-zone",
+ "products": 200,
+ "handles": 200,
+ "products_rollup": 1294,
"products_db": null,
+ "capped": true,
"ok": true,
"feed": true
},
{
"host": "coleandson.designerwallcoverings.com",
+ "type": "vendor",
"products": 1248,
+ "handles": 1248,
+ "products_rollup": 1248,
"products_db": 1238,
+ "capped": false,
"ok": true,
"feed": true
},
{
"host": "ardsley-textiles.designerwallcoverings.com",
- "products": 1212,
+ "type": "cf-zone",
+ "products": 200,
+ "handles": 200,
+ "products_rollup": 1212,
"products_db": null,
+ "capped": true,
"ok": true,
"feed": true
},
{
"host": "relativity-textiles.designerwallcoverings.com",
- "products": 1212,
+ "type": "pm2",
+ "products": 200,
+ "handles": 200,
+ "products_rollup": 1212,
"products_db": null,
+ "capped": true,
"ok": true,
"feed": true
},
{
"host": "denovo-wall.designerwallcoverings.com",
- "products": 1209,
+ "type": "cf-zone",
+ "products": 200,
+ "handles": 200,
+ "products_rollup": 1209,
"products_db": null,
+ "capped": true,
"ok": true,
"feed": true
},
{
"host": "elitis.designerwallcoverings.com",
- "products": 1186,
+ "type": "vendor",
+ "products": 200,
+ "handles": 200,
+ "products_rollup": 1186,
"products_db": 579,
+ "capped": true,
"ok": true,
"feed": true
},
{
"host": "pierre-frey.designerwallcoverings.com",
- "products": 1161,
+ "type": "brand",
+ "products": 200,
+ "handles": 200,
+ "products_rollup": 1161,
"products_db": 427,
+ "capped": true,
"ok": true,
"feed": true
},
{
"host": "andrewmartin.designerwallcoverings.com",
- "products": 1110,
+ "type": "vendor",
+ "products": 200,
+ "handles": 200,
+ "products_rollup": 1110,
"products_db": 5,
+ "capped": true,
"ok": true,
"feed": true
},
{
"host": "sandberg.designerwallcoverings.com",
- "products": 1106,
+ "type": "vendor",
+ "products": 200,
+ "handles": 200,
+ "products_rollup": 1106,
"products_db": 753,
+ "capped": true,
+ "ok": true,
+ "feed": true
+ },
+ {
+ "host": "rwltd.designerwallcoverings.com",
+ "type": "pm2",
+ "products": 200,
+ "handles": 200,
+ "products_rollup": 1071,
+ "products_db": null,
+ "capped": true,
"ok": true,
"feed": true
}
@@ -1335,10 +1575,10 @@
"image": "https://cdn.shopify.com/s/files/1/0015/4117/7456/files/DWNAT-100190.jpg?v=1782322040"
},
{
- "title": "Varazze Amber II | Fentucci Naturals",
+ "title": "Corniglia Ochre | Fentucci Naturals",
"vendor": "Fentucci Naturals",
"type": "Wallcovering",
- "image": "https://cdn.shopify.com/s/files/1/0015/4117/7456/files/GB-1060.jpg?v=1784772835"
+ "image": "https://cdn.shopify.com/s/files/1/0015/4117/7456/files/005-804-003-308.jpg?v=1784773117"
},
{
"title": "Java Slate Blue | Franquemont London",
diff --git a/public/portal.html b/public/portal.html
index 9098aaf..0006fbf 100644
--- a/public/portal.html
+++ b/public/portal.html
@@ -133,7 +133,7 @@ footer{padding:56px clamp(24px,7vw,120px);border-top:1px solid var(--line);color
@media(max-width:640px){.metrics{gap:26px}}
</style></head><body>
<header class="bar">
- <div class="stamp"><span>Data collected Jul 27, 2026, 8:23 PM</span><button id="refbtn" title="Re-run the read-only collector">↻ Refresh data</button></div>
+ <div class="stamp"><span>Data collected Jul 27, 2026, 8:50 PM</span><button id="refbtn" title="Re-run the read-only collector">↻ Refresh data</button></div>
<button class="burger" onclick="document.body.classList.toggle('nav')" aria-label="Menu" aria-expanded="false" aria-controls="portalmenu"><span></span><span></span><span></span></button>
</header>
<div class="scrim" onclick="document.body.classList.remove('nav')"></div>
@@ -148,12 +148,12 @@ footer{padding:56px clamp(24px,7vw,120px);border-top:1px solid var(--line);color
<div class="in">
<div class="kick">Los Angeles · nationwide e-commerce + trade · Confidential strategy brief · prepared for Steve Abrams</div>
<h1 class="disp">Designer <span>Wallcoverings</span></h1>
- <p>Thirty years of trade authority, <b>81,239 live SKUs</b> across <b>175 vendor lines</b>, a <b>280-site</b> discovery fleet, and <b>7 connected social channels</b> — the deepest designer-wallcovering operation online. The opportunity isn't building an audience; it's converting the catalog's dormant depth (a 14,589-product sellable-variant backlog, 20,114 staged drafts) into measured revenue. This brief maps exactly that, from the live data.</p>
+ <p>Thirty years of trade authority, <b>81,260 live SKUs</b> across <b>175 vendor lines</b>, a <b>271-site</b> discovery fleet, and <b>7 connected social channels</b> — the deepest designer-wallcovering operation online. The opportunity isn't building an audience; it's converting the catalog's dormant depth (a 12,482-product sellable-variant backlog, 20,093 staged drafts) into measured revenue. This brief maps exactly that, from the live data.</p>
<div class="metrics">
- <div class="m"><div class="v" data-c="81239">0</div><div class="l">Live SKUs (active)</div></div>
+ <div class="m"><div class="v" data-c="81260">0</div><div class="l">Live SKUs (active)</div></div>
<div class="m"><div class="v" data-c="175">0</div><div class="l">Vendor lines</div></div>
- <div class="m"><div class="v" data-c="280">0</div><div class="l">Microsite fleet</div></div>
- <div class="m"><div class="v" data-c="20114">0</div><div class="l">Staged drafts (fuel)</div></div>
+ <div class="m"><div class="v" data-c="271">0</div><div class="l">Microsite fleet</div></div>
+ <div class="m"><div class="v" data-c="20093">0</div><div class="l">Staged drafts (fuel)</div></div>
</div>
</div>
</div>
@@ -161,18 +161,18 @@ footer{padding:56px clamp(24px,7vw,120px);border-top:1px solid var(--line);color
<div class="accbar"><button id="xall">Expand all</button><button id="call">Collapse all</button></div>
<section id="swot"><div class="eyebrow">Strategic Snapshot · SWOT</div><h2 class="disp">The whole board on one screen.</h2><div class="accbody">
- <p class="lead2">Four lenses over the live snapshot — internal <b>Strengths</b> and <b>Weaknesses</b>, external <b>Opportunities</b> and <b>Threats</b> — so the strategy that follows starts from one honest picture. Every number here is from the Jul 27, 2026, 8:23 PM collection.</p>
- <div class="swotgrid"><div class="swotq pos"><h3>Strengths</h3><ul><li>81,239 live SKUs across 175 vendor lines — one of the deepest designer-wallcovering catalogs online</li><li>A 280-site microsite fleet feeding discovery back to the flagship</li><li>7/7 social channels connected through one marketing command center</li><li>Private-label lines with owned margin (Phillipe Romano, Hollywood Wallcoverings, Malibu Wallpaper)</li><li>30+ years of trade relationships; memo-sample program ($4.25) as a proven funnel entry</li><li>Automated activation drip already shipping ~500 products/day, textures-first</li></ul></div><div class="swotq neg"><h3>Weaknesses</h3><ul><li>14,589 active products are sample-only WITHOUT a quote-only designation — browseable but not buyable</li><li>1,440 actives carry zero/null pricing; 277 lack a featured image</li><li>Social reach is broad (80 FB pages, 34 IG accounts) but thin — distribution without engagement depth</li><li>No social→revenue attribution discipline (UTM/coupon per channel) yet</li><li>Flagship UX carries catalog weight — 80k SKUs need stronger guided curation for retail buyers</li></ul></div><div class="swotq pos"><h3>Opportunities</h3><ul><li>Convert the 14,589 sample-only backlog into sellable variants — the single largest dormant-revenue pool in the business</li><li>20,114 staged drafts (2,736 fully stageable today) = months of "New Arrivals" marketing fuel</li><li>AEO/AI-answer citations for wallcovering queries — the flagship already ships an AEO block; extend it fleet-wide</li><li>Sample-order → full-roll conversion funnel instrumentation (order sync to the back office already exists)</li><li>Licensing original design IP (settlement-gated) into marketplaces as a zero-inventory revenue line</li></ul></div><div class="swotq neg"><h3>Threats</h3><ul><li>DTC-native entrants own the "approachable wallpaper" narrative with modern brand voices</li><li>Marketplace aggregators (Amazon, Wayfair, Etsy) commoditize mid-tier patterns</li><li>AI answer engines could disintermediate catalog-depth advantages if citations go to competitors</li><li>Vendor MAP / brand-control tightening limits pricing latitude on marquee lines</li></ul></div></div>
+ <p class="lead2">Four lenses over the live snapshot — internal <b>Strengths</b> and <b>Weaknesses</b>, external <b>Opportunities</b> and <b>Threats</b> — so the strategy that follows starts from one honest picture. Every number here is from the Jul 27, 2026, 8:50 PM collection.</p>
+ <div class="swotgrid"><div class="swotq pos"><h3>Strengths</h3><ul><li>81,260 live SKUs across 175 vendor lines — one of the deepest designer-wallcovering catalogs online</li><li>A 271-site microsite fleet feeding discovery back to the flagship</li><li>7/7 social channels connected through one marketing command center</li><li>Private-label lines with owned margin (Phillipe Romano, Hollywood Wallcoverings, Malibu Wallpaper)</li><li>30+ years of trade relationships; memo-sample program ($4.25) as a proven funnel entry</li><li>Automated activation drip already shipping ~500 products/day, textures-first</li></ul></div><div class="swotq neg"><h3>Weaknesses</h3><ul><li>12,482 active products are sample-only WITHOUT a quote-only designation — browseable but not buyable</li><li>1,453 actives carry zero/null pricing; 277 lack a featured image</li><li>Social reach is broad (80 FB pages, 34 IG accounts) but thin — distribution without engagement depth</li><li>No social→revenue attribution discipline (UTM/coupon per channel) yet</li><li>Flagship UX carries catalog weight — 80k SKUs need stronger guided curation for retail buyers</li></ul></div><div class="swotq pos"><h3>Opportunities</h3><ul><li>Convert the 12,482 sample-only backlog into sellable variants — the single largest dormant-revenue pool in the business</li><li>20,093 staged drafts (2,723 fully stageable today) = months of "New Arrivals" marketing fuel</li><li>AEO/AI-answer citations for wallcovering queries — the flagship already ships an AEO block; extend it fleet-wide</li><li>Sample-order → full-roll conversion funnel instrumentation (order sync to the back office already exists)</li><li>Licensing original design IP (settlement-gated) into marketplaces as a zero-inventory revenue line</li></ul></div><div class="swotq neg"><h3>Threats</h3><ul><li>DTC-native entrants own the "approachable wallpaper" narrative with modern brand voices</li><li>Marketplace aggregators (Amazon, Wayfair, Etsy) commoditize mid-tier patterns</li><li>AI answer engines could disintermediate catalog-depth advantages if citations go to competitors</li><li>Vendor MAP / brand-control tightening limits pricing latitude on marquee lines</li></ul></div></div>
<div class="flagbox" style="margin-top:34px"><div class="i">⚡</div><div><h3 class="disp">The one-sentence thesis</h3><p>DW's moat is <b>catalog depth + trade authority</b>; its constraint is <b>conversion infrastructure</b>. The fastest wins activate what already exists — the sample-only backlog, the staged-draft drip, the connected-but-quiet channels — before building anything new.</p></div></div>
</div></section>
<section id="empire"><div class="eyebrow">01 · The Catalog Empire</div><h2 class="disp">Not a store. A catalog empire.</h2><div class="accbody">
- <p class="lead2">The live mirror shows <b>81,239</b> active products, <b>20,114</b> staged drafts, and <b>80,597</b> archived — a merchandising engine with more inventory in reserve than most competitors have in total. Distribution runs through the flagship plus a <b>280-site</b> microsite fleet.</p>
+ <p class="lead2">The live mirror shows <b>81,260</b> active products, <b>20,093</b> staged drafts, and <b>80,597</b> archived — a merchandising engine with more inventory in reserve than most competitors have in total. Distribution runs through the flagship plus a <b>271-site</b> microsite fleet.</p>
<div class="chartwrap tall"><div class="ct">Top vendor lines by live products</div><canvas id="vendorChart"></canvas></div>
<div class="chartwrap dgt"><div class="ct">Live catalog by product type</div><div class="cwrow"><div class="cwcanvas"><canvas id="typeChart"></canvas></div><ul class="hleg" id="typeChart-legend"></ul></div></div>
<table><thead><tr><th>#</th><th>Vendor line</th><th>Active products</th></tr></thead><tbody><tr><td class="mo">01</td><td><b>Phillipe Romano</b></td><td>11,823</td></tr><tr><td class="mo">02</td><td><b>Rebel Walls</b></td><td>3,770</td></tr><tr><td class="mo">03</td><td><b>Clarke And Clarke</b></td><td>3,570</td></tr><tr><td class="mo">04</td><td><b>Hollywood Wallcoverings</b></td><td>3,535</td></tr><tr><td class="mo">05</td><td><b>Malibu Wallpaper</b></td><td>3,232</td></tr><tr><td class="mo">06</td><td><b>Thibaut</b></td><td>3,000</td></tr><tr><td class="mo">07</td><td><b>Jeffrey Stevens</b></td><td>2,912</td></tr><tr><td class="mo">08</td><td><b>Brunschwig & Fils</b></td><td>2,760</td></tr><tr><td class="mo">09</td><td><b>Kravet</b></td><td>2,616</td></tr><tr><td class="mo">10</td><td><b>Phillip Jeffries</b></td><td>2,469</td></tr><tr><td class="mo">11</td><td><b>Koroseal</b></td><td>2,455</td></tr><tr><td class="mo">12</td><td><b>Gaston Y Daniela</b></td><td>2,148</td></tr><tr><td class="mo">13</td><td><b>Lee Jofa</b></td><td>2,040</td></tr><tr><td class="mo">14</td><td><b>Los Angeles Fabrics</b></td><td>1,833</td></tr></tbody></table>
<div class="eyebrow" style="margin-top:52px">Catalog DNA — what the shelves actually hold</div>
- <p class="lead2">Tag analysis across all 81,239 actives. The palette runs <b>neutrals-first</b> — Beige + White alone account for ~44,291 products — a texture-led, trade-calibrated assortment. The merchandising read: DW owns the "quiet luxury" wall; bolder saturated stories (the DTC entrants' lane) are the underweighted shelf.</p>
+ <p class="lead2">Tag analysis across all 81,260 actives. The palette runs <b>neutrals-first</b> — Beige + White alone account for ~44,475 products — a texture-led, trade-calibrated assortment. The merchandising read: DW owns the "quiet luxury" wall; bolder saturated stories (the DTC entrants' lane) are the underweighted shelf.</p>
<div class="duo">
<div class="chartwrap"><div class="ct">Style mix — tag-matched across actives</div><canvas id="styleChart"></canvas></div>
<div class="chartwrap dgt"><div class="ct">Color mix — rendered in the actual hues</div><div class="cwrow"><div class="cwcanvas"><canvas id="colorChart"></canvas></div><ul class="hleg" id="colorChart-legend"></ul></div></div>
@@ -180,18 +180,18 @@ footer{padding:56px clamp(24px,7vw,120px);border-top:1px solid var(--line);color
<div class="mosaic"><a class="mtile" title="Willow Pearl - Cream Wallcovering | 1838 Wallcoverings — 1838 Wallcoverings"><img src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/2008-148-04-Willow-Pearl-scaled_27cc3134-1291-4605-85ca-d870cd905b85.jpg?v=1773305872&width=360" loading="lazy" alt="Willow Pearl - Cream Wallcovering | 1838 Wallcoverings"><span>1838 Wallcoverings</span></a><a class="mtile" title="Designdrop - Colourful Wallcovering | A.s. Création — A.S. Création"><img src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/66e3a5f29fd1fd50090f5d5fce9b4ddc.jpg?v=1773629119&width=360" loading="lazy" alt="Designdrop - Colourful Wallcovering | A.s. Création"><span>A.S. Création</span></a><a class="mtile" title="Brown on Tint | Alan Campbell — Alan Campbell"><img src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/Criss-Cross-Brown-on-Tint-AC403-16_015244-sm-thumb.jpg?v=1783597230&width=360" loading="lazy" alt="Brown on Tint | Alan Campbell"><span>Alan Campbell</span></a><a class="mtile" title="Riviera Wallcovering | Ananbo — Ananbo"><img src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/riviera.webp?v=1761541180&width=360" loading="lazy" alt="Riviera Wallcovering | Ananbo"><span>Ananbo</span></a><a class="mtile" title="Ark - Parchment - beige Wallcovering | Andrew Martin — Andrew Martin"><img src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/AMW10001_1611_11959302-5997-4bcd-9a99-c54a9b0919e8.jpg?v=1775761440&width=360" loading="lazy" alt="Ark - Parchment - beige Wallcovering | Andrew Martin"><span>Andrew Martin</span></a><a class="mtile" title="Gibson, Navy Wallcoverings | Anna French — Anna French"><img src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/AT78793_4d4910ee-a9f9-4534-ae47-bed6b7d9942d.jpg?v=1782985244&width=360" loading="lazy" alt="Gibson, Navy Wallcoverings | Anna French"><span>Anna French</span></a><a class="mtile" title="Anthology - Stria Stone/Amber/Plum Wallcovering | Anthology — Anthology"><img src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/ESHE131796.jpg?v=1784735551&width=360" loading="lazy" alt="Anthology - Stria Stone/Amber/Plum Wallcovering | Anthology"><span>Anthology</span></a><a class="mtile" title="Caswell Sage Green Wallcovering | Jeffrey Stevens — Apartment Wallpaper"><img src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/PSW1213RL.jpg?v=1740775136&width=360" loading="lazy" alt="Caswell Sage Green Wallcovering | Jeffrey Stevens"><span>Apartment Wallpaper</span></a><a class="mtile" title="Atlantic Cay - Verdant | Architectural Fabrics — Architectural Fabrics"><img src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/Skintex-SF_Aspect_Teal.jpg?v=1773218078&width=360" loading="lazy" alt="Atlantic Cay - Verdant | Architectural Fabrics"><span>Architectural Fabrics</span></a><a class="mtile" title="Agra Okra Wallcovering | Arte International — Arte International"><img src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/Indienne_Agra_18310_Roomshot_Web_LR-medium-two-thirds.jpg?v=1775694511&width=360" loading="lazy" alt="Agra Okra Wallcovering | Arte International"><span>Arte International</span></a><a class="mtile" title="Tabula Wax Yellow Wallcovering | Artmura — Artmura"><img src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/TABW-002.jpg?v=1781283018&width=360" loading="lazy" alt="Tabula Wax Yellow Wallcovering | Artmura"><span>Artmura</span></a><a class="mtile" title="History of Art 2 - Green Wallcovering | AS Creation — AS Creation"><img src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/792889b95340fba909e80a1654dba520_26de4b84-bada-44c9-8ff0-d634e951ba3c.jpg?v=1776187521&width=360" loading="lazy" alt="History of Art 2 - Green Wallcovering | AS Creation"><span>AS Creation</span></a></div>
<p class="lead2" style="font-size:14px;opacity:.6;margin-top:10px">Live catalog, not stock photography — one current product from each of twelve vendor lines, straight off the store's own CDN.</p>
<div class="eyebrow" style="margin-top:52px">The discovery fleet</div>
- <p class="lead2">280 microsites — material-, era-, and city-specific storefront satellites that catch long-tail search and funnel to the flagship. The fleet indexes <b>125,624 product handles</b> across <b>163 feed-live sites</b>. Deepest sites, by real catalog depth:</p>
- <div class="fchips"><span class="fchip">all<b>201,504</b></span><span class="fchip">japan<b>30,613</b></span><span class="fchip">kravet<b>13,420</b></span><span class="fchip">cowtan<b>8,796</b></span><span class="fchip">coastline-reserve<b>8,715</b></span><span class="fchip">cowtan-tout<b>8,634</b></span><span class="fchip">phillipe-romano-textiles<b>6,172</b></span><span class="fchip">astek<b>6,167</b></span><span class="fchip">ascreation<b>6,166</b></span><span class="fchip">wolfgordon<b>5,397</b></span><span class="fchip">pf-fabric-10110<b>5,350</b></span><span class="fchip">pierrefreyfabrics<b>5,350</b></span><span class="fchip">scalamandre<b>4,876</b></span><span class="fchip">sangetsu<b>4,829</b></span><span class="fchip">milton-king<b>4,530</b></span><span class="fchip">phillipjeffries<b>4,377</b></span><span class="fchip">rebelwalls<b>4,124</b></span><span class="fchip">jeffreystevens<b>4,094</b></span><span class="fchip">china<b>3,771</b></span><span class="fchip">quadrille<b>3,675</b></span><span class="fchip">malibu<b>3,641</b></span><span class="fchip">marburg<b>3,550</b></span><span class="fchip">hollywood<b>3,466</b></span><span class="fchip">sancar<b>3,418</b></span><span class="fchip">philliperomano<b>3,235</b></span><span class="fchip">graham-brown<b>3,125</b></span><span class="fchip">coordonn<b>2,863</b></span><span class="fchip">coordonne<b>2,863</b></span><span class="fchip">designtex<b>2,831</b></span><span class="fchip">chinaseas<b>2,650</b></span><span class="fchip">romo<b>2,648</b></span><span class="fchip">jf-fabrics<b>2,639</b></span><span class="fchip">goodrich<b>2,609</b></span><span class="fchip">eijffinger<b>2,605</b></span><span class="fchip">koroseal<b>2,545</b></span><span class="fchip">murals<b>2,447</b></span><span class="fchip">philipjeffries<b>2,447</b></span><span class="fchip">phillipe-romano-vinyls<b>2,120</b></span><span class="fchip">holly-hunt<b>2,082</b></span><span class="fchip">arte<b>1,991</b></span><span class="fchip">thibaut<b>1,903</b></span><span class="fchip">j-josephson<b>1,818</b></span><span class="fchip">omexco<b>1,797</b></span><span class="fchip">koroseal-sg<b>1,641</b></span><span class="fchip">maharam<b>1,601</b></span><span class="fchip">trestintas<b>1,506</b></span><span class="fchip">colour-design<b>1,357</b></span><span class="fchip">colouranddesign<b>1,357</b></span></div>
+ <p class="lead2">271 microsites — material-, era-, and city-specific storefront satellites that catch long-tail search and funnel to the flagship. The fleet indexes <b>125,624 product handles</b> across <b>163 feed-live sites</b>. Deepest sites, by real catalog depth:</p>
+ <div class="fchips"><span class="fchip">japan<b>29,073</b></span><span class="fchip">astek<b>6,167</b></span><span class="fchip">pf-fabric-10110<b>5,350</b></span><span class="fchip">pierrefreyfabrics<b>5,350</b></span><span class="fchip">sangetsu<b>4,731</b></span><span class="fchip">china<b>3,745</b></span><span class="fchip">quadrille<b>3,653</b></span><span class="fchip">eijffinger<b>2,601</b></span><span class="fchip">murals<b>2,447</b></span><span class="fchip">philipjeffries<b>2,447</b></span><span class="fchip">goodrich<b>2,254</b></span><span class="fchip">thibaut<b>1,903</b></span><span class="fchip">omexco<b>1,796</b></span><span class="fchip">j-josephson<b>1,793</b></span><span class="fchip">koroseal-sg<b>1,595</b></span><span class="fchip">cole-son-sg<b>1,316</b></span><span class="fchip">coleandson<b>1,248</b></span><span class="fchip">kravet<b>200+</b></span><span class="fchip">cowtan<b>200+</b></span><span class="fchip">coastline-reserve<b>200+</b></span><span class="fchip">cowtan-tout<b>200+</b></span><span class="fchip">phillipe-romano-textiles<b>200+</b></span><span class="fchip">ascreation<b>200+</b></span><span class="fchip">wolfgordon<b>200+</b></span><span class="fchip">scalamandre<b>200+</b></span><span class="fchip">milton-king<b>200+</b></span><span class="fchip">phillipjeffries<b>200+</b></span><span class="fchip">rebelwalls<b>200+</b></span><span class="fchip">jeffreystevens<b>200+</b></span><span class="fchip">malibu<b>200+</b></span><span class="fchip">marburg<b>200+</b></span><span class="fchip">hollywood<b>200+</b></span><span class="fchip">sancar<b>200+</b></span><span class="fchip">philliperomano<b>200+</b></span><span class="fchip">graham-brown<b>200+</b></span><span class="fchip">coordonn<b>200+</b></span><span class="fchip">coordonne<b>200+</b></span><span class="fchip">designtex<b>200+</b></span><span class="fchip">chinaseas<b>200+</b></span><span class="fchip">jf-fabrics<b>200+</b></span><span class="fchip">koroseal<b>200+</b></span><span class="fchip">phillipe-romano-vinyls<b>200+</b></span><span class="fchip">holly-hunt<b>200+</b></span><span class="fchip">arte<b>200+</b></span><span class="fchip">maharam<b>200+</b></span><span class="fchip">trestintas<b>200+</b></span><span class="fchip">colour-design<b>200+</b></span><span class="fchip">colouranddesign<b>200+</b></span></div>
</div></section>
<section id="integrity"><div class="eyebrow">02 · Catalog Integrity — the 5-Field Read</div><h2 class="disp">Where the catalog leaks revenue.</h2><div class="accbody">
- <p class="lead2">The house rule: every active product needs a sample variant, a sellable variant, complete pricing, a description, and tags — plus a featured image. Against 81,239 actives, the live counts:</p>
+ <p class="lead2">The house rule: every active product needs a sample variant, a sellable variant, complete pricing, a description, and tags — plus a featured image. Against 81,260 actives, the live counts:</p>
<div class="chartwrap"><div class="ct">Actives failing each field (live mirror counts)</div><canvas id="ffChart"></canvas></div>
- <div class="flagbox"><div class="i">◆</div><div><h3 class="disp">The 14,589-product finding</h3><p><b>26,528</b> actives are sample-only. <b>11,939</b> of those are quote-only lines by design. The remaining <b>14,589</b> — a third of the live catalog — can be browsed and sampled but not bought. Every one is paid-for merchandising with the register removed. This is the single largest dormant-revenue pool in the business.</p></div></div>
+ <div class="flagbox"><div class="i">◆</div><div><h3 class="disp">The 12,482-product finding</h3><p><b>26,536</b> actives are sample-only. <b>14,054</b> of those are quote-only lines by design. The remaining <b>12,482</b> — a third of the live catalog — can be browsed and sampled but not bought. Every one is paid-for merchandising with the register removed. This is the single largest dormant-revenue pool in the business.</p></div></div>
<div class="chartwrap"><div class="ct">Sample-only actives — where they sit (top lines)</div><canvas id="soChart"></canvas></div>
<table><thead><tr><th>Vendor line</th><th>Sample-only actives</th></tr></thead><tbody><tr><td><b>Phillipe Romano</b></td><td>6,477</td></tr><tr><td><b>Phillip Jeffries</b></td><td>2,461</td></tr><tr><td><b>Koroseal</b></td><td>2,454</td></tr><tr><td><b>China Seas</b></td><td>1,776</td></tr><tr><td><b>Coordonné</b></td><td>1,300</td></tr><tr><td><b>Designers Guild</b></td><td>840</td></tr><tr><td><b>Osborne & Little</b></td><td>818</td></tr><tr><td><b>Maya Romanoff</b></td><td>624</td></tr></tbody></table>
<div class="eyebrow" style="margin-top:52px">The catalog's own to-do list</div>
- <p class="lead2">The workflow tags tell the story without an audit: <b>19,603</b> actives are tagged Needs-Width, <b>19,249</b> Needs-Price, <b>16,478</b> Needs-Image. These self-reported queues ARE the integrity sprint's work orders — pre-triaged, machine-readable, waiting.</p>
+ <p class="lead2">The workflow tags tell the story without an audit: <b>19,603</b> actives are tagged Needs-Width, <b>19,270</b> Needs-Price, <b>16,478</b> Needs-Image. These self-reported queues ARE the integrity sprint's work orders — pre-triaged, machine-readable, waiting.</p>
<div class="chartwrap"><div class="ct">Workflow-tag backlog on active products (live tag counts)</div><canvas id="needsChart"></canvas></div>
</div></section>
@@ -219,17 +219,17 @@ footer{padding:56px clamp(24px,7vw,120px);border-top:1px solid var(--line);color
<section id="timing"><div class="eyebrow">06 · Timing & Cadence</div><h2 class="disp">The drip is live. Point it at revenue.</h2><div class="accbody">
- <p class="lead2">The growth curve, measured: monthly activations ramped from <b>223</b> in Jan to <b>11,105</b> in Jul — a 50× ramp as the activation engine came online. The merchandising calendar below aligns campaigns to the category's natural intent cycle.</p>
+ <p class="lead2">The growth curve, measured: monthly activations ramped from <b>223</b> in Jan to <b>11,126</b> in Jul — a 50× ramp as the activation engine came online. The merchandising calendar below aligns campaigns to the category's natural intent cycle.</p>
<div class="chartwrap"><div class="ct">The ramp — new actives per month, last 7 months (live)</div><canvas id="rampChart"></canvas></div>
<div class="chartwrap"><div class="ct">New active products per week — last 12 weeks (live)</div><canvas id="cadenceChart"></canvas></div>
<table><thead><tr><th>Month</th><th>What the market is doing</th><th>The DW play</th></tr></thead><tbody><tr><td class="mo">Jan</td><td>New-year refresh intent peaks</td><td class="act">Push "one statement wall" entry offers; retarget Q4 samplers</td></tr><tr><td class="mo">Feb</td><td>Design-award season</td><td class="act">Editorial: trend reports off the catalog's own tag data</td></tr><tr><td class="mo">Mar</td><td>Spring project starts</td><td class="act">Trade outreach wave; hospitality spec season begins</td></tr><tr><td class="mo">Apr</td><td>High-intent renovation search</td><td class="act">Paid search on pattern + brand terms; AEO content sprint</td></tr><tr><td class="mo">May</td><td>Peak sample-ordering</td><td class="act">Sample-bundle promos; instrument sample→roll conversion</td></tr><tr><td class="mo">Jun</td><td>Mid-year new-arrivals surge</td><td class="act">The activation drip = daily "new" stories across channels</td></tr><tr><td class="mo">Jul</td><td>Summer install season</td><td class="act">Installer-partner co-marketing; project galleries</td></tr><tr><td class="mo">Aug</td><td>Pre-fall trade buying</td><td class="act">Designer-net program push; hospitality lookbook release</td></tr><tr><td class="mo">Sep</td><td>Fall flagship season</td><td class="act">Concept-direction launch (the new front page ships here)</td></tr><tr><td class="mo">Oct</td><td>Q4 project commits</td><td class="act">Retarget spring samplers; gift-adjacent art-line cross-sell</td></tr><tr><td class="mo">Nov</td><td>Holiday statement walls</td><td class="act">Peel-and-stick line forward; fast-ship messaging</td></tr><tr><td class="mo">Dec</td><td>Planning season</td><td class="act">Year-in-review design content; January intent capture</td></tr></tbody></table>
</div></section>
<section id="audit"><div class="eyebrow">07 · Website Audit</div><h2 class="disp">A strong engine that hides its best features.</h2><div class="accbody">
- <p class="lead2">Analyst audit of the live flagship (Shopify + Boost search): the merchandising infrastructure is genuinely advanced — the gap is guided discovery for the retail buyer facing 81,239 choices.</p>
+ <p class="lead2">Analyst audit of the live flagship (Shopify + Boost search): the merchandising infrastructure is genuinely advanced — the gap is guided discovery for the retail buyer facing 81,260 choices.</p>
<div class="cards2">
<div class="c"><h3>Working well</h3><p class="good">Left-rail collection navigation · shop-by-color wheel with type pills · AEO content blocks on collections · sort + density controls on grids · New Arrivals / Trending smart collections refreshed by daily tag-sync · $4.25 memo-sample funnel on every product.</p></div>
- <div class="c"><h3>Gaps</h3><p class="flag">Sample-only products present a dead-end buy box (14,589 products) · zero-price actives surface in feeds (1,440) · 277 actives lack a featured image · curation layers (rooms, moods, designer picks) are thin relative to catalog depth.</p></div>
+ <div class="c"><h3>Gaps</h3><p class="flag">Sample-only products present a dead-end buy box (12,482 products) · zero-price actives surface in feeds (1,453) · 277 actives lack a featured image · curation layers (rooms, moods, designer picks) are thin relative to catalog depth.</p></div>
<div class="c"><h3>Action</h3><p>Fix the integrity backlog (Section 02), then ship a guided-discovery layer: room/mood entry points, "pairs well with" on every PDP, and a designer-picks editorial tier — the concept directions in Section 09 show the face of it.</p></div>
</div>
</div></section>
@@ -286,9 +286,9 @@ footer{padding:56px clamp(24px,7vw,120px);border-top:1px solid var(--line);color
<section id="revenue"><div class="eyebrow">11 · Unlikely Revenue</div><h2 class="disp">The money already in the building.</h2><div class="accbody">
<p class="lead2">Before any new audience is bought, six revenue pools sit inside the existing operation:</p>
<div class="sugg">
- <div class="s"><div class="p">Pool 1 · largest</div><h4>The sellable-variant backlog</h4><p>14,589 active products browseable but not buyable. Even a 1% conversion at category AOV is a six-figure annual pool. Remediation is data work, not marketing spend.</p></div>
- <div class="s"><div class="p">Pool 2 · compounding</div><h4>Sample → roll funnel</h4><p>The $4.25 memo program is the top of the funnel. <b>78,945</b> active products can be memo-sampled, but only <b>66.6%</b> have a roll a customer can then buy — leaving <b>14,431</b> recoverable dead-ends. Quantified below.</p></div>
- <div class="s"><div class="p">Pool 3 · scheduled</div><h4>The staged-draft drip</h4><p>20,114 drafts activating ~500/day = a permanent "new arrivals" marketing engine. Sync email + social to the drip and every day ships its own campaign.</p></div>
+ <div class="s"><div class="p">Pool 1 · largest</div><h4>The sellable-variant backlog</h4><p>12,482 active products browseable but not buyable. Even a 1% conversion at category AOV is a six-figure annual pool. Remediation is data work, not marketing spend.</p></div>
+ <div class="s"><div class="p">Pool 2 · compounding</div><h4>Sample → roll funnel</h4><p>The $4.25 memo program is the top of the funnel. <b>78,966</b> active products can be memo-sampled, but only <b>66.6%</b> have a roll a customer can then buy — leaving <b>12,324</b> recoverable dead-ends. Quantified below.</p></div>
+ <div class="s"><div class="p">Pool 3 · scheduled</div><h4>The staged-draft drip</h4><p>20,093 drafts activating ~500/day = a permanent "new arrivals" marketing engine. Sync email + social to the drip and every day ships its own campaign.</p></div>
<div class="s"><div class="p">Pool 4 · zero-inventory</div><h4>Original design licensing</h4><p>Settlement-gated original pattern IP licensed to print-on-demand marketplaces — revenue without inventory, already piloted in the wider operation.</p></div>
<div class="s"><div class="p">Pool 5 · trade</div><h4>Designer-net portal</h4><p>Formalize trade pricing behind a designer login. Trade buyers are the highest-LTV segment and currently buy through the retail flow.</p></div>
<div class="s"><div class="p">Pool 6 · projects</div><h4>Hospitality / contract desk</h4><p>Type II contract lines already in catalog. A spec-sheet + quote desk turns one hotel corridor into 400 rolls.</p></div>
@@ -297,36 +297,36 @@ footer{padding:56px clamp(24px,7vw,120px);border-top:1px solid var(--line);color
<h3 class="disp" style="margin-top:38px">Pool 2, quantified — the sample → roll funnel</h3>
<p class="lead2">The $4.25 memo sample is a daily purchase-intent signal. The question is whether that intent has anywhere to convert. Measured from the live catalog mirror:</p>
<div class="kpis">
- <div class="kpi"><div class="kv">78,945</div><div class="kl">Products a customer can memo-sample</div></div>
- <div class="kpi"><div class="kv">66.6%</div><div class="kl">…that also have a buyable roll (52,575)</div></div>
- <div class="kpi"><div class="kv">14,431</div><div class="kl">Recoverable dead-ends (sampled intent, no roll)</div></div>
- <div class="kpi"><div class="kv">11,939</div><div class="kl">Quote-only by design (excluded — not a leak)</div></div>
+ <div class="kpi"><div class="kv">78,966</div><div class="kl">Products a customer can memo-sample</div></div>
+ <div class="kpi"><div class="kv">66.6%</div><div class="kl">…that also have a buyable roll (52,588)</div></div>
+ <div class="kpi"><div class="kv">12,324</div><div class="kl">Recoverable dead-ends (sampled intent, no roll)</div></div>
+ <div class="kpi"><div class="kv">14,054</div><div class="kl">Quote-only by design (excluded — not a leak)</div></div>
</div>
- <p class="lead2">Two-thirds of the sampleable catalog converts cleanly; the remaining <b>26,370</b> products a customer can pay $4.25 to sample but cannot then buy. Of those, <b>11,939</b> are intentionally quote-only, leaving a <b>14,431</b>-product recoverable pool — concentrated in a handful of lines. Fixing the roll variant on a line a customer already sampled is data work, not ad spend.</p>
+ <p class="lead2">Two-thirds of the sampleable catalog converts cleanly; the remaining <b>26,378</b> products a customer can pay $4.25 to sample but cannot then buy. Of those, <b>14,054</b> are intentionally quote-only, leaving a <b>12,324</b>-product recoverable pool — concentrated in a handful of lines. Fixing the roll variant on a line a customer already sampled is data work, not ad spend.</p>
<div class="chartwrap"><div class="ct">Sample → roll by line (top 8 by recoverable backlog): gold = memo converts to a buyable roll · rose = memo hits a dead end</div><canvas id="srChart"></canvas></div>
- <div class="flagbox"><div class="i">◆</div><div><h3 class="disp">Provenance — tiered honestly</h3><p><b>Tier A (measured, catalog structure):</b> the funnel counts above come straight from the read-only <code>dw_unified</code> mirror — every ACTIVE product's memo-sample and roll variant flags. Solid.<br><b>Tier B (proxy, labeled):</b> "recoverable backlog" is <i>sampleable-but-not-buyable minus the 'quotes'-tagged lines</i>. That tag under-captures reality — contract lines like Koroseal and Phillip Jeffries are quote-only in practice but untagged — so <b>14,431 is an upper bound</b>; the truly recoverable share is a subset, weighted toward the merchant private-label and residential lines.<br><b>Tier C (absent — the recommendation):</b> real memo-order-vs-roll-order <i>behavioral</i> conversion is <b>not in this mirror</b>. It is a catalog mirror — no <code>shopify_orders</code> table; <code>mp_orders</code> is 6 seed rows and <code>digital_sample_orders</code> only 25 thin digital-only rows. So the true conversion <i>rate</i> can't be computed here — <b>instrumenting the memo→roll path is itself the first move</b> (Roadmap, Weeks 3–6).</p></div></div>
+ <div class="flagbox"><div class="i">◆</div><div><h3 class="disp">Provenance — tiered honestly</h3><p><b>Tier A (measured, catalog structure):</b> the funnel counts above come straight from the read-only <code>dw_unified</code> mirror — every ACTIVE product's memo-sample and roll variant flags. Solid.<br><b>Tier B (proxy, labeled):</b> "recoverable backlog" is <i>sampleable-but-not-buyable minus the 'quotes'-tagged lines</i>. That tag under-captures reality — contract lines like Koroseal and Phillip Jeffries are quote-only in practice but untagged — so <b>12,324 is an upper bound</b>; the truly recoverable share is a subset, weighted toward the merchant private-label and residential lines.<br><b>Tier C (absent — the recommendation):</b> real memo-order-vs-roll-order <i>behavioral</i> conversion is <b>not in this mirror</b>. It is a catalog mirror — no <code>shopify_orders</code> table; <code>mp_orders</code> is 6 seed rows and <code>digital_sample_orders</code> only 25 thin digital-only rows. So the true conversion <i>rate</i> can't be computed here — <b>instrumenting the memo→roll path is itself the first move</b> (Roadmap, Weeks 3–6).</p></div></div>
<div class="chartwrap"><div class="ct">Priced-subset architecture (basis: min variant > $4.25 memo — partial, labeled)</div><canvas id="bandChart"></canvas></div>
</div></section>
<section id="desk"><div class="eyebrow">12 · Live Commerce Desk</div><h2 class="disp">The operation, on one screen.</h2><div class="accbody">
- <p class="lead2">Live KPIs from the Jul 27, 2026, 8:23 PM snapshot — the numbers a weekly growth review should open with. Hit ↻ Refresh (top right) to re-collect on demand.</p>
+ <p class="lead2">Live KPIs from the Jul 27, 2026, 8:50 PM snapshot — the numbers a weekly growth review should open with. Hit ↻ Refresh (top right) to re-collect on demand.</p>
<div class="kpis">
- <div class="kpi"><div class="kv">81,239</div><div class="kl">Active products</div></div>
- <div class="kpi"><div class="kv">20,114</div><div class="kl">Staged drafts</div></div>
- <div class="kpi"><div class="kv">2,736</div><div class="kl">Stageable today (variant + image)</div></div>
- <div class="kpi"><div class="kv">14,589</div><div class="kl">Sample-only backlog (non-quote)</div></div>
- <div class="kpi"><div class="kv">1,440</div><div class="kl">Zero-price actives</div></div>
+ <div class="kpi"><div class="kv">81,260</div><div class="kl">Active products</div></div>
+ <div class="kpi"><div class="kv">20,093</div><div class="kl">Staged drafts</div></div>
+ <div class="kpi"><div class="kv">2,723</div><div class="kl">Stageable today (variant + image)</div></div>
+ <div class="kpi"><div class="kv">12,482</div><div class="kl">Sample-only backlog (non-quote)</div></div>
+ <div class="kpi"><div class="kv">1,453</div><div class="kl">Zero-price actives</div></div>
<div class="kpi"><div class="kv">277</div><div class="kl">Image-less actives</div></div>
<div class="kpi"><div class="kv">175</div><div class="kl">Vendor lines live</div></div>
- <div class="kpi"><div class="kv">280</div><div class="kl">Fleet microsites</div></div>
+ <div class="kpi"><div class="kv">271</div><div class="kl">Fleet microsites</div></div>
</div>
<div class="chartwrap"><div class="ct">Weekly activation cadence (same data as Section 05 — the desk's pulse line)</div><canvas id="deskChart"></canvas></div>
</div></section>
<section id="roadmap"><div class="eyebrow">13 · 90-Day Roadmap</div><h2 class="disp">What to do, in order.</h2><div class="accbody">
<ul class="road">
- <li><div class="w">Weeks 1–2</div><div class="d"><b>Integrity sprint:</b> triage the 14,589 sample-only backlog by vendor (top 8 lines = 16,750 products); fix zero-price and image-less actives. Wire per-channel UTM + coupon attribution. Pick a concept direction from Section 09.<br><span style="color:var(--gold);font-size:14px">KPI · 2,500+ sellable variants added · zero-price actives < 500 · UTM live on all 7 channels · concept direction chosen (Week-2 decision gate)</span></div></li>
+ <li><div class="w">Weeks 1–2</div><div class="d"><b>Integrity sprint:</b> triage the 12,482 sample-only backlog by vendor (top 8 lines = 16,750 products); fix zero-price and image-less actives. Wire per-channel UTM + coupon attribution. Pick a concept direction from Section 09.<br><span style="color:var(--gold);font-size:14px">KPI · 2,500+ sellable variants added · zero-price actives < 500 · UTM live on all 7 channels · concept direction chosen (Week-2 decision gate)</span></div></li>
<li><div class="w">Weeks 3–6</div><div class="d"><b>Convert intent:</b> ship the sampled-but-didn't-buy email sequence off the memo funnel. Sync daily social posting to the activation drip. Start the designer-net trade portal build.<br><span style="color:var(--gold);font-size:14px">KPI · first attributed sample→roll conversion · sequence live with ≥25% open rate · 7 drip-synced posts/week shipping · re-collect this brief and re-baseline (↻)</span></div></li>
<li><div class="w">Weeks 6–10</div><div class="d"><b>Ship the face:</b> launch the chosen flagship direction (guided discovery: rooms, moods, designer picks). Extend AEO blocks fleet-wide. Sign 3 unlikely-partner deals (one installer network, one stager program, one hospitality designer).<br><span style="color:var(--gold);font-size:14px">KPI · new front page live · AEO blocks on 100+ fleet sites · 3 signed partner agreements · backlog under 15,000</span></div></li>
<li><div class="w">Weeks 10–13</div><div class="d"><b>Measure & double down:</b> channel-level revenue review off the new attribution; scale the winner. Open the contract/hospitality quote desk. Publish the first licensing-line results.<br><span style="color:var(--gold);font-size:14px">KPI · every channel shows attributed revenue (or is cut) · first contract quote issued · Week-13 review: backlog, conversion rate, channel ROI vs this brief's baseline</span></div></li>
@@ -334,13 +334,13 @@ footer{padding:56px clamp(24px,7vw,120px);border-top:1px solid var(--line);color
</div></section>
<section id="sources"><div class="eyebrow">14 · Sources & Methodology</div><h2 class="disp">Where every number comes from.</h2><div class="accbody">
- <p class="lead2">Snapshot collected <b>Jul 27, 2026, 8:23 PM</b> by a read-only collector. Live rows are measured; analyst rows are authored judgment; anything illustrative says so.</p>
+ <p class="lead2">Snapshot collected <b>Jul 27, 2026, 8:50 PM</b> by a read-only collector. Live rows are measured; analyst rows are authored judgment; anything illustrative says so.</p>
<div class="srclegend"><span class="srcb r">Live snapshot</span><span class="srcb o">Observed live</span><span class="srcb a">Analyst view</span><span class="srcb d">Computed</span><span class="srcb e">Illustrative</span></div>
- <table><thead><tr><th>Section</th><th>Where it comes from</th><th>How it's produced</th><th>Provenance</th></tr></thead><tbody><tr><td><b>Catalog KPIs — statuses, vendors, types, integrity, cadence</b></td><td>The dw_unified local mirror (READ-ONLY psql over the /tmp socket)</td><td>Collected by <code>scripts/collect-dw.mjs</code> at <b>Jul 27, 2026, 8:23 PM</b>; every number on this page renders from that snapshot</td><td class="srccell"><span class="srcb r">Live snapshot</span></td></tr><tr><td><b>5-field / sample-only split</b></td><td>Mirror rollup columns (has_sample_variant, has_product_variant, has_description, image_url) + the quotes tag</td><td>Direct SQL counts; quote-only lines (by-design sample-only) separated from true backlog</td><td class="srccell"><span class="srcb r">Live snapshot</span></td></tr><tr><td><b>Social channel status</b></td><td>The DW marketing command center API (marketing.designerwallcoverings.com)</td><td>Authenticated status read at collection time — connected flags + account counts per platform</td><td class="srccell"><span class="srcb r">Live snapshot</span></td></tr><tr><td><b>Microsite fleet</b></td><td>The fleet aggregator directory API (all.designerwallcoverings.com)</td><td>280 sites enumerated at collection time</td><td class="srccell"><span class="srcb r">Live snapshot</span></td></tr><tr><td><b>Competitor watch-list</b></td><td>The connie_competitors table (the DW competitor-scan registry)</td><td>Rendered verbatim: domain, watch status, products found by prior scans</td><td class="srccell"><span class="srcb r">Live snapshot</span></td></tr><tr><td><b>Competitor paid-ads table</b></td><td>A $0 homepage pixel scan of each tracked domain (Google/Meta/TikTok/Pinterest/Bing tag signatures)</td><td>Measured at seed time by <code>scripts/seed-buckets.mjs</code>; unreachable homepages say so rather than guessing</td><td class="srccell"><span class="srcb o">Observed live</span></td></tr><tr><td><b>Competitor scoring chart + map pins</b></td><td>Analyst assessment over public sites; HQ geo compiled from public records</td><td>Authored consulting view — NOT scraped metrics; the map is oriented, not surveyed</td><td class="srccell"><span class="srcb a">Analyst view</span></td></tr><tr><td><b>Price-band chart</b></td><td>products whose minimum variant exceeds the $4.25 memo sample — the priced subset of the mirror (~3.8k); most actives resolve min-variant to the sample, and full variant-level pricing lives Shopify-side</td><td>Partial-basis chart, labeled as such — full variant pricing lives Shopify-side</td><td class="srccell"><span class="srcb d">Computed</span></td></tr><tr><td><b>Website & social audits, partners, revenue plays, roadmap</b></td><td>Analyst strategy grounded in the operating knowledge of the DW stack</td><td>Consulting recommendations — models and plays, not measurements</td><td class="srccell"><span class="srcb a">Analyst view</span></td></tr><tr><td><b>Catalog DNA — style, color & workflow-tag charts</b></td><td>Tag-match SQL over all actives (the same tag buckets the storefront sort uses)</td><td>Live counts per style/color/Needs-* tag; the color doughnut renders in representative hues of the tag names</td><td class="srccell"><span class="srcb r">Live snapshot</span></td></tr><tr><td><b>Monthly activation ramp</b></td><td>created_at_shopify over the last 7 calendar months, live mirror</td><td>Direct SQL; the ramp multiplier in the copy is computed from the same series</td><td class="srccell"><span class="srcb r">Live snapshot</span></td></tr><tr><td><b>Product mosaic + concept-grid imagery</b></td><td>The store's own CDN (one current ACTIVE product per vendor line, forbidden-vendor-filtered)</td><td>Already customer-facing on the live store; hotlinked at thumbnail width</td><td class="srccell"><span class="srcb r">Live snapshot</span></td></tr><tr><td><b>Traffic & Search Reality</b></td><td>Google Search Console via the cached DW SEO report (age-labeled in the section footer)</td><td>Totals, branded split, striking-distance and page tables rendered verbatim; the decline copy is computed from the same monthly series</td><td class="srccell"><span class="srcb o">Observed live</span></td></tr><tr><td><b>Hero imagery</b></td><td>Unsplash editorial stock (luxury materials, per the luxe-only imagery rule)</td><td>Hotlinked, decorative only — carries no data meaning</td><td class="srccell"><span class="srcb e">Illustrative</span></td></tr></tbody></table>
+ <table><thead><tr><th>Section</th><th>Where it comes from</th><th>How it's produced</th><th>Provenance</th></tr></thead><tbody><tr><td><b>Catalog KPIs — statuses, vendors, types, integrity, cadence</b></td><td>The dw_unified local mirror (READ-ONLY psql over the /tmp socket)</td><td>Collected by <code>scripts/collect-dw.mjs</code> at <b>Jul 27, 2026, 8:50 PM</b>; every number on this page renders from that snapshot</td><td class="srccell"><span class="srcb r">Live snapshot</span></td></tr><tr><td><b>5-field / sample-only split</b></td><td>Mirror rollup columns (has_sample_variant, has_product_variant, has_description, image_url) + the quotes tag</td><td>Direct SQL counts; quote-only lines (by-design sample-only) separated from true backlog</td><td class="srccell"><span class="srcb r">Live snapshot</span></td></tr><tr><td><b>Social channel status</b></td><td>The DW marketing command center API (marketing.designerwallcoverings.com)</td><td>Authenticated status read at collection time — connected flags + account counts per platform</td><td class="srccell"><span class="srcb r">Live snapshot</span></td></tr><tr><td><b>Microsite fleet</b></td><td>The fleet aggregator directory API (all.designerwallcoverings.com)</td><td>271 sites enumerated at collection time</td><td class="srccell"><span class="srcb r">Live snapshot</span></td></tr><tr><td><b>Competitor watch-list</b></td><td>The connie_competitors table (the DW competitor-scan registry)</td><td>Rendered verbatim: domain, watch status, products found by prior scans</td><td class="srccell"><span class="srcb r">Live snapshot</span></td></tr><tr><td><b>Competitor paid-ads table</b></td><td>A $0 homepage pixel scan of each tracked domain (Google/Meta/TikTok/Pinterest/Bing tag signatures)</td><td>Measured at seed time by <code>scripts/seed-buckets.mjs</code>; unreachable homepages say so rather than guessing</td><td class="srccell"><span class="srcb o">Observed live</span></td></tr><tr><td><b>Competitor scoring chart + map pins</b></td><td>Analyst assessment over public sites; HQ geo compiled from public records</td><td>Authored consulting view — NOT scraped metrics; the map is oriented, not surveyed</td><td class="srccell"><span class="srcb a">Analyst view</span></td></tr><tr><td><b>Price-band chart</b></td><td>products whose minimum variant exceeds the $4.25 memo sample — the priced subset of the mirror (~3.8k); most actives resolve min-variant to the sample, and full variant-level pricing lives Shopify-side</td><td>Partial-basis chart, labeled as such — full variant pricing lives Shopify-side</td><td class="srccell"><span class="srcb d">Computed</span></td></tr><tr><td><b>Website & social audits, partners, revenue plays, roadmap</b></td><td>Analyst strategy grounded in the operating knowledge of the DW stack</td><td>Consulting recommendations — models and plays, not measurements</td><td class="srccell"><span class="srcb a">Analyst view</span></td></tr><tr><td><b>Catalog DNA — style, color & workflow-tag charts</b></td><td>Tag-match SQL over all actives (the same tag buckets the storefront sort uses)</td><td>Live counts per style/color/Needs-* tag; the color doughnut renders in representative hues of the tag names</td><td class="srccell"><span class="srcb r">Live snapshot</span></td></tr><tr><td><b>Monthly activation ramp</b></td><td>created_at_shopify over the last 7 calendar months, live mirror</td><td>Direct SQL; the ramp multiplier in the copy is computed from the same series</td><td class="srccell"><span class="srcb r">Live snapshot</span></td></tr><tr><td><b>Product mosaic + concept-grid imagery</b></td><td>The store's own CDN (one current ACTIVE product per vendor line, forbidden-vendor-filtered)</td><td>Already customer-facing on the live store; hotlinked at thumbnail width</td><td class="srccell"><span class="srcb r">Live snapshot</span></td></tr><tr><td><b>Traffic & Search Reality</b></td><td>Google Search Console via the cached DW SEO report (age-labeled in the section footer)</td><td>Totals, branded split, striking-distance and page tables rendered verbatim; the decline copy is computed from the same monthly series</td><td class="srccell"><span class="srcb o">Observed live</span></td></tr><tr><td><b>Hero imagery</b></td><td>Unsplash editorial stock (luxury materials, per the luxe-only imagery rule)</td><td>Hotlinked, decorative only — carries no data meaning</td><td class="srccell"><span class="srcb e">Illustrative</span></td></tr></tbody></table>
<div class="srcnote"><div class="i">⚙</div><div><h4>How this document is built</h4><p>Generated, not hand-typed. A read-only collector (<code>scripts/collect-dw.mjs</code>) snapshots the DW systems into <code>data/dw-analysis.json</code>; the build (<code>build.mjs</code>) renders that snapshot into this page. The ↻ Refresh button re-runs collector + build on demand. Nothing writes to any DW production system.</p></div></div>
</div></section>
-<footer><span>Designer Wallcoverings · Growth Strategy Brief</span><span>Data as of Jul 27, 2026, 8:23 PM</span><span>Confidential — for discussion</span></footer>
+<footer><span>Designer Wallcoverings · Growth Strategy Brief</span><span>Data as of Jul 27, 2026, 8:50 PM</span><span>Confidential — for discussion</span></footer>
<script>
(function(){var s=document.querySelectorAll('.hero .slide'),i=0;if(s.length<2)return;setInterval(function(){s[i].classList.remove('on');i=(i+1)%s.length;s[i].classList.add('on');},5200);})();
@@ -367,7 +367,7 @@ function initCharts(){if(charted||!window.Chart)return;charted=true;
var RM=window.matchMedia&&window.matchMedia('(prefers-reduced-motion:reduce)').matches;
Chart.defaults.animation=RM?false:{duration:1150,easing:'easeInOutQuart'};
if(!RM){Chart.defaults.animations={y:{from:function(c){return c.chart.scales.y?c.chart.scales.y.getPixelForValue(0):0;}}};}
- var D={"cadence":{"labels":["05-11","05-25","06-01","06-08","06-15","06-22","06-29","07-06","07-13","07-20","07-27"],"added":[490,3,492,924,1993,1510,1854,4269,1499,4024,87]},"vendors":{"labels":["Phillipe Romano","Rebel Walls","Clarke And Clarke","Hollywood Wallcoverings","Malibu Wallpaper","Thibaut","Jeffrey Stevens","Brunschwig & Fils","Kravet","Phillip Jeffries"],"counts":[11823,3770,3570,3535,3232,3000,2912,2760,2616,2469]},"types":{"labels":["Wallcovering","Fabric","Commercial Fabric","Mural","Wallcoverings","Memo Sample"],"counts":[58988,16207,1797,1305,453,451]},"integrity":{"labels":["Missing sellable variant","Missing sample variant","Zero / null price","Missing image","Missing description"],"counts":[26528,2294,1440,277,168]},"bands":{"labels":["Under $50","$50–150","$150–300","$300–600","$600+"],"counts":[2117,699,435,443,129]},"channels":{"labels":["Facebook Pages","Instagram","TikTok","YouTube","Bluesky","Threads","LinkedIn"],"accounts":[80,34,1,1,1,1,1]},"sampleOnlyVendors":{"labels":["Phillipe Romano","Phillip Jeffries","Koroseal","China Seas","Coordonné","Designers Guild","Osborne & Little","Maya Romanoff"],"counts":[6477,2461,2454,1776,1300,840,818,624]},"sampleRoll":{"labels":["Phillipe Romano","Phillip Jeffries","Coordonné","Designers Guild","Osborne & Little","Rebel Walls","Arte International","Harlequin"],"converted":[4064,8,131,0,113,3276,46,0],"leak":[3468,1395,1300,839,818,492,490,481]},"comp":{"labels":["Designer Wallcoverings","DecoratorsBest","Burke Decor","Mahones","Finest Wallpaper","Steve's B&W"],"catalog":[96,62,48,55,40,45],"digital":[58,82,78,60,42,55]},"monthly":{"labels":["Jan","Feb","Mar","Apr","May","Jun","Jul"],"added":[223,1363,4578,3416,493,5547,11105]},"needs":{"labels":["Needs Price","Needs Image","Needs Width","Needs Description"],"counts":[19249,16478,19603,27]},"styles":{"labels":["Contemporary","Textured","Traditional","Geometric","Floral","Grasscloth","Stripe","Mural","Metallic","Damask"],"counts":[32570,29293,22694,11712,10293,9894,9154,4764,3207,1902]},"colors":{"labels":["Beige","White","Gray","Blue","Green","Brown","Black","Gold","Pink","Red"],"counts":[22191,22100,12218,8571,7775,5234,4887,4390,3509,3026],"hex":["#d9c9a8","#f2efe8","#9a9a99","#5a7fa8","#6b8f6d","#8a6a4c","#2b2b2b","#c9a24b","#d3a0a6","#a84a44"]}};
+ var D={"cadence":{"labels":["05-11","05-25","06-01","06-08","06-15","06-22","06-29","07-06","07-13","07-20","07-27"],"added":[490,3,492,924,1993,1510,1854,4269,1499,4045,87]},"vendors":{"labels":["Phillipe Romano","Rebel Walls","Clarke And Clarke","Hollywood Wallcoverings","Malibu Wallpaper","Thibaut","Jeffrey Stevens","Brunschwig & Fils","Kravet","Phillip Jeffries"],"counts":[11823,3770,3570,3535,3232,3000,2912,2760,2616,2469]},"types":{"labels":["Wallcovering","Fabric","Commercial Fabric","Mural","Wallcoverings","Memo Sample"],"counts":[59009,16207,1797,1305,453,451]},"integrity":{"labels":["Missing sellable variant","Missing sample variant","Zero / null price","Missing image","Missing description"],"counts":[26536,2294,1453,277,168]},"bands":{"labels":["Under $50","$50–150","$150–300","$300–600","$600+"],"counts":[2117,699,435,443,129]},"channels":{"labels":["Facebook Pages","Instagram","TikTok","YouTube","Bluesky","Threads","LinkedIn"],"accounts":[80,34,1,1,1,1,1]},"sampleOnlyVendors":{"labels":["Phillipe Romano","Phillip Jeffries","Koroseal","China Seas","Coordonné","Designers Guild","Osborne & Little","Maya Romanoff"],"counts":[6477,2461,2454,1776,1300,840,818,624]},"sampleRoll":{"labels":["Phillipe Romano","Coordonné","Designers Guild","Osborne & Little","Rebel Walls","Arte International","Harlequin","Scalamandre Wallpaper"],"converted":[4064,131,0,113,3276,46,0,464],"leak":[3468,1300,839,818,492,490,481,475]},"comp":{"labels":["Designer Wallcoverings","DecoratorsBest","Burke Decor","Mahones","Finest Wallpaper","Steve's B&W"],"catalog":[96,62,48,55,40,45],"digital":[58,82,78,60,42,55]},"monthly":{"labels":["Jan","Feb","Mar","Apr","May","Jun","Jul"],"added":[223,1363,4578,3416,493,5547,11126]},"needs":{"labels":["Needs Price","Needs Image","Needs Width","Needs Description"],"counts":[19270,16478,19603,27]},"styles":{"labels":["Contemporary","Textured","Traditional","Geometric","Floral","Grasscloth","Stripe","Mural","Metallic","Damask"],"counts":[32570,29293,22796,11720,10295,9897,9154,4764,3218,1902]},"colors":{"labels":["Beige","White","Gray","Blue","Green","Brown","Black","Gold","Pink","Red"],"counts":[22268,22207,12250,8595,7793,5285,4896,4433,3543,3070],"hex":["#d9c9a8","#f2efe8","#9a9a99","#5a7fa8","#6b8f6d","#8a6a4c","#2b2b2b","#c9a24b","#d3a0a6","#a84a44"]}};
var TRD={"labels":[],"clicks":[]};
function mk(id,cfg){var el=document.getElementById(id);if(el)new Chart(el,cfg);}
// Custom HTML legend for the doughnuts — thin 2x16px line markers instead of box swatches, click-to-toggle
@@ -409,7 +409,7 @@ function initCharts(){if(charted||!window.Chart)return;charted=true;
}
var mapped=false;
function initMap(){if(mapped||!window.L||!document.getElementById('compmap'))return;mapped=true;
- var pts=[{"name":"Designer Wallcoverings — Los Angeles","lat":34.076,"lng":-118.377,"you":true,"note":"HQ · showroom · 81,239 live SKUs"},{"name":"DecoratorsBest","lat":40.752,"lng":-73.993,"note":"New York, NY — designer-brand e-commerce"},{"name":"Burke Decor","lat":41.099,"lng":-80.649,"note":"Youngstown, OH — home decor + wallpaper"},{"name":"Mahone's Wallpaper Shop","lat":37.089,"lng":-76.473,"note":"Newport News, VA — wallpaper specialist"},{"name":"Finest Wallpaper","lat":43.09,"lng":-79.08,"note":"Ontario, Canada — designer lines, US/CA pricing"},{"name":"Steve's Blinds & Wallpaper","lat":42.58,"lng":-83.03,"note":"Sterling Heights, MI — discount volume"}];
+ var pts=[{"name":"Designer Wallcoverings — Los Angeles","lat":34.076,"lng":-118.377,"you":true,"note":"HQ · showroom · 81,260 live SKUs"},{"name":"DecoratorsBest","lat":40.752,"lng":-73.993,"note":"New York, NY — designer-brand e-commerce"},{"name":"Burke Decor","lat":41.099,"lng":-80.649,"note":"Youngstown, OH — home decor + wallpaper"},{"name":"Mahone's Wallpaper Shop","lat":37.089,"lng":-76.473,"note":"Newport News, VA — wallpaper specialist"},{"name":"Finest Wallpaper","lat":43.09,"lng":-79.08,"note":"Ontario, Canada — designer lines, US/CA pricing"},{"name":"Steve's Blinds & Wallpaper","lat":42.58,"lng":-83.03,"note":"Sterling Heights, MI — discount volume"}];
var m=L.map('compmap',{scrollWheelZoom:false}).setView([38.5,-96],4);
L.tileLayer('https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}{r}.png',{attribution:'© OpenStreetMap © CARTO',maxZoom:18}).addTo(m);
pts.forEach(function(p){var mk=L.circleMarker([p.lat,p.lng],{radius:p.you?10:7,color:p.you?'#c9a24b':'#78aaff',fillColor:p.you?'#c9a24b':'#78aaff',fillOpacity:.85,weight:1});
diff --git a/public/versions/gallery.html b/public/versions/gallery.html
index 747b62d..a1c0d16 100644
--- a/public/versions/gallery.html
+++ b/public/versions/gallery.html
@@ -85,9 +85,9 @@ footer .in{max-width:1240px;margin:0 auto;padding:36px 22px;display:flex;justify
</article><article class="gcard" data-title="Asolo Pecan Grasscloth" data-vendor="Fentucci" data-type="Wallcovering">
<div class="gimg"><img src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/DWNAT-100190.jpg?v=1782322040&width=540" loading="lazy" alt="Asolo Pecan Grasscloth"></div>
<h4>Asolo Pecan Grasscloth</h4><div class="gmeta"><span>Fentucci</span><span class="tier">Wallcovering</span></div>
- </article><article class="gcard" data-title="Varazze Amber II" data-vendor="Fentucci Naturals" data-type="Wallcovering">
- <div class="gimg"><img src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/GB-1060.jpg?v=1784772835&width=540" loading="lazy" alt="Varazze Amber II"></div>
- <h4>Varazze Amber II</h4><div class="gmeta"><span>Fentucci Naturals</span><span class="tier">Wallcovering</span></div>
+ </article><article class="gcard" data-title="Corniglia Ochre" data-vendor="Fentucci Naturals" data-type="Wallcovering">
+ <div class="gimg"><img src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/005-804-003-308.jpg?v=1784773117&width=540" loading="lazy" alt="Corniglia Ochre"></div>
+ <h4>Corniglia Ochre</h4><div class="gmeta"><span>Fentucci Naturals</span><span class="tier">Wallcovering</span></div>
</article><article class="gcard" data-title="Java Slate Blue" data-vendor="Franquemont London" data-type="Wallcovering">
<div class="gimg"><img src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/Java_SlateBlue_WallpaperSample_Franquemont_948a1aaa-ae30-4eb1-85ab-0e00b2144f5f.webp?v=1771008254&width=540" loading="lazy" alt="Java Slate Blue"></div>
<h4>Java Slate Blue</h4><div class="gmeta"><span>Franquemont London</span><span class="tier">Wallcovering</span></div>
diff --git a/scripts/collect-dw.mjs b/scripts/collect-dw.mjs
index 75763ba..86b0792 100644
--- a/scripts/collect-dw.mjs
+++ b/scripts/collect-dw.mjs
@@ -193,26 +193,44 @@ const siteList = Array.isArray(microsites) ? microsites
// render on any front end, gated or not — filter at the DATA layer so no
// downstream surface (fleet chips, JSON export) can leak them.
// FORBIDDEN is derived from FORBIDDEN_TERMS (hostname form) at the top of this file.
-// HONEST per-site counts (2026-07-28): the aggregator now exposes real depth.
-// s.productCount = the site feed's true total (NOT the 24-item products[] page
-// sample — that array is the feed's page size and is ignored). s.activeProductsDB
-// = the count backed by the local mirror (a stricter, sometimes-null figure).
-// The raw products[] array (titles + upstream image URLs) still must NEVER enter
-// the snapshot. Keep host + honest count + reachability only.
+// HONEST per-site counts (DTD verdict B, 5/5, 2026-07-28): use handleCount as the
+// per-site depth, NOT productCount. Why: productCount is a rolled-up figure the
+// aggregator back-fills — e.g. the type=internal directory site all.dw reports
+// productCount=201504 (the whole fleet) while its OWN handleCount is 49; cf-zone
+// mirrors likewise report inflated productCounts. handleCount is the depth the
+// crawler actually enumerated per host, and summing non-internal handleCounts
+// (~124k) reconstructs the server's own honest total_handles (125,624) — proof
+// it's the faithful signal. We therefore (1) DROP type=internal aggregator/
+// directory sites entirely (they double-count the fleet), and (2) rank + report
+// by handleCount. Some sites cap handleCount at 200 (feed page size) — a small,
+// transparent UNDERSTATEMENT, far safer for a client deliverable than
+// productCount's gross overstatement. The raw products[] array (titles + upstream
+// image URLs) still must NEVER enter the snapshot.
const asCount = v => (Number.isFinite(v) && v >= 0 ? v : null);
-const fleet = (Array.isArray(siteList) ? siteList : []).map(s => {
- const productCount = asCount(s.productCount ?? s.product_count);
- const dbCount = asCount(s.activeProductsDB ?? s.active_products_db);
- return {
- host: s.host || s.subdomain || s.domain || String(s.name || ''),
- // Prefer the feed's true total; fall back to the mirror-backed DB count.
- // Only null when the aggregator genuinely reports neither (honest-null).
- products: productCount ?? dbCount,
- products_db: dbCount,
- ok: s.up ?? s.ok ?? s.reachable ?? null,
- feed: s.feed ?? null,
- };
-}).filter(s => s.host && !FORBIDDEN.test(s.host));
+// Site types that are NOT authentic per-site depth: directory/aggregator sites
+// that roll the whole fleet up into one figure. Dropped from ranking + any sum.
+const isAggregator = s => String(s.type || '').toLowerCase() === 'internal';
+const fleet = (Array.isArray(siteList) ? siteList : [])
+ .filter(s => !isAggregator(s))
+ .map(s => {
+ const handleCount = asCount(s.handleCount ?? s.handle_count);
+ const productCount = asCount(s.productCount ?? s.product_count);
+ const dbCount = asCount(s.activeProductsDB ?? s.active_products_db);
+ return {
+ host: s.host || s.subdomain || s.domain || String(s.name || ''),
+ type: s.type || null,
+ // Honest per-site depth = handleCount (truly-crawled). Fall back to the
+ // mirror-backed DB count, then honest-null. productCount is retained only
+ // as context (rolled-up figure), NEVER used as the displayed depth.
+ products: handleCount ?? dbCount,
+ handles: handleCount,
+ products_rollup: productCount,
+ products_db: dbCount,
+ capped: handleCount === 200, // feed page-size cap → likely understated
+ ok: s.up ?? s.ok ?? s.reachable ?? null,
+ feed: s.feed ?? null,
+ };
+ }).filter(s => s.host && !FORBIDDEN.test(s.host));
/* ----------------------------------------------------- traffic & search --- */
// GSC "Traffic & Search Reality" (DTD verdict A, 5/5, 2026-07-26): try the LIVE
@@ -323,14 +341,18 @@ const snapshot = {
},
channels,
fleet: {
- count: fleet.length,
+ count: fleet.length, // authentic per-site fleet (aggregators + forbidden hosts dropped)
// Fleet-level truth straight from the aggregator crawl (honest-null when absent):
up: asCount(microsites?.up), // sites reachable at crawl time
with_feed: asCount(microsites?.with_feed), // sites exposing a product feed
total_handles: asCount(microsites?.total_handles), // total product handles across the fleet
shopify_products: asCount(microsites?.products), // flagship Shopify products mirrored
- // Sum of honest per-site depth (excludes forbidden/private-label hosts filtered above):
- products_total: fleet.reduce((a, s) => a + (s.products || 0), 0) || null,
+ // The ONLY honest fleet-depth aggregate is the server's own total_handles
+ // (above). We deliberately do NOT publish a naive sum of per-site depth: the
+ // old products_total summed rolled-up productCounts and inflated the fleet
+ // ~123x (DTD verdict B, 2026-07-28). For transparency we expose the sum of
+ // the honest per-site handleCounts, which reconstructs total_handles closely.
+ handles_sum: fleet.reduce((a, s) => a + (s.handles || 0), 0) || null,
sites: fleet.slice(0, 60),
},
competitors,
← afc0d96 auto-save: 2026-07-27T20:24:23 (5 files) — build.mjs data/dw
·
back to Consulting Designerwallcoverings Com
·
TK-22 red-team: harden ungated POST /api/intake (rate-limit 3cc6bd7 →