# Install the pixel

**What it does:** records which pages get visited, attributes them to the
campaign that brought the visitor, captures commerce events if your store emits
them, and — where it can — resolves an anonymous visitor to a person.

**Time:** one tag. The rest of this page is what it collects and how to control
it, which is the part worth reading before you paste it.

Every workflow and playbook on this site lists "the pixel live" as a
prerequisite. This is that step.

---

## The tag

```html
<script async
  src="https://app.signal.geysera.com/signal-pixel.js"
  data-tenant="YOUR_WORKSPACE_ID"></script>
```

Put it in `<head>`. `async` is deliberate — the pixel never blocks rendering,
and nothing on the page waits for it.

Your workspace ID is on the **Settings** page, and the wizard shows this snippet
with the ID already filled in.

### Pinning a version

`/signal-pixel.js` always serves the current release. If you would rather decide
when you move, name a version instead:

```html
<script async
  src="https://app.signal.geysera.com/signal-pixel-v3.8.0.js"
  data-tenant="YOUR_WORKSPACE_ID"></script>
```

A pinned URL never changes its bytes. We do not edit a released version, even to
fix a comment — if something needs to change, it becomes a new version and the
unversioned URL moves to it.

Pin if you have a change-control process. Otherwise use the unversioned URL and
get fixes without doing anything.

---

## Consent

**The default is to collect.** A tag with no consent attribute starts recording
on the first page load.

That is the right default for a first-party analytics tag on your own site in
the US, and it is the wrong default if you run a consent banner. If you do, say
so explicitly:

```html
<script async
  src="https://app.signal.geysera.com/signal-pixel.js"
  data-tenant="YOUR_WORKSPACE_ID"
  data-default-consent="false"></script>
```

With that attribute the pixel collects nothing — no page views, no commerce, no
identity resolution, and it does not even load our identity vendor's script —
until you call:

```js
window.geyseraSignal.grantConsent()
```

Call it when the visitor accepts. Anything that happened before the click is not
lost: page views and commerce events detected while waiting are buffered in the
browser and sent on grant. Nothing leaves the browser before that call.

To withdraw:

```js
window.geyseraSignal.revokeConsent()
```

That stops collection, stops identity resolution including any request already
in flight, and discards the identifiers — ours and our identity partner's alike.
A later opt-in starts a new anonymous visitor rather than rejoining the old one.

**One honest limit.** Our identity partner's script, if it had already loaded
before the visitor withdrew, stays loaded for the rest of that page — a
`<script>` that has run cannot be un-run, by us or by anyone. We stop sending,
and we remove the identifiers it relies on, so it has nothing to recognise. It
is gone entirely on the next page load.

If you want it gone immediately, reload the page after calling
`revokeConsent()`. That is what we do on our own site.

A visitor's choice is stored in their browser and survives page loads. A stored
choice always wins over the attribute, so changing the attribute later does not
override someone who already declined.

### What we do regardless of what you configure

Two gates run before yours and cannot be switched on:

- **Global Privacy Control.** If the browser sets
  `navigator.globalPrivacyControl`, the pixel exits immediately and collects
  nothing. `data-default-consent="true"` does not override this.
- **US only.** The pixel asks our API whether the visitor's region is in scope
  and stops permanently if the answer is no. Traffic from outside the US is
  dropped, by design — you will see this as a `403` in the network tab, and it
  is not a misconfiguration.

Those two are why a default of "collect" is defensible: the population it
applies to is US visitors who have not signalled do-not-sell.

---

## What it collects

**Page views.** On load, and on SPA navigation — the pixel hooks `pushState`, so
a client-side router reports each route change as its own view.

**Attribution.** `utm_*` parameters, ad click IDs (`gclid`, `fbclid`,
`msclkid`, `ttclid`, `li_fat_id`, `epik`) and the referrer. Captured on the
landing hit and attached to *every* subsequent event as `campaign`, stored as
both first touch (written once) and last touch.

Click IDs only exist on the landing URL. If the pixel is not on your landing
pages, they are gone — no later page can recover them.

**Commerce**, automatically, by two routes:

- Your GA4 `dataLayer`, if you have one. `add_to_cart`, `begin_checkout`,
  `purchase` and friends are translated to our names. Entries pushed before the
  pixel loaded are replayed, so a receipt page still reports its purchase.
- WooCommerce directly, from the classes the platform puts on `<body>`. This is
  where the order ID comes from, which is what ties a purchase back to the pages
  that led to it.

We do not guess from URLs. A receipt page named `/thank-you` on one store is
`/order-received` on the next, so detection keys on platform signatures instead.

**Identity**, where available. Anonymous visitors are resolved to a person
through our identity partner. This depends on server-side configuration for your
workspace — if it is not enabled, everything else still works and visitors stay
anonymous.

Identification is **not** instant. See
[Reach the buyer while the signal is
warm](./playbooks/reach-the-buyer-while-the-signal-is-warm.md) for the timing
and, more usefully, why it does not matter as much as it sounds.

---

## Telling us who someone is

If you already know — they logged in, or submitted a form:

```js
window.geyseraSignal.identify("dana@acme.com")
```

That is a stronger signal than anything we can infer, and it is worth wiring
into your form handler. It also fills in history: past anonymous activity for
that browser joins up to the person.

Custom events:

```js
window.geyseraSignal.track("demo_requested", { plan: "growth" })
```

---

## Checking it works

Add `?geysera_debug=1` to any page on your site and open the console. The pixel
logs what it is doing and why it is not doing anything, which answers most
install questions immediately — including the two that look identical from
outside: consent not granted, and region out of scope.

In the dashboard, visitors appear on the **Accounts** page. If the console says
events are being sent and the dashboard is empty, the workspace ID in the tag is
the first thing to check.

---

## What will go wrong

**The tag is on some pages, not all.** The commonest one. A tag manager firing
on a page-view trigger usually covers a normal site; a single-page app usually
needs the tag in the shell, not per route. Landing pages matter most, because
that is the only place click IDs exist.

**You run a banner and did not set `data-default-consent="false"`.** Then the
pixel collects before the visitor answers. If you have a banner, set the
attribute — the default assumes you do not.

**Nothing appears and everything looks right.** Check the region. Non-US traffic
is dropped silently by design, and on some sites that is most of it.

**Your store is not WooCommerce and you have no `dataLayer`.** Then page views
and attribution work and commerce events do not. Pushing GA4-shaped events to
`window.dataLayer` is the supported route for any other platform.

---

## Next

- [Quickstart](./quickstart.md) — create an API key and read the data back out.
- [Developer guide](./guide.md) — the API surface in full.
- [Watch your own data quality](./workflows/watch-your-own-data-quality.md) —
  confirm what is arriving is what you expect.
