Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 10 additions & 3 deletions vtex/utils/extensions/simulation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Enabling removeUTMFromCacheKey now drops UTM from every simulation request, so UTM-dependent pricing is ignored even for non-cacheable requests that still call this extension. Preserving UTM for non-cacheable segments and stripping it only for cacheable responses would avoid regressing the existing simulation behavior for no-store responses.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At vtex/utils/extensions/simulation.ts, line 38:

<comment>Enabling `removeUTMFromCacheKey` now drops UTM from every simulation request, so UTM-dependent pricing is ignored even for non-cacheable requests that still call this extension. Preserving UTM for non-cacheable segments and stripping it only for cacheable responses would avoid regressing the existing simulation behavior for no-store responses.</comment>

<file context>
@@ -30,10 +30,17 @@ const doSimulate = (items: {
+  // 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<string, unknown>();
</file context>


const md = new Map<string, unknown>();
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())
Expand Down
16 changes: 13 additions & 3 deletions vtex/utils/segment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
Loading