Skip to content

fix(browser): track page views on replaceState navigation - #2108

Merged
Mercy811 merged 8 commits into
mainfrom
codex/sdk-413-replacestate-page-views
Oct 30, 2026
Merged

Mercy811 merged 8 commits into
mainfrom
codex/sdk-413-replacestate-page-views

Conversation

@Mercy811

@Mercy811 Mercy811 commented Oct 29, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Fixes SDK-413: React SPA navigation through history.replaceState (including React Router's navigate(path, { replace: true })) currently misses [Amplitude] Page Viewed. Successful URL changes now use the existing trackHistoryChanges and trackOn rules. State-only hydration and unchanged-URL replacements stay silent.

History wrappers forward the original arguments, receiver, return value, and exceptions. The existing synchronous URL baseline, instance tracking guard, teardown policy, and pending page-view completion behavior are preserved. Regression tests exercise native history calls, filtering, suppression, redirects/Back, failures, wrapper composition, shared page-view IDs, multiple projects, and teardown.

Under all (also the default), query cleanup and hash changes made with replaceState count as URL changes; pathOnly continues to ignore them. Applications that replace URLs can therefore see more page views after adopting the fix. Public usage/reference documentation is tracked separately in SDK-447 for the release.

The PR also includes a minimal nuqs SPA under test-server/nuqs-spa (pnpm dev:nuqs). It reads the API key only from VITE_AMPLITUDE_API_KEY in the repository .env, uses the US server zone with SDK debug logging, and lets visitors select all (default) or pathOnly before initialization. The SPA controls table has one row per button, including its handler and History API operation, with expected additional page views in the all (default) and pathOnly columns. The page keeps only initialization, a nuqs history selector, and the button/code/expectation table; inspect events in the console, Network panel, or Amplitude project. There are no custom event observers or history instrumentation. Neither .env nor its values are committed.

Validation

Node.js 24.10.0 / pnpm 11.28.5:

  • pnpm install — passed.

  • pnpm build --concurrency 1 — passed for all 30 projects; default parallel build attempts stalled locally in Rollup.

  • pnpm docs:check — passed.

  • pnpm lint and pnpm lint:deps — passed.

  • Page-view package build/typecheck and all 48 tests — passed with 100% coverage. The new 15-case regression suite fails against the original implementation (12 failures) and passes with this fix.

  • pnpm test -- --runInBand --watchman=false --forceExit — passed for all 31 projects on the final full run (prior successful targets reused Nx cache). Watchman is disabled because of local startup permissions; forceExit avoids existing open Jest handles. An earlier full run failed the page-counter test that schedules navigation exactly at its 500 ms session timeout; that test passed isolated reruns with both the fix and the original tracker.

  • pnpm test:examples — blocked by the existing missing jest.setup.examples.js referenced by the root script. No example configuration changes are included.

  • Latest pnpm test --concurrency 1 -- --runInBand --watchman=false --forceExit — passed for all 31 projects (56 of 60 tasks reused Nx cache); serial execution avoids the local parallel Rollup stalls.

  • nuqs app production build, formatting/dependency checks, and browser verification of initialization and both tracking modes — passed. Browser initialization also verified with the repository .env API key.

Checklist

  • Does your PR title have the correct title format?
  • Does your PR have a breaking change?: No

Note

Medium Risk
Changes global History API monkey-patching and page-view volume for replace-based SPA navigation; well covered by new tests but affects production autocapture behavior.

Overview
Fixes missing [Amplitude] Page Viewed events when SPAs navigate via history.replaceState (e.g. React Router navigate(..., { replace: true }) or nuqs query updates).

The page-view plugin now proxies both pushState and replaceState. For replaceState, it only runs the existing history handler when location.href actually changes, so router hydration and state-only replacements stay silent. pushState still always goes through the handler; trackHistoryChanges, trackOn, deduplication, and teardown behavior are unchanged—apps on all may see more page views for query/hash replaceState updates.

Adds a history.test.ts regression suite and a test-server/nuqs-spa manual harness (pnpm dev:nuqs, root nuqs devDependency) wired out of the shared Vite test-server build.

Reviewed by Cursor Bugbot for commit 58e108b. Configure here.

@linear-code

linear-code Bot commented Oct 29, 2026

Copy link
Copy Markdown
Contributor

SDK-413

@github-actions

github-actions Bot commented Oct 29, 2026 •

Copy link
Copy Markdown

size-limit report 📦

Path Size
packages/analytics-browser/lib/scripts/amplitude-min.js.gz 68.31 KB (0%)
packages/session-replay-browser/lib/scripts/session-replay-browser-min.js.gz 138.22 KB (0%)
packages/unified/lib/scripts/amplitude-min.umd.js.gz 224.27 KB (0%)
@amplitude/element-selector (gzipped esm) 3.48 KB (0%)
@amplitude/analytics-browser/core (gzipped esm) 21.74 KB (0%)

@Mercy811

Copy link
Copy Markdown
Contributor Author

bugbot run

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 58e108b. Configure here.

@Mercy811
Mercy811 marked this pull request as ready for review October 29, 2026 22:11
@Mercy811
Mercy811 requested review from a team as code owners October 29, 2026 22:11
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 29, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ⚠️ Failed 2026-10-29T22:12:37.856183Z
We couldn’t complete this review. Comment @codex review to try again.
58e108b Draft marked ready
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@Mercy811
Mercy811 merged commit 16be3af into main Oct 30, 2026
20 checks passed
@Mercy811
Mercy811 deleted the codex/sdk-413-replacestate-page-views branch October 30, 2026 22:35
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.

2 participants