collect()
The primary entry point. Attaches all collectors to a container element, wires up automatic flush triggers, and returns a handle for manual control.
function collect(
selectorOrEl: string | HTMLElement,
options: CollectOptions
): CollectHandleParameters
selectorOrEl
A CSS selector string passed to document.querySelector, or a direct HTMLElement reference. Can be any element: a <form>, a <div>, a <section>, or document.body. Throws if the selector matches nothing.
Collectors that scope to this element (keystroke, paste, corrections, field timing, reaction time) will listen within it. Collectors for mouse, scroll, click, session rhythm, and visibility always operate at the document or window level regardless of what element you pass.
options
interface CollectOptions {
endpoint: string // URL where the payload is sent via sendBeacon
sessionId: string // unique identifier for this session
}Use crypto.randomUUID() to generate a session ID. It is included in the payload and ties it to the session in the Zoven scoring API.
Return value
interface CollectHandle {
flush: () => void // build payload, sendBeacon to endpoint, then detach. Idempotent.
stop: () => void // detach all listeners without sending. Idempotent.
}Automatic flush behavior
collect registers two flush triggers automatically:
- A
submitlistener on the nearest<form>ancestor of the target element, if one exists. - A
visibilitychangelistener that flushes whendocument.visibilityState === 'hidden'.
Both use { once: true }. If you call flush() or stop() manually before either trigger fires, the automatic triggers become no-ops.
If your surface has no <form> element, the tab-close trigger still fires. Call flush() manually at your chosen score point (button click, step completion, route change) to ensure the payload is sent at the right moment.
BehaviorScanner
Lower-level class for advanced use cases: building payloads on demand, wiring up custom flush logic, or integrating into a framework component lifecycle.
class BehaviorScanner {
attach(el: HTMLElement): this
buildPayload(sessionId: string): BehaviorPayload
detach(): void
}attach(el)
Attaches 13 stateful collectors to the target element and document (12 behavioral and 1 network reaction collector). Also starts async prewarming for the audio fingerprint and incognito detection, so those results are ready by the time buildPayload() is called.
Returns this for chaining. Signals only accumulate while attached, so call this as early as possible in the session.
const scanner = new BehaviorScanner()
// Works with any element:
scanner.attach(document.querySelector('#wizard-step-1')!)
scanner.attach(document.querySelector('#login-container')!)
scanner.attach(document.body)buildPayload(sessionId)
Collects all signals, runs all detection rules, derives a client-side verdict, and returns a complete BehaviorPayload. Safe to call repeatedly. Collectors stay attached between calls, so you can poll for a live payload during the session.
const payload = scanner.buildPayload(sessionId)
// payload.signals, payload.detections, payload.verdict are all populatedThrows if called before attach().
detach()
Removes all event listeners and resets the scanner's internal state. After calling detach(), calling buildPayload() will throw.
Safe to call multiple times. The second and subsequent calls are no-ops.
Types
All types are available as named imports from @devanshhq/nyasa.
import type {
BehaviorPayload,
CollectedSignals,
BehavioralSignals,
FingerprintSignals,
NetworkSignals,
InputTypeSignals,
UploadSignals,
DetectionResult,
Detections,
CollectOptions,
CollectHandle,
} from '@devanshhq/nyasa'Full type definitions for every signal shape are in the Signals reference. The full payload shape is in Payload.