diff --git a/vtex/utils/extensions/simulation.ts b/vtex/utils/extensions/simulation.ts index f4887b4e0..96d5a188b 100644 --- a/vtex/utils/extensions/simulation.ts +++ b/vtex/utils/extensions/simulation.ts @@ -30,10 +30,17 @@ const doSimulate = (items: { }, } = getSegmentFromBag(ctx); + // When removeUTMFromCacheKey is on the store has declared UTM does not + // affect content/price, so the page is cached with UTM stripped from the + // cache key. Feeding UTM into the simulation here would let a UTM-triggered + // promotion change the price and get cached generically, so skip it to keep + // the simulation consistent with the caching contract. + const utmInKey = !ctx.advancedConfigs?.removeUTMFromCacheKey; + const md = new Map(); - utm_campaign && md.set("utmCampaign", utm_campaign); - utm_source && md.set("utmSource", utm_source); - utmi_campaign && md.set("utmiCampaign", utmi_campaign); + utmInKey && utm_campaign && md.set("utmCampaign", utm_campaign); + utmInKey && utm_source && md.set("utmSource", utm_source); + utmInKey && utmi_campaign && md.set("utmiCampaign", utmi_campaign); campaigns && md.set("campaigns", [{ id: campaigns }]); const marketingData = md.size > 0 ? Object.fromEntries(md.entries()) diff --git a/vtex/utils/segment.ts b/vtex/utils/segment.ts index 4afa1ca7a..6e3a9e633 100644 --- a/vtex/utils/segment.ts +++ b/vtex/utils/segment.ts @@ -260,9 +260,19 @@ export const setSegmentBag = ( }); } - // Only set vtex_segment when the channel is non-default so that default-SC - // responses remain cacheable by the CDN without a Set-Cookie header. - if (vtex_segment !== token && !isAnonymous(ctx)) { + // The vtex_segment cookie disqualifies CDN caching (Cloudflare skips + // Set-Cookie responses). Gate its emission on whether the response is + // cacheable. UTM can drive VTEX promotions and change price, so treating + // UTM-only requests as cacheable is only safe when the store opts in via + // removeUTMFromCacheKey (the same flag the loaders use to strip UTM from + // their cache key). With the flag on we use isCacheableSegment (ignores + // UTM); otherwise we keep isAnonymous, which keeps UTM-carrying requests + // non-cacheable and cookie-bearing. + const nonCacheable = ctx.advancedConfigs?.removeUTMFromCacheKey + ? !isCacheableSegment(ctx) + : !isAnonymous(ctx); + + if (vtex_segment !== token && nonCacheable) { setCookie(ctx.response.headers, { value: token, name: SEGMENT_COOKIE_NAME,