← back to Shopify Sample Shipping
gf-classify.mjs
40 lines
import fs from 'node:fs';
const lines=fs.readFileSync('verification/all-customers-bulk.jsonl','utf8').split('\n').filter(Boolean);
// Canonical designer/trade tags already covered by the segment (case-insensitive contains)
const DESIGNER_TAG=/\b(trade|interior design|interior designer|interior|graphic design|graphic designer|architect|contractor|photography studio|photograph|wallcovering installer|commercial property|design(er)?|studio|showroom|dealer|wholesale|to the trade|hospitalit)\b/i;
const RETAIL_TAG=/\b(home ?owner|retail[- ]?customer|retail consumer|verified-sample)\b/i;
const FREEMAIL=/@(gmail|yahoo|ymail|hotmail|outlook|live|msn|aol|icloud|me|mac|comcast|sbcglobal|att|verizon|earthlink|cox|bellsouth|charter|gmx|mail|protonmail|pm|proton|frontier|roadrunner|rr|windstream|juno|netzero|q| meta)\./i;
const DOMAIN_DESIGN=/design|interior|decor|architect|drapery|draperie|studio|staging|remodel|renovat|hospitalit|upholster|workroom|furnish|homes|interiors|kitchen|bath|millwork|cabinet|construc|contract|builders?|realty|properties|hotel|resort/i;
let total=0,tagged=0,retail=0;
const tier1=[],tier2=[];
for(const l of lines){
let c; try{c=JSON.parse(l);}catch{continue;}
if(!c.email) continue; total++;
const tags=(c.tags||[]);
const tstr=tags.join(' ');
if(RETAIL_TAG.test(tstr)){retail++;continue;} // explicit retail -> exclude
if(DESIGNER_TAG.test(tstr)){tagged++;continue;} // already designer-tagged -> covered by segment
// untagged (no designer tag). Is it a design-firm email?
const email=c.email.toLowerCase();
const domain=email.split('@')[1]||'';
const isFreemail=FREEMAIL.test('@'+domain+'.');
const orders=c.numberOfOrders?parseInt(c.numberOfOrders):0;
const spent=parseFloat(c.amountSpent?.amount||'0');
if(!isFreemail && DOMAIN_DESIGN.test(domain)){
tier1.push({email,domain,orders,spent,tags}); // TIER1: design-keyword business domain
} else if(!isFreemail && orders>=1 && spent>60){
tier2.push({email,domain,orders,spent,tags}); // TIER2: business domain + real spend (review)
}
}
tier1.sort((a,b)=>b.spent-a.spent); tier2.sort((a,b)=>b.spent-a.spent);
const out={generated:new Date().toISOString(),totalCustomers:total,alreadyDesignerTagged:tagged,retailTagged:retail,
tier1_count:tier1.length,tier2_count:tier2.length,tier1,tier2};
fs.writeFileSync('verification/grandfather-list.json',JSON.stringify(out,null,2));
console.log(`total customers with email: ${total}`);
console.log(`already designer-tagged (segment covers): ${tagged}`);
console.log(`explicit retail-tagged (excluded): ${retail}`);
console.log(`TIER1 grandfather (design-firm domain, untagged): ${tier1.length}`);
console.log(`TIER2 review (business domain + spend>$60, untagged): ${tier2.length}`);
console.log('\n--- TIER1 sample (top 25 by spend) ---');
for(const r of tier1.slice(0,25)) console.log(` $${r.spent.toFixed(0).padStart(6)} ord=${r.orders} ${r.email}`);