User Guide
Custom Events
Track button clicks, form submissions, purchases — any action that matters to your business.
1. How events work
Every time the tracker fires an event it sends a small JSON payload to the Web Analyzer App ingestion API. Events are tied to the current session and visitor so you can see them in context on the Sessions and Visitors pages. They also appear aggregated on the Events dashboard page.
An event has:
- name — a short string you choose (e.g.
signup,purchase,video_play) - payload (optional) — a flat key/value object with extra data
2. Tracker JavaScript API
After the tracker script loads, a global Tracker object is available in window.Tracker. It exposes two methods:
| Method | Description |
|---|---|
| Tracker.track(name, payload?) | Fire a custom event. name is required (string). payload is an optional plain object. |
| Tracker.page(path?) | Manually send a page-view hit. Pass an optional path string; defaults to window.location.pathname. Useful in SPAs after a route change. |
Signature
Tracker.track(name: string, payload?: Record<string, any>): void
Tracker.page(path?: string): void
async. If you call Tracker.track() inline in a <script> tag before the tracker has loaded, it will silently fail. Use addEventListener('load', ...) or move your calls to DOM-ready handlers.
3. Common examples
Button click
document.getElementById('signup-btn').addEventListener('click', function () {
Tracker.track('signup_click');
});
Form submission
document.getElementById('contact-form').addEventListener('submit', function () {
Tracker.track('form_submit', { form: 'contact' });
});
Purchase / checkout
// After a successful order
Tracker.track('purchase', {
order_id: '1234',
value: '49.99',
currency: 'USD',
plan: 'pro',
});
Video play
document.querySelector('video').addEventListener('play', function () {
Tracker.track('video_play', { title: this.dataset.title });
});
Outbound link
document.querySelectorAll('a[target="_blank"]').forEach(function (link) {
link.addEventListener('click', function () {
Tracker.track('outbound_link', { url: this.href });
});
});
4. Custom payload
The payload argument accepts any flat (non-nested) key/value object. Values can be strings, numbers, or booleans.
- Maximum 10 keys per event
- Key length: max 64 characters
- Value length: max 255 characters
- Nested objects are flattened or ignored
// Good
Tracker.track('upgrade', { plan: 'pro', value: '29', currency: 'USD' });
// Avoid nested objects — they will be stringified
Tracker.track('upgrade', { meta: { plan: 'pro' } }); // ✗
5. Single-page apps (SPA)
In a SPA (React, Vue, Svelte, etc.) the browser never does a full page reload, so the tracker's automatic page-view detection does not fire on route changes. Call Tracker.page() after each navigation:
React Router (v6)
import { useLocation } from 'react-router-dom';
import { useEffect } from 'react';
function Analytics() {
const location = useLocation();
useEffect(() => {
window.Tracker?.page(location.pathname);
}, [location]);
return null;
}
// Add <Analytics /> inside your <Router>
Vue Router
router.afterEach((to) => {
window.Tracker?.page(to.path);
});
Plain History API
const _pushState = history.pushState.bind(history);
history.pushState = function (...args) {
_pushState(...args);
window.Tracker?.page(location.pathname);
};
6. Server-side events (API)
You can also send events from your backend — for example after a successful payment webhook — using the tracker ingestion API directly.
POST /api/t/event
curl -X POST https://yourdomain.com/api/t/event \
-H "Content-Type: application/json" \
-d '{
"tracking_key": "YOUR_TRACKING_KEY",
"visitor_id": "VISITOR_UUID",
"session_id": 123,
"name": "purchase",
"payload": {
"order_id": "1234",
"value": "49.99"
}
}'
The visitor_id is the UUID stored in the visitor's localStorage under the key ot_vid. Pass it to your server on form submit or during checkout to correlate server-side events to the correct visitor record.
The session_id is the numeric session ID stored in sessionStorage under the key ot_sid. Both IDs are set by the tracker after the first page view.
7. Limits & quotas
Events count towards your monthly quota alongside page views.
| Plan | Monthly quota | At 80% | At 100% |
|---|---|---|---|
| Free | 50,000 | Warning in sidebar | Events rejected (402) |
| Pro | 1,000,000 | Warning in sidebar | Events rejected (402) |
Quotas reset on the 1st of each calendar month (UTC). Upgrade on the Billing page to increase your limits.