← back to Dw Signup Fulfillment
verification/tk10836/verify-abandonment.js
37 lines
'use strict';
// Cody hole #2: is Kelly's 0-orders silent abandonment at checkout?
// NOTE: abandonedCheckouts query-filtering is unreliable here, so we page and filter client-side.
const config = require('../../lib/config');
const shop = config.SHOP_DOMAIN, token = config.SHOPIFY_FULFILLMENT_TOKEN;
const TARGETS = ['kcyounge@gmail.com', 'kyounge@umich.edu'];
const Q = `
query($cursor: String) {
abandonedCheckouts(first: 100, after: $cursor) {
pageInfo { hasNextPage endCursor }
nodes { id createdAt customer { id email } totalPriceSet { shopMoney { amount } }
lineItems(first: 10) { nodes { title quantity } } }
}
}`;
(async () => {
let all = [], cursor = null;
for (let i = 0; i < 15; i++) {
const r = await fetch(`https://${shop}/admin/api/2024-10/graphql.json`, {
method: 'POST', headers: { 'X-Shopify-Access-Token': token, 'Content-Type': 'application/json' },
body: JSON.stringify({ query: Q, variables: { cursor } }) });
const j = await r.json();
if (j.errors) { console.error('ACCESS:', JSON.stringify(j.errors.map(e=>e.message))); return; }
const p = j.data.abandonedCheckouts;
all = all.concat(p.nodes);
if (!p.pageInfo.hasNextPage) break;
cursor = p.pageInfo.endCursor;
}
console.log(`abandoned checkouts scanned: ${all.length}`);
const range = all.map(n=>n.createdAt).sort();
console.log(`date range: ${range[0]} .. ${range[range.length-1]}`);
const hits = all.filter(n => n.customer && TARGETS.includes(String(n.customer.email||'').toLowerCase()));
console.log(`\nKelly abandoned checkouts: ${hits.length}`);
console.log(hits.length ? JSON.stringify(hits, null, 2) : ' NONE — no abandoned checkout on either of Kelly\'s emails.');
const post = all.filter(n => n.createdAt >= '2026-09-02');
console.log(`\n(abandoned checkouts recorded on/after 2026-09-02, any customer: ${post.length})`);
})().catch(e => { console.error('ERR', e.message); process.exit(1); });