> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.pivolio.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.pivolio.com/_mcp/server.

# JavaScript SDK

The JavaScript SDK is an inbound source like any other: it authenticates with a
write key and POSTs `UnifiedEvent`s to the collector. What makes it different is
*where* it runs. A browser sees things no server-side source ever will, and the
SDK captures all of them without you writing any code.

For installation, configuration and the full API, see the
[SDK documentation](/documentation/sd-ks/overview) — this page only covers what the SDK
contributes as a source.

## What only the browser can capture

* **Click IDs.** A `gclid`, `fbclid`, `ttclid` or any of the other 11 URL click
  IDs exists exactly once — in the query string of the landing page an ad sent
  the visitor to. The SDK reads them on arrival and persists them for 30 days by
  default, so a purchase three weeks later still carries the click that earned
  it. It also re-reads the `_fbp`, `_fbc` and `_ttp` cookies fresh on every
  event.
* **UTM parameters.** `utm_source`, `utm_medium`, `utm_campaign`, `utm_content`
  and `utm_term` are captured and stored the same way. Click IDs are *merged*
  across visits; a new campaign *replaces* the stored one.
* **Session and page context.** Session ID and start time, page URL, path,
  referrer and title, and device details — the raw material for attribution
  channel inference.
* **Consent state.** Google Consent Mode v2 signals travel with each event, and
  the SDK enforces them client-side before anything leaves the page.

Without these, attribution falls back to referrer inference and UTM medium, and
your ad-platform match rates drop — click ID is the single heaviest-weighted
match signal on every destination.

## The only source that establishes identity

The SDK is what creates a visitor's **anonymous ID**. On init it calls `/id`,
adopts the server's `anonymous_id`, and stores it in both a cookie and
localStorage for 365 days.

That server round-trip matters: Safari's ITP caps script-written cookies at
about seven days, so a purely client-set ID quietly forgets returning visitors
inside a week. The httpOnly cookie the server sets survives far longer.

Every other source — the [webhook](/documentation/integrations/inbound-webhook), [Shopify](/documentation/integrations/shopify) — has to
*supply* an `anonymous_id` rather than mint one. In practice that means reading
the ID the SDK already established and passing it through, which is what ties a
server-side conversion back to the ad click that started it.

> **Tip**
>
> If a server-side source has no browser ID to forward, send `traits.email` or
> `traits.phone` instead. Identity resolution will match on the hashed identifier
> and merge the person — you just lose the click unless the SDK stored one for
> that person first.

## Where to go next

* [SDK overview](/documentation/sd-ks/overview) — packages, installation and the API.
* [Inbound webhook](/documentation/integrations/inbound-webhook) — pair the SDK with a server-side source.
* [Integrations](/documentation/integrations/overview) — every available source.