JavaScript API
Once s.js is on the page, the SDK exposes one global: window.statable.t(). Use it to fire custom events from anywhere, click handlers, framework lifecycle hooks, fire-and-forget instrumentation deep in your code.
This page covers manual events. For HTML attributes see Tracking script reference. For payload shape see Event payload reference.
The legacy global
window.__usdTrackEventstill exists internally but is not part of the public API. Always usewindow.statable.t().
Signature
| Parameter | Type | Required | Description |
|---|---|---|---|
name | string | yes | Human-readable event name. Title Case recommended. |
props | object | no | Custom properties merged into the event payload as p.* |
Returns undefined. Fire-and-forget. No callback, no promise.
Basic usage
Event without props
Event with custom props
Property values can be strings, numbers, or booleans. Nested objects are accepted but flat types index better in the dashboard.
Framework examples
React
import { useEffect } from 'react';
function PricingPage() {
useEffect(() => {
window.statable.t('Pricing Viewed');
}, []);
const handleUpgrade = (plan) => {
window.statable.t('Upgrade Clicked', { plan });
};
return <button onClick={() => handleUpgrade('pro')}>Upgrade</button>;
}
Vue
<script>
export default {
mounted() {
window.statable.t('Modal Opened', { modal: 'newsletter' });
},
methods: {
submit() {
window.statable.t('Newsletter Subscribed');
}
}
}
</script>
Plain DOM
<button id="cta">Start trial</button>
<script>
document.getElementById('cta').addEventListener('click', () => {
window.statable.t('Trial Started', { source: 'hero' });
});
</script>
Safe-call pattern (script not yet loaded)
If your code might run before s.js finishes loading (inline scripts in <head>, or a deferred bundle that hasn't parsed yet), guard against the global being undefined. The simplest pattern is an existence check on the call site:
The optional chaining drops the call when the SDK isn't ready yet, so you don't crash with a reference error. The SDK does not currently auto-replay a queue, so if you depend on the early event being recorded, fire it after DOMContentLoaded.
Auto-tracked events
Some events fire automatically. They appear in your dashboard alongside custom events.
| Trigger | Event name (filterable) |
|---|---|
| Page load + SPA navigation | pageview |
| Tab unload / hidden / 30-min timeout | engagement (system) |
Click on <a> to a different host | Outbound Link Click |
Click on <a> with download extension or download attr | File Download |
Submit on <form data-statable-event="..."> | Your event name |
engagement is a system event that powers session duration and scroll-depth metrics. Not meant to be filtered in the UI like a custom event. Treat it as infrastructure.
File Download matches: pdf, zip, rar, gz, tar, 7z, doc(x), xls(x), ppt(x), csv, exe, dmg, iso, mp3, mp4, avi, mov. Links with a download attribute also count regardless of extension.
Naming conventions
- Use Title Case:
Sign Up,Pricing Viewed,Plan Changed. - Keep names short and human-readable. They appear in dashboards and reports.
- Use property names, not event names, for variable data:
'Plan Changed', { from: 'free', to: 'pro' }instead of'Plan Changed Free To Pro'. - Stay consistent across your codebase. Mismatched casing creates duplicate rows.
Reserved names
The SDK internally wraps custom event names in square brackets ([Event Name]) to distinguish them from system events on the backend. Do not pass names that already contain brackets. The names pageview and engagement are reserved and bypass the bracket wrapping.
Opt-out
Set a flag in localStorage to exclude a visitor from tracking:
The SDK checks this on every send and silently drops events when set. To re-enable:
Scope: per-browser, per-domain (standard localStorage rules). Useful for excluding your own team, contractors, or honoring user-level Do-Not-Track preferences.
Bot detection
Two client-side checks skip tracking entirely:
navigator.webdriver === true. Set by Selenium, Cypress, Playwright, Puppeteer (when not stealth-patched).window.Cypress. Additional Cypress-specific guard.
Server-side filtering (multiple UA parsers, IP heuristics) runs on top. See Event payload reference.
Status code for error pages
For 404, 410, or other non-200 pages, hint the status to the SDK with a meta tag in <head>:
Read on every pageview and added to the payload as sc. The dashboard uses it to separate broken-page traffic from healthy traffic and power the Error pages report.
See also
- Tracking script reference: install attributes.
- Event payload reference: wire format.
Ready to take control of your web analytics? Try Statable free for 30 days — no credit card required, full feature access, GDPR-compliant by default. Start your free trial or view a live demo.