API Reference

Full reference for the collect() function, BehaviorScanner class, and exported types.

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
): CollectHandle

Parameters

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:

  1. A submit listener on the nearest <form> ancestor of the target element, if one exists.
  2. A visibilitychange listener that flushes when document.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 populated

Throws 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.