Basic usage
Track pageviews and custom events with @supapulse/core, name events well, and keep personal data out of them.
These examples use an initialized tracker called supapulse. With the script tag, it's window.supapulse.
Pageviews
Automatic
With the default autoPageviews: true, the tracker sends a pageview:
- when
init()runs (or onDOMContentLoaded, if the document is still loading); - after every
history.pushStateandhistory.replaceState; - on
popstate(back and forward).
That covers server-rendered sites and most single-page app routers. See SPA support for the details.
Manual
Set autoPageviews: false and call pageview() yourself:
supapulse.init({ apiToken: 'pub_your_token', autoPageviews: false });
supapulse.pageview();pageview() reads location.href, document.referrer and document.title. Override any of them:
supapulse.pageview({
url: 'https://acme.com/checkout/step-2',
title: 'Checkout: shipping',
referrer: 'https://acme.com/checkout/step-1',
});Overriding url is how you record a virtual pageview, like a step in a modal flow. Pass a full URL: the server reads the path and UTM parameters from it.
What a pageview records
| Field | Source |
|---|---|
url, path | location.href, or the url you pass |
referrer | document.referrer, or the referrer you pass |
title | document.title, or the title you pass |
locale | navigator.language |
utm_source, utm_medium, utm_campaign, utm_term, utm_content | Query parameters of the URL |
session_id | The tracker's session ID |
The server adds the visitor hash, country, browser, OS and device type.
Events
supapulse.event('signup', { plan: 'growth', billing: 'yearly' });- The name is required. Calls without one are ignored. The server stores up to 255 characters.
- Properties are optional. Send a flat object of strings, numbers and booleans; it's stored as JSON.
- The event also records the current URL and path, and the session ID.
Common patterns
Outbound clicks, file downloads and form submissions can be tracked without code: see Automatic events. For anything else, send your own:
// A step in a funnel
supapulse.event('checkout_step', { step: 2, name: 'shipping' });
// A button
document.querySelector('#hero-cta')?.addEventListener('click', () => {
supapulse.event('cta_click', { id: 'hero' });
});Naming
Pick one style and keep it. Snake case object-then-action names (signup_started, signup_completed, plan_upgraded) group well in reports. Put variable parts in properties, not in the name: button_click with { id: 'hero_cta' }, not hero_cta_click.
Keep personal data out
Don't send email addresses, names, phone numbers or account IDs in event properties or URLs. Supapulse stores what you send as-is. If a URL can carry personal data in its query string, pass a cleaned url to pageview() with autoPageviews: false.
Revenue
Revenue doesn't go through the browser tracker. Identify the customer here and send revenue from Stripe or your server:
supapulse.identify(user.id); // after login or signupTo link a payment to this visit directly, read the fingerprint and session ID when checkout starts:
const fingerprint = await supapulse.getVisitorFingerprint();
const sessionId = supapulse.getSessionId();See Revenue tracking.
Testing
Turn on debug: true to log every send. In the Network tab, filter by ingest: each call is a POST with a JSON body like:
{
"type": "event",
"data": {
"visitor_fingerprint": null,
"session_id": "6f1c…",
"event_name": "signup",
"event_data": { "plan": "growth" },
"url": "https://acme.com/pricing",
"path": "/pricing"
},
"token": "pub_…"
}visitor_fingerprint is null in pageview and event payloads; the server fills it in.