Error handling
What happens when a send fails in the browser tracker, the React hooks and server-side revenue calls, and how to notice.
Browser tracker
The tracker never throws from pageview() or event(), so a network problem can't break your page.
| Situation | What happens |
|---|---|
Called before init() | Logs [Supapulse] Not initialized as a warning; nothing is sent. |
sendBeacon accepted the request | Counted as sent. The browser delivers it, even after the page closes. |
sendBeacon unavailable or refused | Falls back to fetch with keepalive. |
fetch fails, or returns a status other than the ones below | Retried after retryBackoff × 2^(attempt − 1) ms, capped at 30 s. |
400, 401, 402, 403, 404, 413 or 422 | Final. The server will never accept it, so the event is dropped without retrying. |
429 Too Many Requests | Retried after the Retry-After header (60 s if absent). |
maxRetries reached | Dropped. With debug: true, logs [Supapulse] Dropped after N attempts. |
| Page hidden or closed with retries pending | Each pending event is tried once more. |
The retry queue lives in memory and is lost when the page closes. There's no persistent offline queue.
init() throws Browser environment required if it runs without window, during server rendering for example. Guard it:
if (typeof window !== 'undefined') {
supapulse.init({ apiToken: 'pub_your_token' });
}React hooks
useSupapulse()throws if there's no<SupapulseProvider>above the component.- Before the provider has initialized, calls to the tracker are dropped with a
[Supapulse] Not initializedwarning, includinguseEvent()anduseIdentify(). Send events from handlers, or wait forisReadyin effects. - If
init()throws inside the provider, the error is logged as[Supapulse React] Initialization errorand stored in the context'serror.
Server-side revenue
Revenue is a plain HTTP call, so handle it like any other dependency:
- Non-2xx response: throw, and let your webhook return an error so the payment provider retries it.
401: the secret token is wrong or was regenerated. Alert on it; every payment until it's fixed is lost.402: the site's team has no active plan, or (for pageviews, events and identify) reached its monthly limit. Not retried by the SDKs. Revenue isn't blocked by the limit.422: the payload failed validation. The response names the field. Fix it; don't retry.429: wait forRetry-After.202: validated and queued. A repeatedtransaction_idwith the same event type is ignored.
Retrying is safe: Supapulse keeps the first event per transaction_id.
The @supapulse/revenue SDK retries network errors, 5xx and 429s up to maxRetries (3) times, then throws. Other 4xx responses throw at once.
Monitoring
- Keep
debug: falsein production; turn it on in a staging build to watch sends. - Log failed revenue calls with the transaction ID, so you can resend them by hand.
- Compare Supapulse's revenue total with your processor's dashboard now and then. A gap means webhooks are failing or events are being rejected.
The full list of API errors is in Error codes.