supapulsedocs
Core packageBasic usage

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 on DOMContentLoaded, if the document is still loading);
  • after every history.pushState and history.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

FieldSource
url, pathlocation.href, or the url you pass
referrerdocument.referrer, or the referrer you pass
titledocument.title, or the title you pass
localenavigator.language
utm_source, utm_medium, utm_campaign, utm_term, utm_contentQuery parameters of the URL
session_idThe 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 signup

To 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.