[object Object]

← back to Gmc Titlefix

TK-10451: primary-source GMC $4.25 leak fix — canary proves overwriting sample offer in primary DS 180695450 wins the merge (3/3 served real roll price)

0ab1c50febf548566f79c1f0c770ded0317539b1 · 2026-08-27 17:35:25 -0700 · Steve Abrams

Files touched

Diff

commit 0ab1c50febf548566f79c1f0c770ded0317539b1
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Thu Aug 27 17:35:25 2026 -0700

    TK-10451: primary-source GMC $4.25 leak fix — canary proves overwriting sample offer in primary DS 180695450 wins the merge (3/3 served real roll price)
---
 .../shopify_US_7283813122099_42301068312627.json   |  39 +++++
 .../shopify_US_7421458415667_42654175232051.json   |  39 +++++
 .../shopify_US_7422637047859_42658306719795.json   |  35 +++++
 primary-fix-canary.mjs                             | 166 +++++++++++++++++++++
 4 files changed, 279 insertions(+)

diff --git a/data/primary-fix-rollback/shopify_US_7283813122099_42301068312627.json b/data/primary-fix-rollback/shopify_US_7283813122099_42301068312627.json
new file mode 100644
index 0000000..1962977
--- /dev/null
+++ b/data/primary-fix-rollback/shopify_US_7283813122099_42301068312627.json
@@ -0,0 +1,39 @@
+{
+  "capturedAt": "2026-08-28T00:16:47.429Z",
+  "dataSource": "accounts/146735262/dataSources/180695450",
+  "offerId": "shopify_US_7283813122099_42301068312627",
+  "productAttributes": {
+    "identifierExists": false,
+    "title": "Adorn Mid Century Floral Light Tan and Off-White by Malibu Wal... Sample",
+    "description": "Our professional sales staff at Designer Wallcoverings is here to assist with all of your interior designer product needs. We offer one stop purchasing of the most well respected names in the design trade as well as our own collections. 1-888-373-4564",
+    "link": "https://www.designerwallcoverings.com/products/dwqw-56287-handle?variant=42301068312627&country=US&currency=USD&utm_medium=product_sync&utm_source=google&utm_content=sag_organic&utm_campaign=sag_organic",
+    "imageLink": "https://cdn.shopify.com/s/files/1/0015/4117/7456/files/NE50505.jpg?v=1748381786",
+    "additionalImageLinks": [
+      "https://cdn.shopify.com/s/files/1/0015/4117/7456/files/room-living_room-dwqw-56287-handle.jpg?v=1775971154"
+    ],
+    "availability": "IN_STOCK",
+    "condition": "NEW",
+    "googleProductCategory": "Home & Garden > Decor > Wallpaper",
+    "itemGroupId": "shopify_US_7283813122099",
+    "price": {
+      "amountMicros": "4250000",
+      "currencyCode": "USD"
+    },
+    "productTypes": [
+      "Wallcovering"
+    ],
+    "sellOnGoogleQuantity": "2026",
+    "shippingWeight": {
+      "value": 0.35,
+      "unit": "lb"
+    },
+    "size": "Sample",
+    "productDetails": [
+      {
+        "sectionName": "Variant",
+        "attributeName": "size",
+        "attributeValue": "Sample"
+      }
+    ]
+  }
+}
\ No newline at end of file
diff --git a/data/primary-fix-rollback/shopify_US_7421458415667_42654175232051.json b/data/primary-fix-rollback/shopify_US_7421458415667_42654175232051.json
new file mode 100644
index 0000000..56c5714
--- /dev/null
+++ b/data/primary-fix-rollback/shopify_US_7421458415667_42654175232051.json
@@ -0,0 +1,39 @@
+{
+  "capturedAt": "2026-08-28T00:16:46.987Z",
+  "dataSource": "accounts/146735262/dataSources/180695450",
+  "offerId": "shopify_US_7421458415667_42654175232051",
+  "productAttributes": {
+    "identifierExists": false,
+    "title": "Jaspe - Quartz Light Grey By Cole & Son by Cole & Son Sample",
+    "description": "Our professional sales staff at Designer Wallcoverings is here to assist with all of your interior designer product needs. We offer one stop purchasing of the most well respected names in the design trade as well as our own collections. 1-888-373-4564",
+    "link": "https://www.designerwallcoverings.com/products/dwkk-g9886c389?variant=42654175232051&country=US&currency=USD&utm_medium=product_sync&utm_source=google&utm_content=sag_organic&utm_campaign=sag_organic",
+    "imageLink": "https://cdn.shopify.com/s/files/1/0015/4117/7456/files/106_3037_CS_2d26f29f-56a5-4fb1-8a9a-3418a022ace6.jpg?v=1753306290",
+    "additionalImageLinks": [
+      "https://cdn.shopify.com/s/files/1/0015/4117/7456/files/dwkk-g9886c389-swatch-spin.gif?v=1774092875"
+    ],
+    "availability": "IN_STOCK",
+    "condition": "NEW",
+    "googleProductCategory": "Home & Garden > Decor > Wallpaper",
+    "itemGroupId": "shopify_US_7421458415667",
+    "price": {
+      "amountMicros": "4250000",
+      "currencyCode": "USD"
+    },
+    "productTypes": [
+      "Wallcovering"
+    ],
+    "sellOnGoogleQuantity": "1000",
+    "shippingWeight": {
+      "value": 0.35,
+      "unit": "lb"
+    },
+    "size": "Sample",
+    "productDetails": [
+      {
+        "sectionName": "Variant",
+        "attributeName": "size",
+        "attributeValue": "Sample"
+      }
+    ]
+  }
+}
\ No newline at end of file
diff --git a/data/primary-fix-rollback/shopify_US_7422637047859_42658306719795.json b/data/primary-fix-rollback/shopify_US_7422637047859_42658306719795.json
new file mode 100644
index 0000000..8abc342
--- /dev/null
+++ b/data/primary-fix-rollback/shopify_US_7422637047859_42658306719795.json
@@ -0,0 +1,35 @@
+{
+  "capturedAt": "2026-08-28T00:16:46.540Z",
+  "dataSource": "accounts/146735262/dataSources/180695450",
+  "offerId": "shopify_US_7422637047859_42658306719795",
+  "productAttributes": {
+    "identifierExists": false,
+    "title": "Sample: Kravet Design - W3653-416 Gold Wallcovering by Kravet Design",
+    "description": "Our professional sales staff at Designer Wallcoverings is here to assist with all of your interior designer product needs. We offer one stop purchasing of the most well respected names in the design trade as well as our own collections. 1-888-373-4564",
+    "link": "https://www.designerwallcoverings.com/products/dwkk-128752?variant=42658306719795&country=US&currency=USD&utm_medium=product_sync&utm_source=google&utm_content=sag_organic&utm_campaign=sag_organic",
+    "imageLink": "https://cdn.shopify.com/s/files/1/0015/4117/7456/files/W3653_416_0fdbdcfc-0456-4b9b-808e-ae844d7712b2.jpg?v=1753292362",
+    "availability": "IN_STOCK",
+    "condition": "NEW",
+    "googleProductCategory": "Home & Garden > Decor > Wallpaper",
+    "price": {
+      "amountMicros": "4250000",
+      "currencyCode": "USD"
+    },
+    "productTypes": [
+      "Wallcovering"
+    ],
+    "sellOnGoogleQuantity": "1000",
+    "shippingWeight": {
+      "value": 0.35,
+      "unit": "lb"
+    },
+    "size": "Sample",
+    "productDetails": [
+      {
+        "sectionName": "Variant",
+        "attributeName": "size",
+        "attributeValue": "Sample"
+      }
+    ]
+  }
+}
\ No newline at end of file
diff --git a/primary-fix-canary.mjs b/primary-fix-canary.mjs
new file mode 100644
index 0000000..e60daef
--- /dev/null
+++ b/primary-fix-canary.mjs
@@ -0,0 +1,166 @@
+// TK-10451 PRIMARY-SOURCE fix canary.
+// Overwrites the $4.25 SAMPLE-variant offer that lives in PRIMARY DS 180695450
+// (Content API, input=API — the Shopify Google&YouTube channel's offers) with the
+// REAL ROLL variant's full attributes (title/link/sku/price/weight), so the primary
+// feed asserts the real roll price. Same offerId => productInputs:insert REPLACES the
+// existing input on the same DS (no duplicate, no merge to lose).
+//
+// SAFETY:
+//  - Captures the EXACT current processed productInput to data/primary-fix-rollback/<offerId>.json
+//    BEFORE writing, so the write is reversible (re-insert the captured $4.25 body).
+//  - Sends FULL productAttributes (insert replaces the whole input; a partial body would
+//    erase title/image/link/etc — codex-flagged).
+//  - --apply required to write; default is DRY-RUN (prints the planned body only).
+//  - --verify reads back the served price via Content API v2.1 products.get.
+//
+//   node primary-fix-canary.mjs                 # DRY-RUN: show planned roll-offer body for the canary set
+//   node primary-fix-canary.mjs --apply         # GATED: write the canary set to primary DS 180695450
+//   node primary-fix-canary.mjs --verify        # read back served price (run ~a few min after apply)
+//   node primary-fix-canary.mjs --rollback --apply   # REVERT: re-insert captured $4.25 bodies
+import fs from 'fs';
+import { createRequire } from 'module';
+const require = createRequire(import.meta.url);
+const { token, MERCHANT } = require('./_auth.js');
+
+const PRIMARY_DS = `accounts/${MERCHANT}/dataSources/180695450`;
+const ROLLBACK_DIR = new URL('./data/primary-fix-rollback/', import.meta.url).pathname;
+fs.mkdirSync(ROLLBACK_DIR, { recursive: true });
+const args = process.argv.slice(2);
+const has = f => args.includes(f);
+const APPLY = has('--apply');
+const sleep = ms => new Promise(r => setTimeout(r, ms));
+
+// Canary set: pid -> {rollVid, sampleVid}. Small, verified, enumerable.
+const CANARY = [
+  { name: 'Kravet W3653-416', pid: '7422637047859', roll: '44466525044787', sample: '42658306719795' },
+  { name: 'Cole&Son Jaspe',   pid: '7421458415667', roll: '44346656325683', sample: '42654175232051' },
+  { name: 'Malibu Cypress',   pid: '7283813122099', roll: '42301335371827', sample: '42301068312627' },
+];
+
+const envTxt = fs.readFileSync(process.env.HOME + '/Projects/secrets-manager/.env', 'utf8');
+const g = k => (envTxt.match(new RegExp('^' + k + '=(.*)$', 'm')) || [])[1]?.trim();
+const SHOP_TOKEN = g('SHOPIFY_ADMIN_TOKEN');
+const DOMAIN = 'designer-laboratory-sandbox.myshopify.com';
+
+async function shopifyProduct(pid) {
+  const r = await fetch(`https://${DOMAIN}/admin/api/2024-10/products/${pid}.json`, {
+    headers: { 'X-Shopify-Access-Token': SHOP_TOKEN, 'Content-Type': 'application/json' } });
+  return (await r.json()).product;
+}
+
+async function getProcessed(tok, offerId) {
+  const name = `accounts/${MERCHANT}/products/online~en~US~${offerId}`;
+  const r = await fetch(`https://merchantapi.googleapis.com/products/v1/${name}`, {
+    headers: { Authorization: 'Bearer ' + tok, Accept: 'application/json' } });
+  return { status: r.status, body: await r.json() };
+}
+
+async function getServedV21(tok, offerId) {
+  const rid = `online:en:US:${offerId}`;
+  const r = await fetch(`https://shoppingcontent.googleapis.com/content/v2.1/${MERCHANT}/products/${encodeURIComponent(rid)}`,
+    { headers: { Authorization: 'Bearer ' + tok } });
+  return r.json();
+}
+
+// Build the FULL roll-variant productAttributes from the current (sample) processed offer + Shopify roll variant.
+function buildRollBody(processed, product, rollVid) {
+  const rv = (product.variants || []).find(v => String(v.id) === String(rollVid));
+  const pa = processed.productAttributes || {};
+  // Roll title: strip "Sample: " prefix; use the product title (roll identity).
+  const rollTitle = (product.title || pa.title || '').replace(/^Sample:\s*/i, '').slice(0, 150);
+  const rollLink = (pa.link || '').replace(/([?&]variant=)\d+/, `$1${rollVid}`) ||
+    `https://www.designerwallcoverings.com/products/${product.handle}?variant=${rollVid}&country=US&currency=USD`;
+  const rollWeightLb = /wallcovering/i.test((pa.productTypes || []).join(' ') + (product.product_type || '')) ? 4 : 1;
+  return {
+    offerId: processed.offerId,
+    contentLanguage: 'en',
+    feedLabel: 'US',
+    productAttributes: {
+      title: rollTitle,
+      description: pa.description,
+      link: rollLink,
+      imageLink: pa.imageLink,
+      additionalImageLinks: pa.additionalImageLinks || [],
+      availability: pa.availability || 'in_stock',
+      condition: 'new',
+      price: { amountMicros: String(Math.round(parseFloat(rv.price) * 1e6)), currencyCode: 'USD' },
+      brand: pa.brand,
+      mpn: rv.sku || pa.mpn,
+      gtin: pa.gtin,
+      googleProductCategory: pa.googleProductCategory,
+      productTypes: pa.productTypes || [],
+      shippingWeight: { value: rollWeightLb, unit: 'lb' },
+    },
+    _meta: { rollSku: rv.sku, rollPrice: rv.price, oldPrice: pa.price?.amountMicros, rollTitle },
+  };
+}
+
+async function main() {
+  let tok = await token();
+  const ROLLBACK = has('--rollback');
+
+  if (ROLLBACK) {
+    // Re-insert captured original bodies.
+    for (const c of CANARY) {
+      const offerId = `shopify_US_${c.pid}_${c.sample}`;
+      const f = ROLLBACK_DIR + offerId + '.json';
+      if (!fs.existsSync(f)) { console.log(`  [skip] no rollback capture for ${offerId}`); continue; }
+      const orig = JSON.parse(fs.readFileSync(f, 'utf8'));
+      const body = {
+        offerId, contentLanguage: 'en', feedLabel: 'US',
+        productAttributes: orig.productAttributes,
+      };
+      if (!APPLY) { console.log(`[DRY rollback] would restore ${offerId} price=${orig.productAttributes?.price?.amountMicros}`); continue; }
+      const url = `https://merchantapi.googleapis.com/products/v1/accounts/${MERCHANT}/productInputs:insert?dataSource=${encodeURIComponent(PRIMARY_DS)}`;
+      const r = await fetch(url, { method: 'POST', headers: { Authorization: 'Bearer ' + tok, 'Content-Type': 'application/json' }, body: JSON.stringify(body) });
+      console.log(`[rollback] ${offerId} -> ${r.status} ${r.ok ? 'OK' : (await r.text()).slice(0, 120)}`);
+      await sleep(300);
+    }
+    return;
+  }
+
+  const plans = [];
+  for (const c of CANARY) {
+    const offerId = `shopify_US_${c.pid}_${c.sample}`;
+    const { status, body: processed } = await getProcessed(tok, offerId);
+    if (status !== 200) { console.log(`  [skip] ${c.name} ${offerId} processed get ${status}`); continue; }
+    if (processed.dataSource !== PRIMARY_DS) {
+      console.log(`  [SKIP-OWNERSHIP] ${c.name} owned by ${processed.dataSource}, not ${PRIMARY_DS} — refusing to write (would transfer ownership).`);
+      continue;
+    }
+    // capture EXACT original for rollback (before any write)
+    fs.writeFileSync(ROLLBACK_DIR + offerId + '.json', JSON.stringify({ capturedAt: new Date().toISOString(), dataSource: processed.dataSource, offerId, productAttributes: processed.productAttributes }, null, 2));
+    const product = await shopifyProduct(c.pid);
+    const plan = buildRollBody(processed, product, c.roll);
+    plans.push({ c, plan });
+    console.log(`\n${c.name}  ${offerId}`);
+    console.log(`  old: $${(Number(plan._meta.oldPrice) / 1e6).toFixed(2)}  "${processed.productAttributes?.title?.slice(0, 45)}"`);
+    console.log(`  new: $${plan._meta.rollPrice}  sku=${plan._meta.rollSku}  "${plan._meta.rollTitle.slice(0, 45)}"`);
+  }
+
+  if (!APPLY) { console.log(`\nDRY-RUN — ${plans.length} planned. Re-run with --apply to write to primary DS ${PRIMARY_DS}.`); return; }
+
+  console.log(`\n=== APPLYING ${plans.length} to primary DS ${PRIMARY_DS} ===`);
+  for (const { c, plan } of plans) {
+    const body = { offerId: plan.offerId, contentLanguage: plan.contentLanguage, feedLabel: plan.feedLabel, productAttributes: plan.productAttributes };
+    const url = `https://merchantapi.googleapis.com/products/v1/accounts/${MERCHANT}/productInputs:insert?dataSource=${encodeURIComponent(PRIMARY_DS)}`;
+    const r = await fetch(url, { method: 'POST', headers: { Authorization: 'Bearer ' + tok, 'Content-Type': 'application/json' }, body: JSON.stringify(body) });
+    const t = await r.text();
+    console.log(`  ${c.name} ${plan.offerId} -> ${r.status} ${r.ok ? 'OK' : t.slice(0, 200)}`);
+    await sleep(400);
+  }
+  console.log('\nApplied. Wait a few minutes, then: node primary-fix-canary.mjs --verify');
+}
+
+if (has('--verify')) {
+  const tok = await token();
+  console.log('=== VERIFY served price (Content API v2.1 products.get) ===');
+  for (const c of CANARY) {
+    const offerId = `shopify_US_${c.pid}_${c.sample}`;
+    const pr = await getServedV21(tok, offerId);
+    if (pr.error) { console.log(`  ${c.name} ${offerId}: ${pr.error.code} ${(pr.error.message || '').slice(0, 40)}`); continue; }
+    console.log(`  ${c.name} ${offerId}: SERVED $${pr.price?.value} title="${(pr.title || '').slice(0, 45)}"`);
+  }
+} else {
+  main().catch(e => { console.error('FATAL', e.message); process.exit(1); });
+}

← 463ca3d track canary tooling (apply-canary/build-fresh-canary/verify  ·  back to Gmc Titlefix  ·  TK-10862: scaled primary-fix batch runner (capped, reversibl b76a6a6 →