#4546·umami

Allow the session replay recorder to customize/normalize the recorded URL (or run in manual mode)

Author: lucasjoaoCreated Sep 17, 2026Updated Sep 17, 2026

Problem

The tracker (script.js) lets an app control the URL it reports: with data-auto-track="false" (or data-auto-pageview="false") plus umami.track(props => ({ ...props, url })), a single-page app can send a normalized route instead of the raw location.href.

The recorder (recorder.js) has no equivalent. Inspecting the current bundle, it only reads two attributes:

  • data-website-id
  • data-host-url

Why it matters

For SPAs with dynamic route parameters (e.g. /foo/HM547WwgG), the app already normalizes pageview URLs to /foo/:id, but the recorder bypasses that layer and stores the raw path. Two consequences:

  1. Heatmaps fragment. Each distinct parameter becomes its own "page" in the Pages list, so clicks never aggregate into a meaningful heatmap.
  2. Sensitive identifiers get recorded. In privacy-sensitive apps, the raw path itself is sensitive data, and there is currently no way to keep it out of replay/heatmap storage even though the rest of the analytics pipeline already strips it.

maskLevel: strict does not help here — it masks text and inputs, not the URL.

Proposed options (any one would solve it)

  1. A data-before-send-style hook on the recorder that receives the URL (and optionally the event) and can transform or drop it, mirroring the tracker.
  2. Have the recorder reuse the tracker's already-normalized URL / session context instead of reading location.href independently.
  3. A data-* attribute to point the recorder at a user-provided URL transform function on window.

Option 2 would be the most consistent, since it would make replay/heatmap URLs match what the tracker already reports.

Environment

  • Umami self-hosted v3.3.0
  • SPA (Angular) with manual pageview tracking (data-auto-track="false")