> ## Documentation Index
> Fetch the complete documentation index at: https://docs.evomarketing.co/llms.txt
> Use this file to discover all available pages before exploring further.

# EVO pixel for websites

> One script tag and one purchase call to report storefront sales back to Dialed

The EVO pixel captures the creator click token when a visitor arrives from a creator link, keeps it for 30 days, and attaches it to the purchase you report.

Nothing in the pixel is allowed to throw into your page. Every failure path is swallowed.

The script is served from `dialed.evomarketing.co`. Its source is published as [`packages/web-pixel/evo-pixel.js`](https://github.com/Evo-Marketing-LLC/evo-attribution-sdk/blob/main/packages/web-pixel/evo-pixel.js) in the SDK repository if you want to read exactly what runs on your page.

## Install

Paste this once, ideally in `<head>`:

```html theme={null}
<script async src="https://dialed.evomarketing.co/evo-pixel.js" data-pixel-key="pk_your_brand_key"></script>
```

<Note>
  Find your pixel key in the client portal under **Results → Attribution**, in the **Developer setup** section. It also shows the ready-to-paste snippet with your key already filled in.
</Note>

| Attribute        | Required | Purpose                                                                                                 |
| ---------------- | -------- | ------------------------------------------------------------------------------------------------------- |
| `data-pixel-key` | Yes      | Identifies your brand. Without it the pixel loads but sends nothing                                     |
| `data-endpoint`  | No       | Overrides the beacon URL. Defaults to `https://dialedapi.evomarketing.co/api/public/attribution/events` |

The pixel exposes a global `evo()` function. Calls made before the script finishes loading are drained from `window.evo.q` once it does, so a stub queue is safe.

## Report a purchase

On your order-confirmation page:

```javascript theme={null}
evo("purchase", { orderId: "1234", amount: 99.5, currency: "USD" })
```

<ParamField path="event type" type="string" default="purchase">
  First argument. `purchase`, `renewal`, `refund`, `trial`, `signup`, `lead`, or `custom`.
</ParamField>

<ParamField path="orderId" type="string">
  Sent as `transaction_id`. This is the deduplication key — the same order id never counts twice. `transactionId` is accepted as an alias.
</ParamField>

<ParamField path="amount" type="number">
  Purchase value in major units, for example `99.5`. `revenue` is accepted as an alias.
</ParamField>

<ParamField path="currency" type="string" default="USD">
  `USD`, `CAD`, `EUR`, `GBP`, or `AUD`. Anything else falls back to `USD`.
</ParamField>

<ParamField path="userId" type="string">
  Sent as `external_user_id`. Optional; useful for tying a web purchase to your own customer record.
</ParamField>

<ParamField path="code" type="string">
  A creator code the customer typed at checkout. Attributes the sale on its own, with no click token in the picture.
</ParamField>

Every beacon also carries the stored click token as `click_token` and an `occurred_at` timestamp.

## Stripe Checkout

`evo.token()` returns the captured click token, or `null` when the visitor did not arrive through a creator link. Pass it when you create the Checkout Session:

```javascript theme={null}
client_reference_id: evo.token()
```

Stripe echoes it back on the webhook, and the [Stripe connector](/attribution/billing-connectors) resolves the creator from it. `metadata.evo_cid` works the same way if `client_reference_id` is already spoken for.

## Shopify

On a Shopify storefront the pixel does one extra thing automatically: the first time it captures a new token, it copies it into the cart attributes.

```javascript theme={null}
fetch("/cart/update.js", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ attributes: { evo_cid: stored.t } }),
  credentials: "same-origin",
})
```

The token is marked as sent *before* the request fires, so reloads and duplicate script tags never send it twice. The Shopify connector then reads `evo_cid` from the order's landing site URL or from that note attribute.

## What gets stored

|          |                                                                              |
| -------- | ---------------------------------------------------------------------------- |
| Where    | `localStorage`, key `evo_attr`                                               |
| Shape    | `{ t: "<click token>", ts: <ms timestamp>, sent: <boolean> }`                |
| Lifetime | 30 days from capture; older entries are ignored                              |
| Cookies  | None. The pixel sets no cookies and sends beacons with `credentials: "omit"` |

Storage access throws in private mode and in some in-app webviews. The pixel catches that and behaves as if no token were present — the purchase still lands, just unattributed.

## Test it

<Steps>
  <Step title="Load a real creator link">
    Open one of your brand's creator links. It forwards to your site with `?evo_cid=evc_…` in the URL.
  </Step>

  <Step title="Confirm the token was captured">
    In the browser console:

    ```javascript theme={null}
    evo.token()
    // → "evc_…"
    ```

    `null` means the pixel did not see an `evo_cid` — check that the script actually loaded on the landing page.
  </Step>

  <Step title="Fire a test purchase">
    ```javascript theme={null}
    evo("purchase", { orderId: "test-order-1", amount: 10, currency: "USD" })
    ```

    In the Network tab the request to `/api/public/attribution/events` should return `200` with `{"ok":true,"duplicate":false}`.
  </Step>

  <Step title="Repeat it">
    Fire the exact same call again. It returns `{"ok":true,"duplicate":true}` — proof that `orderId` is deduplicating.
  </Step>

  <Step title="Check the portal">
    The conversion and its revenue appear against that creator's link under **Results → Attribution**.
  </Step>
</Steps>

You can also test the endpoint directly, without a browser:

```bash theme={null}
curl -i https://dialedapi.evomarketing.co/api/public/attribution/events \
  -H 'Content-Type: application/json' \
  -d '{"pixel_key":"pk_your_brand_key","event_type":"purchase","transaction_id":"test-order-1","amount":10,"currency":"USD"}'
```

## Troubleshooting

### Nothing arrives at all

Check the pixel key. An unknown or blank `pixel_key` returns `403` with `{"error":"invalid_pixel_key"}`. Also confirm the script tag has `data-pixel-key` — without it the pixel loads and silently no-ops.

### `evo.token()` returns null

The visitor did not arrive through a creator link on this browser, the token is older than 30 days, or `localStorage` is unavailable (private mode, some in-app webviews). Purchases still record; they resolve as unattributed unless a creator code is passed.

### Ad blockers

The beacon is a normal cross-origin `fetch` and can be blocked. Delivery is best-effort by design and never retried. If a meaningful share of your traffic blocks it, report purchases server-side through a [billing connector](/attribution/billing-connectors) instead — connectors are unaffected by the browser.

### The purchase counted twice

It should not: `(brand, event_type, transaction_id)` is unique in the database. If you see two rows, you sent two different `orderId` values for one order.

### Revenue is right but the creator is missing

The purchase landed without a click token. Common causes: the confirmation page is on a different domain than the landing page (separate `localStorage`), the checkout is hosted by a third party, or the visitor cleared storage. Use `evo.token()` at checkout, the Shopify cart attribute, or a creator code.
