← back to Tk10656 Empty Collections
storefront-empty-scan.mjs
31 lines
// TK-10656 — customer-truth scan: for every collection PUBLISHED to Online Store, fetch the
// storefront /collections/<handle>/products.json (published products only). Flag those that
// return 0 products = a live collection page that shows the SHOPPER nothing (hidden dead page
// even if the Admin productsCount>0, because all members are archived/draft/unpublished).
import { readFileSync, writeFileSync } from 'node:fs';
const sleep=ms=>new Promise(r=>setTimeout(r,ms));
const BASE='https://www.designerwallcoverings.com';
const rows=readFileSync('data/collections-dump.jsonl','utf8').trim().split('\n').map(JSON.parse).filter(c=>c.pub);
let checked=0, emptyToShopper=0, errs=0; const empties=[];
for(const c of rows){
let ok=false;
for(let a=0;a<4;a++){
try{
const r=await fetch(`${BASE}/collections/${c.handle}/products.json?limit=1`,{headers:{'User-Agent':'Mozilla/5.0 dw-audit'}});
if(r.status===429||r.status>=500){ await sleep(1500*(a+1)); continue; }
const j=await r.json().catch(()=>null);
if(!j){ await sleep(1000*(a+1)); continue; }
const nprod=(j.products||[]).length;
if(nprod===0){ emptyToShopper++; empties.push({handle:c.handle,title:c.title,admin_count:c.count}); }
ok=true; break;
}catch(e){ await sleep(1000*(a+1)); }
}
if(!ok) errs++;
checked++;
if(checked%100===0) process.stderr.write(` checked ${checked}/${rows.length}, empty-to-shopper ${emptyToShopper}, errs ${errs}\n`);
await sleep(120); // gentle
}
writeFileSync('data/empty-to-shopper.json', JSON.stringify(empties,null,2));
console.log(JSON.stringify({published_collections_checked:checked, EMPTY_to_shopper:emptyToShopper, fetch_errors:errs,
sample:empties.slice(0,25)},null,2));