← back to Designerwallcoverings
scripts/_lib/dw-publications.js
67 lines
/**
* dw-publications.js — canonical DW Shopify sales-channel (Publication) list.
*
* SOURCE-FIX for the GMC $4.25 sample-leak (Steve policy, 2026-07-08):
* Shopify's "Google & YouTube" channel auto-syncs each published product's
* minVariantPrice to Merchant Center. On DW that min is almost always the
* $4.25 "-Sample" variant → Google advertises $4.25 on a real-roll product →
* price_mismatch DISAPPROVAL. Every onboard/go-live script publishes new SKUs
* to ALL 13 publications, INCLUDING Google (29646651457), so every new import
* re-leaks $4.25 onto the channel. That is the re-leak vector.
*
* THE FIX: new SKUs must NOT land on the Google & YouTube channel. Google is fed
* exclusively by the CONTROLLED TSV feed (build-google-feed.js → Merchant
* Center primary datasource), which drops the sample variant and emits the real
* (highest) price. So channel membership on Google is intentionally empty.
*
* DEFAULT export ALL_CHANNELS_NO_GOOGLE excludes 29646651457. Onboard scripts
* should publish to this list. Opt back into Google only if you have a reason
* AND the product is genuinely sample-only (its price IS $4.25) — see
* channelsFor() below.
*
* Reversible: to restore the old behavior, import ALL_CHANNELS_WITH_GOOGLE
* instead, or pass {includeGoogle:true} to channelsFor().
*/
const GOOGLE_PUBLICATION_ID = 29646651457; // "Google & YouTube" — fed by the controlled TSV, NOT channel auto-sync.
// All 13 DW sales channels (numeric publication ids).
const ALL_PUBLICATION_IDS = [
22208643184, 22497296496, 29646651457, 29739483201, 29776969793, 37904089153,
43657658419, 44234276915, 44317474867, 44317507635, 71898464307, 115856375859, 140027723827,
];
const gid = n => `gid://shopify/Publication/${n}`;
// DEFAULT for new imports: every channel EXCEPT Google & YouTube.
const ALL_CHANNELS_NO_GOOGLE = ALL_PUBLICATION_IDS
.filter(n => n !== GOOGLE_PUBLICATION_ID)
.map(gid);
// Legacy full list (INCLUDES Google) — kept for explicit opt-in / rollback only.
const ALL_CHANNELS_WITH_GOOGLE = ALL_PUBLICATION_IDS.map(gid);
/**
* channelsFor(product) → the publications a product should be published to.
* - Real-roll products (a variant priced > $4.25 exists): NEVER Google
* (the TSV feed carries it at the real price).
* - Sample-only products (only variant is the $4.25 sample): Google is safe,
* because $4.25 IS the true product price (Steve's exception). But even here
* the TSV feed already covers it, so the safe default is still no-Google.
*
* Pass { includeGoogle:true } to force Google membership (rarely needed).
*/
function channelsFor(opts = {}) {
if (opts.includeGoogle) return ALL_CHANNELS_WITH_GOOGLE;
return ALL_CHANNELS_NO_GOOGLE;
}
module.exports = {
GOOGLE_PUBLICATION_ID,
GOOGLE_PUBLICATION_GID: gid(GOOGLE_PUBLICATION_ID),
ALL_PUBLICATION_IDS,
ALL_CHANNELS_NO_GOOGLE,
ALL_CHANNELS_WITH_GOOGLE,
channelsFor,
};