← 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,
};