New — hover-time tooltips & auto-highlighting markers in WaveformPlayer 1.16. What's new →

WaveformTracker

Headless audio analytics.

A ~2KB add-on that measures real listened media-time, ignores seeks, sets no cookies, and POSTs compact JSON events when listeners cross your thresholds.

$ npm i @arraypress/waveform-tracker
GitHub

Play below to see it in action.

Live demo

Watch real media-time accumulate.

Play, pause, seek — every event is captured live. The tracker ignores seeks and only credits genuine playback. Watch the payload update in real time as you listen.

Threshold lowered to 5s for the demo. In production you'd POST these to an endpoint instead of a handler.

Captured events
  1. Press play — captured events appear here.

What it measures

Built on four core principles.

Every metric is honest: real media-time consumed, no wall-clock padding, and no inflated numbers from seeks or pauses.

Media-time, not wall-clock

Engagement accumulates from real listened seconds. 1.5x/2x playback is fully credited; paused and idle time is not.

Seeks ignored

Forward jumps of 5s or more are treated as seeks and dropped — scrubbing never inflates your numbers.

Privacy-first

No cookies, no localStorage, no PII. The optional session id is a random in-memory string, regenerated every reload.

Survives unload

Terminal events use sendBeacon (with fetch + keepalive fallback) so they land even as the page navigates away.

Auto-discovers players

Call init() once and it immediately tracks every player on the page, plus any created later (lazy-mounted, SPA routes).

Compact JSON events

POSTs {event, url, time, duration, page, ...metadata, session?, title?} to your endpoint or hands it to a handler.

Event payload

Compact JSON, straight to your endpoint.

When a listener crosses a threshold, the tracker POSTs this payload to your endpoint (or hands it to a handler). Field order is deterministic; custom metadata can be spread in.

payload.json
{
  "event": "listen",
  "url": "audio/ep-42.mp3",
  "time": 30,
  "duration": 180,
  "page": "/podcast/ep-42",
  "post_id": 456,
  "session": "k3f9q2abc1",
  "title": "Episode 42"
}

Configuration

One call to init().

Set your endpoint (or handler), define thresholds, add custom metadata, and optionally enable session tracking. Every option is optional — the defaults fire a listen event at 30 seconds.

tracker.js
import WaveformTracker from '@arraypress/waveform-tracker';

WaveformTracker.init({
  endpoint: '/api/track',           // or handler instead
  events: {
    play: 3,                         // 3s of media-time
    listen: 30,                      // 30s of media-time
    complete: 90                     // 90% of duration
  },
  metadata: { post_id: 456 },       // spread into every payload
  session: true,                     // random per-reload id
  headers: { 'Authorization': '…' }, // custom headers for fetch
  debug: false                       // verbose logging
});

Privacy first

No cookies, no localStorage, no PII.

The tracker collects only media-time metrics. The optional session id is a fresh random string per page load, held in memory only — it correlates events within one session, nothing more. You control what identifying data (if any) gets attached via metadata.

Getting started

Three steps to live tracking.

Load the player, load the tracker, and call init() once. The tracker auto-discovers every player on the page — no per-element wiring needed.

index.html
<!-- 1. Load the player first, then the tracker -->
<script src="https://unpkg.com/@arraypress/waveform-player"></script>
<script src="https://unpkg.com/@arraypress/waveform-tracker"></script>

<!-- 2. Any player on the page is tracked automatically -->
<div data-waveform-player
     data-url="/audio/ep-42.mp3"
     data-title="Episode 42"></div>

<!-- 3. Initialize once -->
<script>
  WaveformTracker.init({
    endpoint: '/api/track',
    events: { listen: 30, complete: 90 },
    metadata: { user_id: 42 }
  });
</script>

Start shipping beautiful audio.

Free, open-source and ~10KB — add a div and go.

Read the docs

API reference, guides and recipes for all nine packages.

Browse docs

Open the builder

Configure a player visually and copy the HTML, JS or React.

Try it

Star on GitHub

MIT-licensed, open source, zero dependencies.

View source