Skip to content

feat(rum): wait for the first remote settings on a page with nothing stored - #50

Merged
Fiona2016 merged 1 commit into
publishfrom
feat/remote-config-wait-first-visit
Oct 19, 2026
Merged

Fiona2016 merged 1 commit into
publishfrom
feat/remote-config-wait-first-visit

Conversation

@Fiona2016

Copy link
Copy Markdown
Collaborator

Motivation

With remote configuration enabled, a session is drawn on the settings stored by an earlier page, and the settings fetched at start-up only apply to the next session. A page with nothing stored — a first visit, a private window, a browser that clears storage — therefore always drew on the values passed to init. For visitors whose storage does not last until their next session that is every session, so the rates delivered from the console never applied to them.

Changes

  • Wait for the first settings when nothing is stored. After tracking consent is granted and before RUM starts, a page with no stored settings (and writable localStorage, and no event bridge) waits for the first settings answer, at most REMOTE_CONFIGURATION_WAIT (1 s). Any answer ends the wait, a failed one included; a late answer is still stored for the next draw. Pages with settings stored start exactly as before.
  • One fetcher, created before the start. startRemoteConfiguration(configuration, lifeCycle) becomes createRemoteConfiguration(configuration), which sends nothing on creation. preStartRum subscribes to its answers, then issues the first request; startRum connects it to the lifecycle (connectRemoteConfiguration). Still one request per page load.
  • Consent. Consent withdrawn before RUM starts cancels the wait and stops the fetcher, so no retry goes out; a later grant starts afresh. The pre-start consent subscription is now kept until right before RUM starts, which also covers a withdrawal while waiting for the first startView with trackViewsManually.
  • _dd.configuration.rc_wait. The wait (whole ms, at least 1) is kept with the draw it preceded (DrawnConfiguration.wait, persisted in the draw record even when the draw landed on the init values) and reported by every page of that session, next to rc_version.
  • Settings stored before the start. When the session manager starts and storage holds a settings version different from the one the current session was drawn under, it judges that session by them once (endSessionIfSettingsAreDecisive). A session the page only continued — from another subdomain, or drawn before the settings changed — is ended by an emergency stop or a stricter privacy level, as it would be if the settings had arrived a moment later.
  • Docs of remoteConfigurationEnabled and BeforeSamplingContext updated accordingly.

Trade-offs worth a look:

  • Up to 1 s of start delay for pages with nothing stored. Uncaught errors and console errors raised during the wait are not collected (as before init); API calls are buffered; performance entries are recovered through buffered observers; the initial view still starts at navigation start.
  • A page continuing a running session on an origin with nothing stored waits once as well (storage alone decides).
  • A session drawn on the init values after a timeout is judged once per later page while the stored version differs from its draw, which calls beforeSampling once more on those pages.

Test instructions

  • yarn test:unit — new and updated specs in preStartRum.spec.ts, startRum.spec.ts, remoteConfiguration.spec.ts, rumSessionManager.spec.ts, sessionContext.spec.ts.
  • Manually: enable remoteConfigurationEnabled, clear site data, load a page and check that beforeSampling receives the delivered rate on the first draw and that view events carry _dd.configuration.rc_wait; reload and check that no wait happens; delay the settings response past 1 s and check that the page starts on the init values with rc_wait ≈ 1000.

Checklist

  • Tested locally
  • Tested on staging
  • Added unit tests for this change.
  • Added e2e/integration tests for this change.

…stored

A page that has no remote settings stored drew its first session on the
values passed to init, and the settings it then fetched only applied to the
next session. For a visitor whose storage does not last until then (a one-off
visit, a private window, a browser that clears storage) that was every
session, so the console's rates never applied to them.

Such a page now waits for the first settings answer before it starts, once
tracking consent is granted, for at most REMOTE_CONFIGURATION_WAIT (1 s). Any
answer ends the wait, a failed one included; an answer arriving later is still
stored for the next draw. A page with settings stored never waits, and nothing
waits when localStorage cannot be written or under an event bridge.

- createRemoteConfiguration (was startRemoteConfiguration) creates the
  settings fetcher without sending anything; preStart subscribes to its
  answers, then issues the first request, and startRum connects it to the
  lifecycle with connectRemoteConfiguration. One request per page, as before.
- Consent withdrawn before RUM starts cancels the wait and stops the fetcher,
  so no retry goes out; a later grant starts afresh. The consent subscription
  is now dropped only right before RUM starts, so this also holds while the
  start waits for the first startView.
- The wait, in whole milliseconds and at least 1, is kept with the draw it
  preceded (DrawnConfiguration.wait, persisted in the draw record, also when
  the draw landed on the init values) and reported as _dd.configuration.rc_wait
  by every page of that session.
- When the session manager starts and storage holds a settings version other
  than the one the current session was drawn under, it judges that session by
  them once, as it would on hearing them: a session the page only continued
  (another subdomain, or drawn before the settings changed) is ended by an
  emergency stop or a stricter privacy level.
@Fiona2016
Fiona2016 merged commit 1d25d92 into publish Oct 19, 2026
5 checks passed
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.

1 participant