@observejs/plugin-auto-track
v0.1.0
Published
Automatic tracking plugin for Observe.js — pageviews, clicks, forms, scroll, clipboard, visibility, session, network, and window events.
Maintainers
Readme
@observejs/plugin-auto-track
Automatic tracking plugin for Observe.js.
Capture user interactions without writing a single Observe.track() call.
Built on the @observejs/browser plugin system — pluggable, isolated, and
zero impact on the host app if it crashes.
Install
npm install @observejs/browser @observejs/plugin-auto-trackUsage
import { Observe } from "@observejs/browser";
import { autoTrackPlugin } from "@observejs/plugin-auto-track";
Observe.init({
apiKey: "obs_pk_live_xxx",
plugins: [autoTrackPlugin()],
});That's it. The plugin attaches listeners and ships events through the SDK queue — same batching, retries, and offline behavior as any other event.
What gets captured
| Category | Event names |
| ----------- | ------------------------------------------------------------------------ |
| Page | $page (initial, pushstate, replacestate, popstate, hashchange) |
| Click | $click, $dblclick, $contextmenu |
| Form | $form_submit, $form_reset, $input_focus, $input_blur, $input, $input_change, $checkbox_change, $radio_change, $select_change, $textarea_change |
| Scroll | $scroll_depth (25 / 50 / 75 / 100 thresholds, one-shot per route) |
| Mouse | $mouse_enter, $mouse_leave (only on [data-track-hover] / [data-track]) |
| Clipboard | $clipboard_copy, $clipboard_cut, $clipboard_paste (action only — never contents) |
| Visibility | $tab_hidden, $tab_visible, $beforeunload, $pagehide |
| Session | $session_started, $session_ended, $session_timeout, $session_resumed |
| Online | $online, $offline, $connection_restored |
| Window | $viewport_resize, $orientation_change |
Every event carries the full SDK schema (eventId, sessionId, visitorId,
deviceId, url, path, referrer, device, metadata, …) on top of the
category-specific properties shown above.
Configuration
autoTrackPlugin({
// Toggle individual categories — all on by default.
categories: {
page: true,
click: true,
form: true,
scroll: true,
mouse: true,
clipboard: true,
visibility: true,
session: true,
online: true,
window: true,
},
// CSS selectors whose interactions should never produce events.
ignoreSelectors: ["[data-no-track]", ".sensitive", "#admin-panel"],
// Field name / id / aria-label substrings to mask (case-insensitive).
// Sensible defaults already cover password, cc, cvv, ssn, otp, token, etc.
maskFields: ["accountNumber", "routingNumber"],
// URL patterns to ignore (combined with the SDK-level ignoreUrls).
ignoreUrls: ["/admin/", /\/internal\//],
// Cap text captured from buttons/links/inputs.
maxTextLength: 120,
// Debounce for `$input` events.
inputDebounce: 400,
});Opting elements out
Any element with these attributes is ignored entirely:
<form data-obs-ignore>...</form>
<button data-observe-ignore>Don't track me</button>
<input class="obs-ignore" />Opting elements in (hover tracking)
Mouse enter/leave events fire only for elements that opt in (to avoid flooding the queue):
<div data-track-hover>Pricing tier — hover counts</div>
<a data-track href="/upgrade">Upgrade</a>Privacy
The plugin never captures:
<input type="password">values<input type="hidden">values- Fields with
autocomplete="cc-*",current-password,new-password,one-time-code - Fields whose
name,id,aria-label,placeholder, ordata-fieldcontains:password,secret,token,apikey,auth,ssn,credit,card,cvv,cvc,pin,otp,mfa,verification, … (full list inDEFAULT_MASK_FIELDS) - Clipboard contents (only the action: copy / cut / paste)
- Mouse coordinates or movement paths
- Cookies or auth tokens
Add your own substrings with maskFields. All input text is also truncated
to 120 chars before being sent.
Performance
- All listeners use capture phase +
passive: truewhere possible. $scroll_depthis throttled to 200ms and emits at most 4 events per route.$inputis debounced (default 400ms).$viewport_resizeis debounced to 250ms.- Hover tracking is opt-in (
[data-track-hover]) to avoid DOM-wide noise. - Continuous mouse movement is deliberately not captured here — the replay plugin (later phase) handles that.
- Total listener footprint: ~15 listeners regardless of DOM size.
Lifecycle
The plugin returns a teardown function. Observe.shutdown() will:
- Remove every DOM listener
- Restore the original
history.pushState/history.replaceState - Cancel any pending debounced/throttled callbacks
- Clear the session-timeout timer
No memory leaks, even across hot reloads.
Debug
Enable debug: true on the SDK and the plugin logs initialization, each
tracker's setup, and every captured event:
Observe.init({
apiKey: "obs_pk_live_xxx",
debug: true,
plugins: [autoTrackPlugin()],
});Production mode (default) is silent.
License
MIT
