Skip to content

CATALYST-1532: Fix analytics visit count inflation#2916

Merged
chanceaclark merged 1 commit intocanaryfrom
CATALYST-1532/fix/analytics-visit-count-inflation
Mar 10, 2026
Merged

CATALYST-1532: Fix analytics visit count inflation#2916
chanceaclark merged 1 commit intocanaryfrom
CATALYST-1532/fix/analytics-visit-count-inflation

Conversation

@chanceaclark
Copy link
Copy Markdown
Contributor

@chanceaclark chanceaclark commented Mar 9, 2026

Jira: CATALYST-1532

What/Why?

Enterprise merchant (Marucci Sports) reported significantly inflated visitor counts after migrating from Stencil to Catalyst. Three root causes:

  1. No sliding window on visit cookie — the 30-minute visitId cookie TTL was set once and never refreshed, so sessions >30 minutes silently created new visits.
  2. Prefetch/RSC requests create visits — Next.js client-side navigation fires RSC and Next-Router-Prefetch requests through middleware. With an expired cookie, each triggered a separate VisitStarted mutation.
  3. Locale redirects bypass analyticswithIntl ran before withAnalyticsCookies and returned early on redirects, so the visit cookie was never refreshed on those requests.

Notable edge case: when a prefetch/RSC request arrives with an expired cookie, we intentionally skip setting a new visitId cookie so the subsequent real navigation properly detects a new visit and fires the event. The same prefetch guard is applied to recordProductVisit in with-routes.ts.

Fixes CATALYST-1532

Rollout/Rollback

Standard code rollout. No feature flags, database migrations, or experiments. Rollback is a simple revert.

Testing

  1. Sliding window: Browse the storefront for >30 minutes. Confirm in dev tools that catalyst.visitId cookie expiry resets on each navigation.
  2. Prefetch guard: In the network tab, observe RSC/prefetch requests (RSC: 1 or Next-Router-Prefetch: 1 headers). Confirm these do not trigger VisitStarted mutations in GraphQL client logs.
  3. Middleware reorder: Navigate to a URL that triggers a locale redirect. Confirm Set-Cookie for catalyst.visitId is present on the redirect response.
  4. Regression check: cd core && npx playwright test

@vercel
Copy link
Copy Markdown

vercel Bot commented Mar 9, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
catalyst Ready Ready Preview, Comment Mar 10, 2026 4:26pm

Request Review

@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Mar 9, 2026

🦋 Changeset detected

Latest commit: 1c91011

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@bigcommerce/catalyst-core Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@chanceaclark chanceaclark marked this pull request as ready for review March 9, 2026 22:44
@chanceaclark chanceaclark requested a review from a team as a code owner March 9, 2026 22:44
@chanceaclark chanceaclark force-pushed the CATALYST-1532/fix/analytics-visit-count-inflation branch from 510c0b4 to a7cdc53 Compare March 9, 2026 23:18
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Mar 9, 2026

Bundle Size Report

Comparing against baseline from 5dcf35b (2026-03-10).

No bundle size changes detected.

Copy link
Copy Markdown
Contributor

@jorgemoya jorgemoya left a comment

Choose a reason for hiding this comment

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

I was seeing this with the unstable_cache refactor, nice fix

Resolve inflated visitor counts caused by three issues:

- Visit cookie used a fixed TTL instead of a sliding window, creating
  new visits for users browsing longer than 30 minutes. Now refreshes
  the cookie TTL on every request.
- Prefetch and RSC requests triggered new visit and product view events.
  Now guards against Next-Router-Prefetch and RSC headers so only real
  navigations fire analytics mutations.
- Locale redirects from withIntl bypassed analytics entirely. Reorder
  middleware so withAnalyticsCookies runs before withIntl, ensuring
  cookies survive redirect responses.

Fixes CATALYST-1532
Co-Authored-By: Claude <noreply@anthropic.com>
@chanceaclark chanceaclark force-pushed the CATALYST-1532/fix/analytics-visit-count-inflation branch from a7cdc53 to 1c91011 Compare March 10, 2026 16:25
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Just added a changeset and rebased the PR.

@chanceaclark chanceaclark enabled auto-merge March 10, 2026 16:26
@chanceaclark chanceaclark added this pull request to the merge queue Mar 10, 2026
Merged via the queue into canary with commit e3185b6 Mar 10, 2026
14 of 17 checks passed
@chanceaclark chanceaclark deleted the CATALYST-1532/fix/analytics-visit-count-inflation branch March 10, 2026 16:29
chanceaclark added a commit that referenced this pull request Apr 27, 2026
Resolve inflated visitor counts caused by three issues:

- Visit cookie used a fixed TTL instead of a sliding window, creating
  new visits for users browsing longer than 30 minutes. Now refreshes
  the cookie TTL on every request.
- Prefetch and RSC requests triggered new visit and product view events.
  Now guards against Next-Router-Prefetch and RSC headers so only real
  navigations fire analytics mutations.
- Locale redirects from withIntl bypassed analytics entirely. Reorder
  middleware so withAnalyticsCookies runs before withIntl, ensuring
  cookies survive redirect responses.

Fixes CATALYST-1532

Co-authored-by: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants