SDK reference
Every method, option and automatic event in the LaunchPulse JavaScript SDK.
The JavaScript SDK is @basekick-labs/launchpulse — currently v0.1.2, MIT licensed, zero dependencies, about 1.9 kB gzipped. This page is the complete API surface. If you only want to get tracking, start with Installation instead.
Loading the SDK
The package ships an ESM build at dist/lp.mjs and an IIFE build at dist/lp.js. The IIFE build is also served directly by the collector, and both are on unpkg and jsDelivr.
<script src="https://collector.launchpulse.dev/lp.js"></script>
<script>LaunchPulse.init("lp_pub_yourkey");</script>
npm i @basekick-labs/launchpulse
import { LaunchPulse } from "@basekick-labs/launchpulse";
The script tag sets window.LaunchPulse. After init() runs, the instance is also available as window.lp.
Methods
| Call | Behavior |
|---|---|
LaunchPulse.init(publicKey, options?) | Establishes identity, fires an initial $pageview, hooks SPA navigation, registers flush handlers. Returns the instance and sets window.lp |
lp.track(name, properties?) | Sends a custom event. Names starting with $ are rejected with a console warning |
lp.identify(userId) | Sets the user id (persisted in the cookie) and emits a $identify event |
lp.reset() | Clears the user id and rotates both the visitor id and the session id |
lp.track_pageview() | Sends a $pageview manually |
init(publicKey, options?)
Call it once per page load. It returns the instance, so you can hold onto it instead of reaching for window.lp:
const lp = LaunchPulse.init("lp_pub_yourkey");
lp.track("signup_started");
Your public key is lp_pub_ followed by 22 base58 characters. It is designed to ship in client code — putting it in your HTML or bundle is safe and expected. The separate secret key is for server-side events and must never appear in the browser.
Options:
| Option | Type | Meaning |
|---|---|---|
collector | string | Base URL of the collector. Events POST to ${collector}/e. Only set this when self-hosting |
cookieDomain | string | For example .yourapp.com, to share identity across subdomains. Normally supplied by the collector automatically. Unset means a host-only cookie |
debug | boolean | Tags events as debug. Debug events are never counted |
The default collector is https://collector.launchpulse.dev, so you can leave collector out unless you run your own.
On cookieDomain: the SDK ships no public-suffix list, which means it can never mis-scope your cookie to something like .co.uk. The value it uses comes from the collector, or from what you pass explicitly.
track(name, properties?)
lp.track("plan_upgraded", { plan: "pro", seats: 3 });
Event names starting with $ are reserved. If you pass one, the SDK rejects the call and warns in the console. See Tracking events for naming advice.
Properties are enforced by the collector, and violating any single limit rejects the whole event:
| Limit | Value |
|---|---|
| Max properties per event | 64 |
| Max key length | 64 characters |
| Key charset | letters, digits, _, ., - |
| Max string value length | 1024 characters |
| Max nesting depth | 3 |
| Max array/object entries | 32 |
| Max serialized JSON | 8192 bytes |
Two property keys are exceptions to the $ rule: $revenue and $currency. See Revenue tracking. Any other $-prefixed property key rejects the event.
identify(userId)
lp.identify("user_8f21c");
Sets the user id, persists it in the cookie, and emits a $identify event. The SDK warns in the console if the value looks like an email address — use an internal user id, never PII. Full detail in Identifying users.
reset()
lp.reset();
Clears the user id and rotates both the visitor id and the session id. Call it on logout, and on shared devices.
track_pageview()
lp.track_pageview();
Sends a $pageview manually. You rarely need this — init() fires one, and SPA navigation is handled for you.
Automatic events
Two events are sent for you, and they are the only reserved names the collector accepts:
$pageview fires on init() and on SPA navigation. The SDK hooks history.pushState and history.replaceState, plus popstate. Pageviews are deduplicated by path plus search string. That dedupe matters: SPAs — Next.js especially — call replaceState constantly for same-page state, and firing on every call would inflate your pageview count badly.
$identify is emitted by identify().
Any other $-prefixed event name is rejected by the collector.
Transport
Useful when you’re debugging in the network tab.
Events are queued and sent with navigator.sendBeacon, using a text/plain Blob. If the beacon fails, or the payload exceeds 60,000 bytes, the SDK falls back to fetch(..., { keepalive: true }).
The text/plain content type is deliberate. It’s CORS-safelisted, so the request counts as “simple” and needs no preflight. application/json would force a preflight that sendBeacon cannot satisfy cross-origin, and your events would silently vanish.
The queue flushes on any of:
- a 1-second timer
- 10 queued events
pagehidevisibilitychangeto hidden
The browser batch endpoint is POST ${collector}/e with a body of { "k": "lp_pub_...", "events": [ ... ] }.
What gets sent with every event
Identity and attribution ride along automatically, from the _lp_vid cookie. Visitor id, session id, user id if set, first-touch attribution, session attribution, and UTM parameters. See Identifying users for the exact fields and lifetimes, and Sources for how attribution is classified.
Your client IP is used only to derive a country, then discarded. It is never stored.
Debugging
Set debug: true to tag events as debug. They show up while you’re testing but are never counted:
LaunchPulse.init("lp_pub_yourkey", { debug: true });
To confirm real data is arriving, use the events log. Note that the ingest API returns a uniform 2xx even for unknown or revoked keys, so a 200 in the network tab does not prove your key is valid. Only seeing the event in the log does.
If nothing shows up, Troubleshooting walks through the usual causes.