Browser SDK
@pivolio/browser is the engine every other binding wraps. It has zero runtime
dependencies and ships ESM, CommonJS, an IIFE bundle, and types.
Install
npm
Script tag
Initialize
init() returns the Tracker it built. Calling it twice warns and returns the
existing instance rather than creating a second one — so an accidental double
init won’t double-count your traffic. Every option is documented in
Configuration.
Methods
The module exports a singleton API. Every method below is also a method on the
Tracker class, which you can construct directly with new Tracker(config) if
you need more than one instance.
Two methods exist only on the Tracker class and have no singleton equivalent:
getConsent() returns the current Consent Mode state, and isInitialized()
reports whether the tracker actually started (it returns false when
respectDNT disabled it).
Tracking events
Properties are nested under properties. This is the single most common
mistake — a top-level bag is silently not read as event properties:
You can attach PII on the same call via traits:
Event names must match ^[a-zA-Z0-9_.]{1,128}$, and the property bag is capped
at 64 KB of JSON. Violate either and the SDK drops the event client-side with an
error in the console rather than sending something the collector will reject.
Commerce helpers — prefer these
trackPurchase, trackAddToCart and trackBeginCheckout take a CommerceData
object and rewrite its well-known keys into the exact property names the backend
enricher reads:
value— becomesproperties.value, the revenue signal.currency— becomesproperties.currency.orderId— becomesproperties.order_id.
That last mapping is the reason to prefer the helpers over raw track(). The
enricher reads order_id, not orderId; ad platforms use it as the
deduplication key, so a camelCase typo means the same purchase can be counted
twice by Meta and by Google Ads. Any extra keys you pass are forwarded unchanged.
The helpers emit purchase, add_to_cart, begin_checkout and lead. If your
reporting is built around order_completed or lead_submitted instead, use
track() with the helper’s property shape — both names carry the same
conversion weight.
identify()
Send raw email and phone. Pivolio normalizes and hashes them server-side so every destination receives byte-identical digests — hashing them yourself is the fastest way to quietly destroy your match rates.
identify() only emits an event when something actually changed: a new
user_id, or a trait whose value differs from what it already holds. Calling it
on every page load with the same payload is therefore free and idiomatic — the
repeats are skipped rather than inflating your event volume. Traits accumulate
across calls, so a later identify({ phone }) keeps the email from earlier.
reset() and destroy()
The singleton reset() also calls destroy() and nulls the instance. After
calling it you must call init() again or every subsequent track() will
warn and no-op. The Tracker class method behaves differently: tracker.reset()
rotates the identity and leaves the tracker running.
Use reset() on logout, to give the browser a fresh anonymous_id and session
and clear accumulated traits:
Use destroy() when you want to tear down listeners without touching identity —
on unmount, or before a hot reload. It persists anything still buffered, so a
later init() replays those events instead of losing them.
Next steps
- Configuration — every option, default and unit.
- Identity and consent — cookies, the linker, opt-out.
- React and Next.js — the framework bindings.