Skip to content

[OpenSpec] portal-traffic-experiments #450

Description

@github-actions

⚠️ OpenSpec-managed issue — this content is automatically synced
from the openspec/ directory. Manual edits will be overwritten on next sync.

Artifacts

Summary

Phase 4b, the last, of portal traffic analytics (phase 0:
portal-traffic-analytics, phase 1: portal-traffic-visitors-and-geo,
phase 3: portal-traffic-outcomes, phase 4a: portal-traffic-reporting).
The earlier phases count, judge and report; this one lets a portal try
something and see whether it worked, and gives an operator who accepts
the warning two behavioural instruments that the earlier phases only
named.

  1. Page experiments. A portal declares A/B experiments in
    traffic.experiments: a page, two or more variants (another page
    shown in its place without a reload, or the same page with some text
    changed), a goal and a status. The client puts a visitor on a variant,
    sticky for the visit, and tags every event of that session with the
    experiment and the variant. The aggregation counts sessions and
    conversions per variant and names a winner only with thirty sessions
    per variant and a two-proportion z-test at 95 percent. An Experiments
    widget shows the variants, the rates and the verdict, and says "not
    enough data" until there is.
  2. Heatmaps, off by default. With sensitive.heatmaps on, the client
    sends where a click landed (fractions of the document, a viewport
    bucket, the element's tag and a short selector without ids) and how
    far a page was scrolled; nothing else. The rollup carries a fifty by
    fifty click grid and scroll deciles per page; a Heatmap widget draws
    them on a plain rectangle, not a screenshot. With the switch off the
    events are refused as sensitive-off.
  3. Session recording, off by default. With sensitive.sessionRecording
    on, the client lazily loads a separate recorder that streams the
    page's layout as a tree in which every text node is only its length
    and every input only the length of its value, plus the pointer, the
    clicks, the scrolling and the navigations. The collector masks every
    chunk again on arrival, bounds a chunk at 256 KB and a visit at 2 MB,
    stores the visit as a portalTrafficRecording object with the raw
    events' retention, never records an external portal and never before
    consent where consent is required. A Recordings widget lists the
    visits and a player replays them in a sandboxed frame.

Specs

Tasks

  • 1.1 TrafficExperimentDefinitions: traffic.experiments[] normalised (id, page, two or more variants each with a page route or text changes, goal, status, started and stopped moments); drafts dropped from the resolved block; unit tests.
  • 1.2 TrafficExperiments: sessions and conversions per variant from the first tagged event, a stopped experiment counting nothing after its stop, the two-proportion z-test, a winner only with thirty sessions per variant and 95 percent; unit tests on a known table.
  • 1.3 Validator: experiment and variant params survive only when they name a running experiment and one of its variants.
  • 1.4 Client: the running experiment on the current route, a weighted sticky pick (client id or per-load seed), a soft redirect to a variant page through replaceState and popstate, text changes applied and re-applied on render, the tag on every event; node tests for the split and the stickiness.
  • 1.5 Rollup experiments[], roll-up sum merging by id with the verdict re-derived; the summary folds the range and re-derives the verdict in the browser; widget TrafficExperiments with "Not enough data".
  • 2.1 Resolver: heat_click and heat_scroll exist only under sensitive.heatmaps; validator refuses them as sensitive-off otherwise and keeps positions only (x, y, vw, tag, selector, depth), the selector stripped of ids and attributes.
  • 2.2 Client: a click as fractions of the document with a viewport bucket, a tag and a safe selector; the deepest scroll per page view, sent when the page view ends.
  • 2.3 TrafficHeatmapStats: the fifty by fifty click grid and the scroll deciles per page; rollup heatmaps[] only while the switch is on; unit tests.
  • 2.4 Widget TrafficHeatmap: a page picker, the grid on a canvas over a plain rectangle, the deciles as bars, "off for this portal".
  • 3.1 src/traffic/recorder.js as a second webpack entry served from /api/traffic-recorder.js, loaded by the client only when mayRecord (switch on, not an external portal, consent where required): masked snapshots, pointer, clicks, scrolls, viewport, navigations, posted in chunks, stopping at 2 MB.
  • 3.2 TrafficRecordingMask: every chunk reduced on arrival to lengths, allowed attributes and numbers; TrafficRecordingService with the four gates and the two budgets; TrafficRecordingStore; POST /api/traffic/recording; unit tests.
  • 3.3 Schema portalTrafficRecording (admin-readable, expires), purged by the aggregation run.
  • 3.4 Widget TrafficRecordings and the player modal TrafficRecordingPlayer (srcdoc, sandbox without scripts); the overview warning says how many recordings exist and how long they are kept.
  • 4.1 Schemas: portal.traffic.experiments, the sensitive descriptions rewritten now the switches do something, portalTrafficEvent enum, portalTrafficDaily.experiments and heatmaps, portalTrafficRecording; versions bumped (register 0.21.0, portal 0.6.0, daily 0.5.0, event 0.4.0); every new string catalogued.
  • 4.2 A custom form field for the sensitive block checked and found not feasible on nc-vue 2.37 (no consumer of appliesTo); recorded in the proposal and the docs.
  • 4.3 docs/operations/traffic-analytics.md: experiments, heatmaps, session recording (what is masked, why an external portal never records, the budgets, the retention).
  • 4.4 Seed: an external portal open-extern with recording on, so "never on an external portal" is proven against a real record; traffic-outcomes.spec.ts no longer asserts a missing path inside a top-ten list.
  • 4.5 E2E tests/e2e/traffic-experiments.spec.ts on the throwaway instance, one test per scenario.

Synced from openspec/changes/portal-traffic-experiments by OpenSpec workflow
App: portaliq

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions