Performance
What the Supapulse tracker costs your page, how it loads and sends, and how to keep it off the critical path.
The numbers
| Build | Minified | Gzipped |
|---|---|---|
Script tag (dist/browser.js) | about 6 KB | about 2.3 KB |
@supapulse/core from npm | about 6 KB | about 2.2 KB |
@supapulse/react on top of core | about 1 KB | about 0.6 KB |
Neither package has runtime dependencies. Measure your own bundle to confirm; these come from the 1.0 builds.
What the tracker does at runtime
- One request per pageview or event. Sent with
navigator.sendBeacon, which doesn't block the page or delay unload. Events aren't batched. - No work on the main thread beyond building a small JSON payload. No polling, timers or DOM observers. The only timers are retries after a failed send.
- History patching.
pushStateandreplaceStateare wrapped to schedule a pageview on the next tick. - Nothing persisted. No storage reads or writes.
Loading the script tag
Use defer:
<script
defer
src="https://cdn.jsdelivr.net/npm/@supapulse/core@1/dist/browser.js"
data-token="YOUR_PUBLIC_TOKEN"
></script>defer downloads in parallel and runs after the HTML is parsed, so it doesn't block rendering. async works too, but runs at an unpredictable point, which makes window.supapulse harder to rely on from your own scripts.
To shave the connection setup, add a preconnect for the CDN and the API:
<link rel="preconnect" href="https://cdn.jsdelivr.net" />
<link rel="preconnect" href="https://supapulse.app" />Loading from npm
@supapulse/core is small enough to bundle with your app. If you'd rather keep it out of the initial chunk, import it after the page is interactive:
window.addEventListener('load', async () => {
const { Supapulse } = await import('@supapulse/core');
const supapulse = new Supapulse();
supapulse.init({ apiToken: 'pub_your_token' });
});Late initialization still records the first pageview, because init() sends one. Events sent before then are lost, so don't do this if you track events during load.
Content Security Policy
script-src 'self' https://cdn.jsdelivr.net;
connect-src 'self' https://supapulse.app;script-src is only needed for the script tag.
Server-side revenue
A revenue call is one HTTPS request from your webhook handler. The API queues it and answers without waiting for it to be stored. Await it before returning, so a failure can be retried.
Measuring
- Lighthouse or WebPageTest: compare runs with and without the script.
- Network tab: filter by
ingestto see each send and its size; filter bybrowser.jsfor the script. - Bundle analyzers (
webpack-bundle-analyzer,@next/bundle-analyzer,rollup-plugin-visualizer): check that only@supapulse/coreand@supapulse/reactshow up.