Sessions and Delivery

Episode 5: one pageview, one session, exactly two records, three queues, three triggers, and beacons that outlive the page

Guide~3 min read

Copy this guide and your current settings as a prompt for your AI agent.

Preview agent promptSee the guide, code and settings included when you copy.

Episode 4 ended with a visitor inside an experiment. Now the question that decides whether your numbers can be trusted: what exactly gets written down? The answer is an invariant: one pageview, one session, exactly two records, an exposure and a page-view. Everything else in measurement hangs off that pair.

Watch: 3m 25s — Runtime Walkthrough, episode 5: session identity, the pair, engagement, viewed variants, the three queues, flush triggers, sendBeacon, and the join
On this page
  1. 01Session identity
  2. 02The pair
  3. 03Engagement
  4. 04Viewed variants
  5. 05The three queues
  6. 06Flush triggers
  7. 07sendBeacon, no fallback
  8. 08The join
  9. 09Where in the code

01Session identity

A session is minted per pageview, with one subtlety: the first variant application reuses the session id created at boot, so anything logged before init, like a hydration warning, shares the id of the session it belongs to. Every navigation after that mints a fresh UUID. Session equals pageview, by construction.

02The pair

On every apply, startSession writes two records:

Record Carries Queue Table
Session The full assignment output from episode 1, the SDK version, the browser context exposure impressions (the denominator)
page_view event Type, session id, URL, token behavior events

One pageview, one impression, one page-view. Never more.

03Engagement

Then the SDK waits to see if the visit is real. session_start fires on the first click anywhere, or after ten seconds counted visibility-aware (ENGAGED_SESSION_THRESHOLD): a background tab’s clock re-checks when the tab is shown. Whichever comes first, and exactly once: the engaged flag is set before the event is queued, so nothing can double-fire it.

04Viewed variants

Every applied node carries coframe-exp-id. On scroll, and when rendering completes, the SDK checks visibility. The first time an element is on screen it is stamped coframe-experienced and one modification_view event is queued: once per variant, per page.

05The three queues

Queue Holds Endpoint Table
behavior Clicks, page-views, session-starts batched_events/<projectId>/ events
health The monitoring stream batched_monitoring/<projectId>/ monitoring_sdk
exposure Sessions session_result/ impressions

06Flush triggers

  • Size: any queue reaching 32 (batchSize).
  • Time: an immediate flush at apply, then every three seconds (FLUSH_EVENTS_TIME).
  • Lifecycle: beforeunload, pagehide, visibilitychange, three overlapping signals because mobile browsers fire them inconsistently.

Every trigger funnels through flushQueuedEvents, behind the consent gate from episode 2.

07sendBeacon, no fallback

Delivery is navigator.sendBeacon and nothing else. A beacon is handed to the browser itself and survives navigation: a conversion click that immediately leaves the page still arrives. There is deliberately no fetch fallback. The source comment explains why: a fetch dies with the page, so clicks would vanish while impressions survive, skewing every rate downward. If the beacon fails, usually an ad-blocker, the SDK only warns.

08The join

impressions is the denominator: who was exposed, to which variant. events is the numerator: what they did. The stats engine joins them per session and divides. Because every pageview writes exactly one exposure, the denominator cannot inflate, and a rate you cannot inflate is a rate you can trust.

09Where in the code

File What to look for
sdk/sdk-js/src/init/modifyPage.ts createApplyVariants (session id reuse at boot, fresh id per navigation), FLUSH_EVENTS_TIME, setupFlushInterval
sdk/sdk-js/src/init/setupTracking.ts startSession, ENGAGED_SESSION_THRESHOLD, updateViewedVariants, lifecycle flushes
sdk/sdk-js/src/api.ts The three queues, batchSize, flushQueuedEvents, the endpoints, sendBeacon and the no-fallback comment

Related reading

Content and video lessons from Coframe documentation. Code examples are not executed on this page.

BACK TOHow Coframe Works

Documentation

Open Coframe App

Search documentation

Search all guides and references↑ ↓ Navigate · Esc Close