ScaleBun
Skip to article

Behaviour signals

webDeveloper

Exit intent, attention bands, scroll depth, rage clicks and dead clicks — the derived signals autocapture produces without any instrumentation.

Updated Reviewed

Beyond clicks and pageviews, autocapture derives a handful of signals about how a page was used. All of them ride on autocapture, need no instrumentation, and capture positions and durations — never page content.

Exit intent#

$exit_intent fires when a visitor looks like they are leaving — either the pointer leaves through the top edge of the page, or the page is scrolled upward hard and fast after real engagement.

The event carries velocity_px_ms, distance_px and exit_y, which exist so you can tune the thresholds from your own distribution rather than trusting a default that was a guess:

TypeScript
await ScaleBun.init({  clientKey,  apiBaseUrl,  exitIntent: {    windowMs: 120,          // how far back upward velocity is measured    minDistancePx: 80,      // minimum upward travel — filters micro-corrections    minVelocityPxMs: 0.7,   // ≈700 px/s — a flick, not a drift    minDepthPct: 25,        // engagement floor: how far they got first    sustainSamples: 3,      // consecutive qualifying samples (hysteresis)    topEdgePx: 40,          // pointer-exit band at the top of the page  },});

topEdgePx belongs to the pointer trigger, not scroll reversal. mouseout reports the last sampled pointer position, and a fast flick toward the tab bar covers tens of pixels between samples — so a narrow band misses exactly the deliberate gestures it exists to catch. Raise it if pointer exits look under-reported.

Attention#

The document is split into ten vertical bands, and a coarse timer credits each band by how much of it is on screen. Only time that is both active and visible counts: a backgrounded tab accrues nothing, and so does a page left open while someone is away (15 s without interaction stops the clock).

The summary rides along on $pageleave as attention_bands, attention_active_ms and attention_bands_n.

This is what separates "they reached the pricing table" from "they read it" — scroll depth answers the first, attention answers the second.

Scroll depth#

Depth is computed at emit time, from the deepest pixel offset reached and the document height tracked by a ResizeObserver. That matters on any page that grows: infinite scroll, late-loaded content, virtualized lists. A naive percentage captured on each scroll is frozen against the height at that instant and reports the wrong number.

$pageleave carries scroll_depth_pct, max_scroll_px, doc_h, viewport_h, max_bucket (0/25/50/75/100) and scrollable.

Rage and dead clicks#

$rageclick fires on rapid repeated clicks in the same small area — the signature of something that looks interactive and is not responding. $deadclick fires on a click that produced no DOM change, no navigation and no network request.

Both are strong triage signals precisely because they need no instrumentation: they surface the broken thing you did not know to measure.

Opting out#

Any subtree can be excluded from autocapture entirely:

HTML
<div data-scalebun-no-capture>  <!-- nothing in here is autocaptured --></div>

To keep capture but hide the text on interaction events, set privacy.maskEventText. See Privacy & consent.

Next#

Behaviour signals · Web SDK · ScaleBun