← back to Shopify Sample Shipping

weight-census.mjs

31 lines

import {query} from './query.mjs';
// Bounded census: sample active products, split variants into Sample vs non-Sample, characterize weights.
let cursor=null, pages=0;
const buckets={ sample:{n:0,w0:0,wLE3:0,wGT3:0,min:1e9,max:0}, regular:{n:0,w0:0,wLE3:0,wGT3:0,min:1e9,max:0} };
const lightRegularExamples=[];
const q=`query($c:String){products(first:120,after:$c,query:"status:active"){pageInfo{hasNextPage endCursor} nodes{title variants(first:15){nodes{title price inventoryItem{measurement{weight{value unit}}}}}}}}`;
while(pages<9){ // up to ~1080 products as a signal
  const d=await query(q,{c:cursor});
  for(const p of d.products.nodes){
    for(const v of p.variants.nodes){
      const isSample=/sample/i.test(v.title);
      const w=v.inventoryItem?.measurement?.weight;
      const val=w?Number(w.value):null; // POUNDS assumed (confirmed on spot-check)
      const b=isSample?buckets.sample:buckets.regular;
      b.n++;
      if(val===null||val===0){b.w0++;}
      else{ b.min=Math.min(b.min,val); b.max=Math.max(b.max,val); if(val<=3)b.wLE3++; else b.wGT3++; }
      if(!isSample && val!==null && val>0 && val<=3 && lightRegularExamples.length<12) lightRegularExamples.push(`${p.title.slice(0,40)} / ${v.title} = ${val}lb $${v.price}`);
    }
  }
  pages++;
  if(!d.products.pageInfo.hasNextPage) break;
  cursor=d.products.pageInfo.endCursor;
}
console.log('pages scanned:',pages);
console.log('SAMPLE variants:',JSON.stringify(buckets.sample));
console.log('REGULAR variants:',JSON.stringify(buckets.regular));
console.log('\nLight (<=3lb, weight>0) REGULAR examples (would leak under a 3lb band):');
for(const e of lightRegularExamples) console.log('  '+e);
console.log('\nNOTE: regular variants with weight=0/missing ('+buckets.regular.w0+') would ALSO leak free under a weight band — key risk to weigh.');