Configuration
Configuration
Section titled “Configuration”All options are passed to init(config). Every key is optional, but you must supply either endpoint or handler — with neither, init() emits a console.warn and no events are delivered.
| Option | Type | Default | Description |
|---|---|---|---|
endpoint |
string | null |
null |
URL that events are POSTed to as JSON. Required unless handler is set. |
handler |
function | null |
null |
Custom delivery callback handler(payload). When set it fully replaces network delivery — endpoint is never called. Thrown errors are caught and logged, not propagated. |
events |
object |
{ listen: 30 } |
Which events fire and their thresholds. Keys: play, listen (seconds of media-time), complete (percent 0–100). Any subset; omit a key (or pass null / false) to disable that event. 0 is a real threshold (1.1.0+). |
headers |
object<string,string> |
{} |
Extra headers merged into the fetch POST (e.g. Authorization). Any custom header rules out sendBeacon (beacon can’t set headers), so terminal events always go by fetch + keepalive. For a cross-origin endpoint, list each header in the preflight’s Access-Control-Allow-Headers — see Delivery semantics. |
metadata |
object |
{} |
Key/value pairs spread into every payload (e.g. user_id, post_id). |
session |
boolean |
true |
When true, a random anonymous session id is generated on init() and added to every payload as session (a later init() keeps it, 1.1.0+). Pass false to omit it entirely. |
debug |
boolean |
false |
When true, emits verbose console.log('[WaveformTracker]', …) tracing (ready/destroy, play/pause, sent payloads, beacon fallbacks). Does not suppress sending. |
The events thresholds
Section titled “The events thresholds”WaveformTracker.init({ endpoint: '/api/track', events: { play: 3, // fire 'play' once 3s of media-time accumulates listen: 30, // fire 'listen' once 30s of media-time accumulates complete: 90 // fire 'complete' once playback reaches 90% of duration }});playandlistenare seconds of accumulated media-time.completeis a percent (0–100) of duration. It fires when(currentTime / duration) * 100crosses the threshold during playback, or on the player’sendedevent — only for a finite duration above0, so never for a live stream.completealso needs real listening (1.1.0+): at least half the audio up to the threshold must have been heard, in media-time (COMPLETE_ENGAGEMENT = 0.5). Withcomplete: 90on a 4-minute track that’s 108s, so scrubbing to 95% — or to the end — no longer counts as a completion. Expect fewercompleteevents than 1.0.x reported.- A threshold of
0fires on the first check after playback starts (1.1.0+; it used to disable the event). Omit the key, or passnull/false, to turn an event off. - Each event fires at most once per track, tracked per player. The set re-arms on
ended, so a replay can fire them all again, and when the player switches to a different URL (loadTrack()orload()), so the new track gets its own events (1.0.2+). - The default config — when you pass no
events— fires onlylistenat 30 seconds.
Metadata, session, and field precedence
Section titled “Metadata, session, and field precedence”metadata is spread into the payload before the fixed session and title keys. That ordering matters:
metadatacan override the five core fields —event,url,time,duration,page.metadatacannot overridesessionortitle(they’re added afterward).
WaveformTracker.init({ endpoint: '/api/track', metadata: { user_id: 42, post_id: 456 }, session: true // default; set false to drop the session id});The session id is anonymous and in-memory only — a fresh random string (Math.random().toString(36).slice(2) + Date.now().toString(36)) generated by the first init() (and again after reset()) and regenerated on every reload. It correlates events within a single page session; it is not a persistent identifier.