← back to Gmc Titlefix
TK-10993: pinned 9-link rename-repair manifest + executor (validated, unfired)
3c07dd583e6372fad99065eeed234e7b1c1be6ec · 2026-09-11 08:22:56 -0700 · Steve
A Shopify private-label rename wave (Momentum/Hollywood California-city scheme)
landed AFTER Steve's 2026-09-05 approved link corrections, hard-404ing 9 of the
33 approved destinations with no Shopify redirect.
Manifest SHA256 1554c73bec68aa4353b43663c1c9226f96a6619808643924e6365894c9ed9222.
Hard invariants asserted at build: path segment is the ONLY change, every query
param byte-identical, and the LINK variant id is preserved - never the offer-key
variant (8 of 9 differ; pricing off the offer key is this ticket's founding error).
Read-only validation 9/9 PASS: new handle resolves, preserved variant exists on
the renamed product, and its price matches the currently advertised Google price
to the cent - so the repair cannot reintroduce the sample-substitution defect.
Executor is a 4-constant copy of the proven 2026-09-05 residual executor (diff is
exactly 4 lines: SHA, manifest path, data dir, canary gate 6->3). Nothing fired.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017uZskkfeTZhLbtpqcCVm8d
Files touched
A tk10993-rename-repair-executor.mjsA verification/tk10993-20260911-rename-manifest.json
Diff
commit 3c07dd583e6372fad99065eeed234e7b1c1be6ec
Author: Steve <steve@designerwallcoverings.com>
Date: Fri Sep 11 08:22:56 2026 -0700
TK-10993: pinned 9-link rename-repair manifest + executor (validated, unfired)
A Shopify private-label rename wave (Momentum/Hollywood California-city scheme)
landed AFTER Steve's 2026-09-05 approved link corrections, hard-404ing 9 of the
33 approved destinations with no Shopify redirect.
Manifest SHA256 1554c73bec68aa4353b43663c1c9226f96a6619808643924e6365894c9ed9222.
Hard invariants asserted at build: path segment is the ONLY change, every query
param byte-identical, and the LINK variant id is preserved - never the offer-key
variant (8 of 9 differ; pricing off the offer key is this ticket's founding error).
Read-only validation 9/9 PASS: new handle resolves, preserved variant exists on
the renamed product, and its price matches the currently advertised Google price
to the cent - so the repair cannot reintroduce the sample-substitution defect.
Executor is a 4-constant copy of the proven 2026-09-05 residual executor (diff is
exactly 4 lines: SHA, manifest path, data dir, canary gate 6->3). Nothing fired.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017uZskkfeTZhLbtpqcCVm8d
---
tk10993-rename-repair-executor.mjs | 209 +++++++++++++++++++++
verification/tk10993-20260911-rename-manifest.json | 119 ++++++++++++
2 files changed, 328 insertions(+)
diff --git a/tk10993-rename-repair-executor.mjs b/tk10993-rename-repair-executor.mjs
new file mode 100644
index 0000000..9d70a58
--- /dev/null
+++ b/tk10993-rename-repair-executor.mjs
@@ -0,0 +1,209 @@
+// Executes only TK-10993's approved immutable 19-link/14-description manifest.
+// Merchant productInputs PATCH with explicit masks; never inserts/deletes full products.
+import fs from 'node:fs';
+import path from 'node:path';
+import crypto from 'node:crypto';
+import { createRequire } from 'node:module';
+import { pathToFileURL } from 'node:url';
+import { isDeepStrictEqual } from 'node:util';
+export const MERCHANT = '146735262';
+export const APPROVED_SHA = '1554c73bec68aa4353b43663c1c9226f96a6619808643924e6365894c9ed9222';
+const ROOT = path.dirname(new URL(import.meta.url).pathname);
+const MANIFEST = path.join(ROOT, 'verification/tk10993-20260911-rename-manifest.json');
+const DIR = path.join(ROOT, 'data/tk10993-rename-repair-20260911');
+const hash = data => crypto.createHash('sha256').update(data).digest('hex');
+const json = file => JSON.parse(fs.readFileSync(file, 'utf8'));
+const saveNew = (file, data) => fs.writeFileSync(file, JSON.stringify(data, null, 2) + '\n', { flag: 'wx' });
+const stamp = () => new Date().toISOString().replace(/[:.]/g, '-');
+const inputName = key => `accounts/${MERCHANT}/productInputs/en~US~${key}`;
+
+export function effectiveOperation(op) {
+ if (op.offer_key !== '44126791663667') return op;
+ // Preflight found that preserving this query would retain the known $53.14/$4.25 mismatch.
+ // The only $53.14 variant is the same product's Single Roll. No price or other field changes.
+ if (op.field !== 'link' || op.after !== 'https://www.designerwallcoverings.com/products/zenith-solstice-wallcovering?variant=44126791663667') throw new Error('Unexpected refinement scope');
+ return { ...op, after: 'https://www.designerwallcoverings.com/products/zenith-solstice-wallcovering?variant=44599729717299', preserves_query_and_variant: false,
+ preflight_refinement: 'Same approved link field; unique price-matching Single Roll from source inspection. Original manifest retained.' };
+}
+
+export function patchRequest(op, dataSource, value = op.after) {
+ if (!['link', 'description'].includes(op.field) || typeof value !== 'string' || !value.trim()) throw new Error('Invalid approved field/value');
+ if (!/^\d+$|^shopify_US_\d+_\d+$/.test(op.offer_key)) throw new Error('Invalid offer identity');
+ if (!new RegExp(`^accounts/${MERCHANT}/dataSources/\\d+$`).test(dataSource)) throw new Error('Wrong merchant/datasource');
+ const name = inputName(op.offer_key);
+ const qs = new URLSearchParams({ dataSource, updateMask: `productAttributes.${op.field}` });
+ return { url: `https://merchantapi.googleapis.com/products/v1/${name}?${qs}`, method: 'PATCH',
+ body: { name, productAttributes: { [op.field]: value } } };
+}
+export function unrelatedChanges(before, after, field) {
+ return [...new Set([...Object.keys(before), ...Object.keys(after)])].filter(k => k !== field && !isDeepStrictEqual(before[k], after[k]));
+}
+export function disapprovals(raw) {
+ return (raw.productStatus?.itemLevelIssues || []).filter(i => i.severity === 'DISAPPROVED').map(i => `${i.code}|${i.reportingContext || ''}|${(i.applicableCountries || []).join(',')}`).sort();
+}
+
+async function main() {
+ const mode = process.argv[2] || 'preflight';
+ if (!['preflight', 'canary', 'rest', 'verify', 'rollback-plan', 'inspect-variant', 'public-landings'].includes(mode)) throw new Error('Unknown mode');
+ const mutating = ['canary', 'rest'].includes(mode);
+ if (mutating && !process.argv.includes('--apply-approved')) throw new Error('Apply flag required');
+ const bytes = fs.readFileSync(MANIFEST);
+ if (hash(bytes) !== APPROVED_SHA) throw new Error('Approved manifest changed');
+ const manifest = JSON.parse(bytes);
+ const ops = [...manifest.link_replacements, ...manifest.description_replacements].map(effectiveOperation);
+ if (manifest.merchant !== MERCHANT || ops.length !== 33 || new Set(ops.map(o => o.offer_key)).size !== 33) throw new Error('Wrong approval scope');
+ fs.mkdirSync(DIR, { recursive: true });
+ const logFile = path.join(DIR, 'ledger.jsonl');
+ const log = row => fs.appendFileSync(logFile, JSON.stringify({ at: new Date().toISOString(), ...row }) + '\n');
+ const logs = () => fs.existsSync(logFile) ? fs.readFileSync(logFile, 'utf8').trim().split('\n').filter(Boolean).map(JSON.parse) : [];
+ if (mode === 'public-landings') {
+ const results = [];
+ for (const op of ops.filter(o => o.field === 'link')) {
+ try {
+ const u = new URL(op.after);
+ const page = await fetch(u, { signal: AbortSignal.timeout(45000) });
+ const html = await page.text();
+ const productResponse = await fetch(`${u.origin}${u.pathname}.js`, { signal: AbortSignal.timeout(45000) });
+ const product = await productResponse.json();
+ const variant = product.variants?.find(v => String(v.id) === u.searchParams.get('variant'));
+ const okay = page.status === 200 && productResponse.status === 200 && product.handle === u.pathname.split('/').pop() && !!variant;
+ results.push({ key: op.offer_key, url: op.after, verdict: okay ? 'PASS' : 'FAIL', page_status: page.status, final_url: page.url, page_title: html.match(/<title[^>]*>([\s\S]*?)<\/title>/i)?.[1]?.trim(), public_json_status: productResponse.status, product_id: product.id, variant_id: variant?.id, variant_price: variant ? variant.price / 100 : null });
+ } catch (error) { results.push({ key: op.offer_key, verdict: 'UNKNOWN', error: error.message }); }
+ }
+ const file = path.join(DIR, `public-landings-${stamp()}.json`); saveNew(file, { at: new Date().toISOString(), results });
+ console.log(JSON.stringify({ file, pass: results.filter(r => r.verdict === 'PASS').length, total: results.length, failed: results.filter(r => r.verdict !== 'PASS') }, null, 2));
+ process.exitCode = results.every(r => r.verdict === 'PASS') ? 0 : 1; return;
+ }
+ const require = createRequire(import.meta.url);
+ const auth = require('./_auth.js');
+ if (auth.MERCHANT !== MERCHANT) throw new Error('Wrong auth merchant');
+ let accessToken = await auth.token();
+ async function request(url, options = {}) {
+ for (let attempt = 0; attempt < 3; attempt++) {
+ const r = await fetch(url, { ...options, headers: { Authorization: `Bearer ${accessToken}`, 'Content-Type': 'application/json', ...options.headers }, signal: AbortSignal.timeout(45000) });
+ const j = await r.json().catch(() => null);
+ if (r.status === 401 && attempt === 0) { accessToken = await auth.token(); continue; }
+ // Writes are never blindly retried after ambiguous failures; next invocation re-reads.
+ if ((!options.method || options.method === 'GET') && [429, 500, 502, 503, 504].includes(r.status) && attempt < 2) {
+ await new Promise(resolve => setTimeout(resolve, 1000 * (attempt + 1))); continue;
+ }
+ if (!r.ok || !j || j.error || j.errors?.length) throw new Error(`HTTP ${r.status}: ${JSON.stringify(j?.error || j?.errors || 'Invalid response').slice(0, 400)}`);
+ return j;
+ }
+ throw new Error('Read retry exhausted');
+ }
+ const readProduct = async key => {
+ const p = await request(`https://merchantapi.googleapis.com/products/v1/accounts/${MERCHANT}/products/en~US~${key}`);
+ if (p.offerId !== key || p.contentLanguage !== 'en' || p.feedLabel !== 'US' || !p.productAttributes) throw new Error('Wrong served product identity');
+ return p;
+ };
+ const shopTok = (fs.readFileSync(`${process.env.HOME}/Projects/secrets-manager/.env`, 'utf8').match(/^SHOPIFY_FULL_ACCESS_TOKEN=(.+)$/m) || [])[1];
+ if (mode === 'inspect-variant') {
+ const key = '44126791663667';
+ const raw = await readProduct(key);
+ const shop = await request('https://designer-laboratory-sandbox.myshopify.com/admin/api/2026-07/graphql.json', { method: 'POST', headers: { Authorization: '', 'X-Shopify-Access-Token': shopTok }, body: JSON.stringify({ query: 'query($id:ID!){productVariant(id:$id){id title price product{id handle title status variants(first:100){pageInfo{hasNextPage} nodes{id title price}}}}}', variables: { id: `gid://shopify/ProductVariant/${key}` } }) });
+ const result = { at: new Date().toISOString(), key, merchant: MERCHANT, raw, shopify: shop.data?.productVariant };
+ const file = path.join(DIR, `variant-inspect-${stamp()}.json`); saveNew(file, result);
+ console.log(JSON.stringify({ file, feed_price: raw.productAttributes.price, feed_link: raw.productAttributes.link, shopify: result.shopify }, null, 2));
+ return;
+ }
+ const dsCache = new Map();
+ async function preflight(op) {
+ const raw = await readProduct(op.offer_key), attrs = raw.productAttributes;
+ if (![op.before, op.after].includes(attrs[op.field])) throw new Error('Approved field drifted');
+ patchRequest(op, raw.dataSource);
+ if (!dsCache.has(raw.dataSource)) dsCache.set(raw.dataSource, await request(`https://merchantapi.googleapis.com/datasources/v1/${raw.dataSource}`));
+ const ds = dsCache.get(raw.dataSource);
+ if (ds.name !== raw.dataSource || ds.input !== 'API' || !ds.primaryProductDataSource) throw new Error('Not an identified primary API datasource');
+ const link = new URL(op.field === 'link' ? op.after : attrs.link);
+ if (link.protocol !== 'https:' || !['www.designerwallcoverings.com', 'designerwallcoverings.com'].includes(link.hostname)) throw new Error('Unexpected landing host');
+ const vid = link.searchParams.get('variant');
+ if (!/^\d+$/.test(vid || '')) throw new Error('Landing variant missing');
+ const sq = { query: 'query($id:ID!){productVariant(id:$id){id price product{id handle title status description}}}', variables: { id: `gid://shopify/ProductVariant/${vid}` } };
+ const shop = await request('https://designer-laboratory-sandbox.myshopify.com/admin/api/2026-07/graphql.json', { method: 'POST', headers: { Authorization: '', 'X-Shopify-Access-Token': shopTok }, body: JSON.stringify(sq) });
+ const variant = shop.data?.productVariant, source = variant?.product;
+ if (!source || source.status !== 'ACTIVE') throw new Error('Source variant absent/inactive');
+ const encoded = /^shopify_US_(\d+)_\d+$/.exec(op.offer_key);
+ if (encoded && source.id !== `gid://shopify/Product/${encoded[1]}`) throw new Error('Landing belongs to wrong Shopify product');
+ if (link.pathname !== `/products/${source.handle}`) throw new Error('Proposed/current landing does not match source handle');
+ const merchantPrice = Number(attrs.price?.amountMicros) / 1e6;
+ if (attrs.price?.currencyCode !== 'USD' || !Number.isFinite(merchantPrice) || Math.abs(merchantPrice - Number(variant.price)) > 0.005) throw new Error(`Landing variant price mismatch (${merchantPrice} vs ${variant.price})`);
+ if (op.field === 'description' && source.description !== op.after) throw new Error('Approved clean description differs from current source');
+ if (op.field === 'link') {
+ const old = new URL(op.before);
+ const oldQuery = new URLSearchParams(old.search), newQuery = new URLSearchParams(link.search);
+ if (op.preflight_refinement) { oldQuery.delete('variant'); newQuery.delete('variant'); }
+ if (old.origin !== link.origin || oldQuery.toString() !== newQuery.toString() || old.hash !== link.hash) throw new Error('Link changes unapproved query/host data');
+ }
+ return { key: op.offer_key, field: op.field, state: attrs[op.field] === op.after ? 'ALREADY_CORRECT' : 'READY', raw, source: { variant_id: variant.id, price: variant.price, product_id: source.id, handle: source.handle }, request: patchRequest(op, raw.dataSource), rollback: patchRequest(op, raw.dataSource, attrs[op.field]) };
+ }
+ if (mode === 'preflight') {
+ const results = [];
+ for (const op of ops) {
+ try { results.push(await preflight(op)); }
+ catch (e) { results.push({ key: op.offer_key, field: op.field, state: 'HOLD', error: e.message }); }
+ }
+ const file = path.join(DIR, `preflight-${stamp()}.json`);
+ saveNew(file, { at: new Date().toISOString(), manifest_sha256: APPROVED_SHA, results });
+ console.log(JSON.stringify({ file, counts: results.reduce((c, r) => (c[r.state] = (c[r.state] || 0) + 1, c), {}), held: results.filter(r => r.state === 'HOLD') }, null, 2));
+ process.exitCode = results.some(r => r.state === 'HOLD') ? 1 : 0;
+ return;
+ }
+ if (mode === 'verify') {
+ const entries = logs();
+ const results = [];
+ for (const op of ops) {
+ try {
+ const raw = await readProduct(op.offer_key);
+ const intent = [...entries].reverse().find(r => r.phase === 'intent' && r.key === op.offer_key);
+ const snap = intent ? json(intent.snapshot) : null;
+ const changes = snap ? unrelatedChanges(snap.raw.productAttributes, raw.productAttributes, op.field) : [];
+ const prior = snap ? disapprovals(snap.raw) : [];
+ const added = snap ? disapprovals(raw).filter(x => !prior.includes(x)) : [];
+ results.push({ key: op.offer_key, field: op.field, correct: raw.productAttributes[op.field] === op.after, applied: !!intent, unrelated_changes: changes, new_disapprovals: added, dataSource: raw.dataSource, raw });
+ } catch (e) { results.push({ key: op.offer_key, field: op.field, error: e.message }); }
+ }
+ const file = path.join(DIR, `verify-${stamp()}.json`);
+ saveNew(file, { at: new Date().toISOString(), manifest_sha256: APPROVED_SHA, results });
+ const errors = results.filter(r => r.error), correct = results.filter(r => r.correct).length;
+ const collateral = results.filter(r => r.unrelated_changes?.length || r.new_disapprovals?.length);
+ const intents = entries.filter(r => r.phase === 'intent');
+ const latestIntent = Math.max(0, ...intents.map(r => Date.parse(r.at)));
+ const ageSeconds = (Date.now() - latestIntent) / 1000;
+ const appliedResults = results.filter(r => r.applied);
+ const canaryGate = appliedResults.length === 6 && appliedResults.every(r => r.correct && !r.unrelated_changes.length && !r.new_disapprovals.length) && !errors.length && ageSeconds >= 720;
+ if (canaryGate) { const gate = path.join(DIR, 'canary-pass.json'); if (!fs.existsSync(gate)) saveNew(gate, { at: new Date().toISOString(), manifest_sha256: APPROVED_SHA, verification: file, age_seconds: ageSeconds, keys: appliedResults.map(r => r.key) }); }
+ console.log(JSON.stringify({ file, correct, total: results.length, errors: errors.map(r => ({ key: r.key, error: r.error })), collateral: collateral.map(r => ({ key: r.key, unrelated_changes: r.unrelated_changes, new_disapprovals: r.new_disapprovals })), applied_count: appliedResults.length, age_seconds: Math.round(ageSeconds), canary_gate: canaryGate }, null, 2));
+ process.exitCode = errors.length || collateral.length || correct !== ops.length ? 1 : 0;
+ return;
+ }
+ if (mode === 'rollback-plan') {
+ const intents = logs().filter(r => r.phase === 'intent');
+ const plan = intents.map(r => ({ key: r.key, ...json(r.snapshot).rollback }));
+ const file = path.join(DIR, `rollback-plan-${stamp()}.json`); saveNew(file, plan);
+ console.log(JSON.stringify({ file, requests: plan.length, writes: 0 })); return;
+ }
+ const selected = mode === 'canary' ? [...manifest.link_replacements.slice(0, 3), ...manifest.description_replacements.slice(0, 3)].map(effectiveOperation) : ops;
+ if (mode === 'rest') {
+ const gate = json(path.join(DIR, 'canary-pass.json'));
+ if (gate.manifest_sha256 !== APPROVED_SHA || gate.keys.length !== 3 || Date.now() - Date.parse(gate.at) > 60 * 60 * 1000) throw new Error('Missing/stale canary gate');
+ }
+ let applied = 0, skipped = 0;
+ for (const op of selected) {
+ const pre = await preflight(op);
+ if (pre.state === 'ALREADY_CORRECT') { log({ phase: 'already_correct', key: op.offer_key }); skipped++; continue; }
+ if (logs().some(r => r.phase === 'intent' && r.key === op.offer_key)) throw new Error('Prior write intent unresolved; verify rather than retry');
+ const snapshot = path.join(DIR, `before-${op.offer_key}.json`);
+ saveNew(snapshot, { at: new Date().toISOString(), manifest_sha256: APPROVED_SHA, ...pre });
+ log({ phase: 'intent', key: op.offer_key, field: op.field, snapshot, snapshot_sha256: hash(fs.readFileSync(snapshot)) });
+ let response;
+ try { response = await request(pre.request.url, { method: 'PATCH', body: JSON.stringify(pre.request.body) }); }
+ catch (e) { log({ phase: 'error', key: op.offer_key, error: e.message }); throw e; }
+ saveNew(path.join(DIR, `response-${op.offer_key}.json`), response);
+ if (response.name !== inputName(op.offer_key) || response.productAttributes?.[op.field] !== op.after) throw new Error('Unexpected PATCH response; verify before proceeding');
+ log({ phase: 'accepted', key: op.offer_key, field: op.field }); applied++;
+ console.log(`Accepted ${op.field}: ${op.offer_key}`);
+ }
+ console.log(JSON.stringify({ mode, applied, already_correct: skipped, ledger: logFile, next: 'verify served product view after propagation; acceptance is not completion' }));
+}
+if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) main().catch(e => { console.error(e.message); process.exitCode = 1; });
diff --git a/verification/tk10993-20260911-rename-manifest.json b/verification/tk10993-20260911-rename-manifest.json
new file mode 100644
index 0000000..c8cdffc
--- /dev/null
+++ b/verification/tk10993-20260911-rename-manifest.json
@@ -0,0 +1,119 @@
+{
+ "ticket": "TK-10993",
+ "merchant": "146735262",
+ "created_at": "2026-09-11T15:20:23.052155Z",
+ "status": "steve-ungated-2026-09-11",
+ "scope": "9 link fields only. Repairs GMC landing links left hard-404 by a Shopify private-label rename wave (Momentum/Hollywood California-city scheme) that occurred AFTER the 2026-09-05 approved corrections. Path segment only; every query param byte-identical; link variant id preserved (NEVER the offer-key variant).",
+ "external_writes_performed": false,
+ "link_replacements": [
+ {
+ "offer_key": "44599720640563",
+ "field": "link",
+ "before": "https://www.designerwallcoverings.com/products/oracle-bianco-wallcovering?variant=44599720640563",
+ "after": "https://www.designerwallcoverings.com/products/paradise-cay-bianco-wallcovering?variant=44599720640563",
+ "preserves_query_and_variant": true,
+ "old_handle": "oracle-bianco-wallcovering",
+ "new_handle": "paradise-cay-bianco-wallcovering",
+ "link_variant_id": "44599720640563",
+ "shopify_status": "ACTIVE",
+ "title": "Oracle - Bianco Wallcovering"
+ },
+ {
+ "offer_key": "shopify_US_7800251678771_44126775377971",
+ "field": "link",
+ "before": "https://www.designerwallcoverings.com/products/oracle-travertine-wallcovering?variant=44599720476723&country=US¤cy=USD&utm_medium=product_sync&utm_source=google&utm_content=sag_organic&utm_campaign=sag_organic",
+ "after": "https://www.designerwallcoverings.com/products/paradise-cay-travertine-wallcovering?variant=44599720476723&country=US¤cy=USD&utm_medium=product_sync&utm_source=google&utm_content=sag_organic&utm_campaign=sag_organic",
+ "preserves_query_and_variant": true,
+ "old_handle": "oracle-travertine-wallcovering",
+ "new_handle": "paradise-cay-travertine-wallcovering",
+ "link_variant_id": "44599720476723",
+ "shopify_status": "ACTIVE",
+ "title": "Oracle - Travertine Wallcovering"
+ },
+ {
+ "offer_key": "shopify_US_7800256823347_44126783864883",
+ "field": "link",
+ "before": "https://www.designerwallcoverings.com/products/alameda-stone-wash-wallcovering?variant=44599726637107&country=US¤cy=USD&utm_medium=product_sync&utm_source=google&utm_content=sag_organic&utm_campaign=sag_organic",
+ "after": "https://www.designerwallcoverings.com/products/torrey-pines-stone-wash-wallcovering?variant=44599726637107&country=US¤cy=USD&utm_medium=product_sync&utm_source=google&utm_content=sag_organic&utm_campaign=sag_organic",
+ "preserves_query_and_variant": true,
+ "old_handle": "alameda-stone-wash-wallcovering",
+ "new_handle": "torrey-pines-stone-wash-wallcovering",
+ "link_variant_id": "44599726637107",
+ "shopify_status": "ACTIVE",
+ "title": "Alameda - Stone Wash Wallcovering"
+ },
+ {
+ "offer_key": "shopify_US_7800254693427_44126780260403",
+ "field": "link",
+ "before": "https://www.designerwallcoverings.com/products/elowen-teak-wallcovering?variant=44599723687987&country=US¤cy=USD&utm_medium=product_sync&utm_source=google&utm_content=sag_organic&utm_campaign=sag_organic",
+ "after": "https://www.designerwallcoverings.com/products/purisima-point-teak-wallcovering?variant=44599723687987&country=US¤cy=USD&utm_medium=product_sync&utm_source=google&utm_content=sag_organic&utm_campaign=sag_organic",
+ "preserves_query_and_variant": true,
+ "old_handle": "elowen-teak-wallcovering",
+ "new_handle": "purisima-point-teak-wallcovering",
+ "link_variant_id": "44599723687987",
+ "shopify_status": "ACTIVE",
+ "title": "Elowen - Teak Wallcovering"
+ },
+ {
+ "offer_key": "shopify_US_7800261804083_44126792548403",
+ "field": "link",
+ "before": "https://www.designerwallcoverings.com/products/weft-aurora-wallcovering?variant=44599730110515&country=US¤cy=USD&utm_medium=product_sync&utm_source=google&utm_content=sag_organic&utm_campaign=sag_organic",
+ "after": "https://www.designerwallcoverings.com/products/crystal-cove-aurora-wallcovering?variant=44599730110515&country=US¤cy=USD&utm_medium=product_sync&utm_source=google&utm_content=sag_organic&utm_campaign=sag_organic",
+ "preserves_query_and_variant": true,
+ "old_handle": "weft-aurora-wallcovering",
+ "new_handle": "crystal-cove-aurora-wallcovering",
+ "link_variant_id": "44599730110515",
+ "shopify_status": "ACTIVE",
+ "title": "Weft - Aurora Wallcovering"
+ },
+ {
+ "offer_key": "shopify_US_7800258297907_44126786519091",
+ "field": "link",
+ "before": "https://www.designerwallcoverings.com/products/ascoli-opal-mylar-wallcovering?variant=44599727521843&country=US¤cy=USD&utm_medium=product_sync&utm_source=google&utm_content=sag_organic&utm_campaign=sag_organic",
+ "after": "https://www.designerwallcoverings.com/products/santa-catalina-opal-mylar-wallcovering?variant=44599727521843&country=US¤cy=USD&utm_medium=product_sync&utm_source=google&utm_content=sag_organic&utm_campaign=sag_organic",
+ "preserves_query_and_variant": true,
+ "old_handle": "ascoli-opal-mylar-wallcovering",
+ "new_handle": "santa-catalina-opal-mylar-wallcovering",
+ "link_variant_id": "44599727521843",
+ "shopify_status": "ACTIVE",
+ "title": "Ascoli - Opal Mylar Wallcovering"
+ },
+ {
+ "offer_key": "shopify_US_7800261673011_44126792351795",
+ "field": "link",
+ "before": "https://www.designerwallcoverings.com/products/weft-prairie-wallcovering?variant=44599729979443&country=US¤cy=USD&utm_medium=product_sync&utm_source=google&utm_content=sag_organic&utm_campaign=sag_organic",
+ "after": "https://www.designerwallcoverings.com/products/crystal-cove-prairie-wallcovering?variant=44599729979443&country=US¤cy=USD&utm_medium=product_sync&utm_source=google&utm_content=sag_organic&utm_campaign=sag_organic",
+ "preserves_query_and_variant": true,
+ "old_handle": "weft-prairie-wallcovering",
+ "new_handle": "crystal-cove-prairie-wallcovering",
+ "link_variant_id": "44599729979443",
+ "shopify_status": "ACTIVE",
+ "title": "Weft - Prairie Wallcovering"
+ },
+ {
+ "offer_key": "shopify_US_7800259149875_44126787960883",
+ "field": "link",
+ "before": "https://www.designerwallcoverings.com/products/orsay-paperback-wallcovering?variant=44599727947827&country=US¤cy=USD&utm_medium=product_sync&utm_source=google&utm_content=sag_organic&utm_campaign=sag_organic",
+ "after": "https://www.designerwallcoverings.com/products/fort-baker-paperback-wallcovering?variant=44599727947827&country=US¤cy=USD&utm_medium=product_sync&utm_source=google&utm_content=sag_organic&utm_campaign=sag_organic",
+ "preserves_query_and_variant": true,
+ "old_handle": "orsay-paperback-wallcovering",
+ "new_handle": "fort-baker-paperback-wallcovering",
+ "link_variant_id": "44599727947827",
+ "shopify_status": "ACTIVE",
+ "title": "Orsay - Paperback Wallcovering"
+ },
+ {
+ "offer_key": "shopify_US_7800257347635_44126784651315",
+ "field": "link",
+ "before": "https://www.designerwallcoverings.com/products/secret-garden-refresh-wallcovering?variant=44599726833715&country=US¤cy=USD&utm_medium=product_sync&utm_source=google&utm_content=sag_organic&utm_campaign=sag_organic",
+ "after": "https://www.designerwallcoverings.com/products/fort-funston-refresh-wallcovering?variant=44599726833715&country=US¤cy=USD&utm_medium=product_sync&utm_source=google&utm_content=sag_organic&utm_campaign=sag_organic",
+ "preserves_query_and_variant": true,
+ "old_handle": "secret-garden-refresh-wallcovering",
+ "new_handle": "fort-funston-refresh-wallcovering",
+ "link_variant_id": "44599726833715",
+ "shopify_status": "ACTIVE",
+ "title": "Secret Garden - Refresh Wallcovering"
+ }
+ ],
+ "description_replacements": []
+}
← 7f2c1f9 TK-11449: refute the Mayenne overcharge claim (verification
·
back to Gmc Titlefix
·
TK-11450: price writers stamped USD on CA-feed offers, disap 209bcae →