supapulsedocs
Core packageAPI reference

API reference

Every method and type @supapulse/core exports, with signatures and behavior.

import { Supapulse } from '@supapulse/core';

The package exports the Supapulse class and its types. The script tag build exposes one instance as window.supapulse.

new Supapulse()

const supapulse = new Supapulse();

Creates a tracker and its session ID. Nothing is sent until init().

init()

init(config: SupapulseConfig): void

Starts the tracker. Sets up automatic pageviews (unless autoPageviews: false) and the handlers that flush pending sends when the page is hidden or closed.

  • Throws Browser environment required if window is undefined.
  • A second call on the same instance is ignored.

See Configuration for the options.

pageview()

pageview(options?: PageviewOptions): Promise<void>

Sends a pageview. Defaults to location.href, document.referrer and document.title. The promise resolves once the request is handed off, not when the server has stored it.

event()

event(eventName: string, eventData?: EventData): Promise<void>

Sends a custom event with optional properties. Does nothing if eventName is empty.

getSessionId()

getSessionId(): string

Returns the session ID: a random UUID created with the tracker. Pass it to your server at checkout to link a payment to this visit. See Sessions.

identify()

identify(customerId: string): Promise<void>

Links the current visitor to your own customer ID, so revenue sent later for that ID is credited to the visitor's first touch. Call it after login or signup. It sends { customer_id, session_id, url } as an identify event with the public token. Supapulse builds the visitor fingerprint on the server from the request. Does nothing if customerId is empty or the tracker isn't initialized. Identify events never count toward your usage.

supapulse.identify(user.id);

See Revenue attribution.

getVisitorFingerprint()

getVisitorFingerprint(): Promise<string | null>

Resolves to the visitor's fingerprint, the same server-built hash stored on their pageviews. The first call requests it from POST /api/fingerprint with the public token. The result is cached on the instance, and concurrent calls share one request. Pass it through checkout metadata for the strongest revenue link.

Resolves to null and sends nothing if the tracker isn't initialized. It also resolves to null when the request fails. A network error or a 5xx isn't cached, so the next call tries again. A 401, 402, 403 or 404 is final: the null is cached and the instance doesn't ask again.

const fingerprint = await supapulse.getVisitorFingerprint(); // string | null

The endpoint comes from fingerprintEndpoint, which defaults to endpoint with /ingest replaced by /fingerprint. For a custom endpoint that doesn't end in /ingest, it uses /api/fingerprint on the endpoint's origin.

Retries and final status codes

Sends use sendBeacon first and fall back to fetch. On a failed fetch:

ResponseWhat the tracker does
2xxDone.
429Waits for Retry-After (60 seconds if missing), then retries.
400, 401, 402, 403, 404, 413, 422Final. The event is dropped without retrying.
Anything else, or a network errorRetries with exponential backoff, up to maxRetries, then drops it.

A 402 means the site's team has no active plan or reached its monthly event limit. See Error codes.

use()

use(extension: SupapulseExtension): void

Registers an extension and calls its init(core) with the tracker. Registering the same name twice is ignored.

supapulse.use({
  name: 'scroll-depth',
  init(core) {
    let sent = false;
    addEventListener('scroll', () => {
      const depth = (scrollY + innerHeight) / document.body.scrollHeight;
      if (!sent && depth > 0.9) {
        sent = true;
        core.event('scrolled_to_bottom');
      }
    });
  },
});

Types

interface SupapulseConfig {
  apiToken: string;
  endpoint?: string;
  fingerprintEndpoint?: string;
  autoPageviews?: boolean;
  debug?: boolean;
  maxRetries?: number;
  retryBackoff?: number;
}

interface PageviewOptions {
  url?: string;
  referrer?: string;
  title?: string;
}

interface EventData {
  [key: string]: any;
}

interface SupapulseExtension {
  name: string;
  init(core: SupapulseCore): void;
}

interface SupapulseCore {
  init(config: SupapulseConfig): void;
  pageview(options?: PageviewOptions): void;
  event(eventName: string, eventData?: EventData): void;
  identify(customerId: string): Promise<void>;
  getVisitorFingerprint(): Promise<string | null>;
  getSessionId(): string;
  use(extension: SupapulseExtension): void;
}

TrackingData and QueuedEvent describe the request payload and the retry queue. They're exported for completeness; you don't need them to use the tracker. The full list is in TypeScript types.

Not in the API

Older docs mentioned reset(), isInitialized(), isIdentified() and a supapulse.q command queue. None of them exist.

Browser support

The tracker needs fetch, Blob, URL and history.pushState, which every current browser has. It uses crypto.randomUUID() when available and falls back to Math.random() for session IDs.