What's captured

Press d on any SERP page to toggle this debug overlay.

Episodes: 14
Retreats: 9
Classification:
clicked: 2
deferred: 4,7
evaluated_rejected: 1,3,5,8,10
not_approached: 6

Every finalized approach-retreat episode becomes a PostHog ar_episode event with the full 19-field flatten below, plus a 10% downsampled cursor trajectory (xytvxvy/1 format — flat integer array, time relative to entry).

Four-class taxonomy splits the non-click outcomes into deferred (retreated but re-approached), evaluated_rejected (retreated and never returned), and not_approached (visible but cursor never entered the AOI).

A session summary fires on visibilitychange/pagehide with per-position classification counts and time-to-first-click. Append ?ph=0 to any URL to disable capture entirely.

The full schema — 19 fields per episode

Everything we log on every result you hover. Nothing hidden, nothing invented.

Identity & outcome

positionrank in the SERP, from data-position
outcomefour-class: clicked | deferred | evaluated_rejected | not_approached
visitedalways true for emitted episodes
clickedwhether the visit ended in a click
retreatedwhether the cursor exited the AOI without clicking
visit_number1 = first visit, 2+ = re-approach

Timing

dwell_mstotal time the cursor was over the AOI
entered_atwhen cursor crossed into the AOI (performance.now)
exited_atwhen cursor left the AOI
clicked_atpopulated only when the visit ended in a click

Cursor dynamics

approach_velocitypx/ms at the moment of entry — fast = scanning, slow = evaluating
approach_angleatan2(vy, vx) at entry, radians
peak_velocitymax speed while over the result
min_velocitymin speed while over — near-pause = reading
retreat_distancepx from AOI center at max retreat (0 if clicked)
sample_countnumber of raw mousemove samples captured

Scroll context (forward/regressive)

directionforward = at/near scroll high-water mark; regressive = scrolled back up
entry_scrollwindow.scrollY at entry
hwm_at_entryrunning max of scrollY at entry

Session context (merged into every event)

ar_session_id (UUID), ar_layout, ar_query_id, ar_year_min/ar_year_max, viewport w/h/dpr, ar_ua, ar_referrer, ar_page_path, ar_loaded_at.

Optional raw trajectory — ar_trajectory

Flat integer array in xytvxvy/1 format: [x, y, t_rel_ms, vx, vy, x, y, ...]. 10% downsample (every 10th sample) from the native ~60Hz mousemove stream. A typical 5-second episode ships ~700 bytes of trajectory. Research-grade material, kept so cursor reanalysis stays possible.

Schema defined in src/approach-retreat.js Episode.toJSON() · adapter in src/adapters/posthog.js.

Choose a layout

Every variant uses the same library. Different geometries, same AOI contract.

Choose a question

Content swaps via ?q= on any layout page.

Every example

All 20 layout × question combinations. Linkable, bookmarkable, shareable.