> For the complete documentation index, see [llms.txt](https://docs.chord.co/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.chord.co/activate/event-streaming/destinations/email-and-marketing/insider/insider-pixel.md).

# Insider Pixel

This destination loads the Insider One Web SDK (`ins.js`) directly in the visitor's browser and sends page views, ecommerce events and user profile updates from there using `window.InsiderQueue`. Unlike the [Insider One](/activate/event-streaming/destinations/email-and-marketing/insider/insider-one.md) version, events originate from the browser and are subject to ad blockers, but they carry richer client-side context such as session data and browser fingerprinting. See [Insider](/activate/event-streaming/destinations/email-and-marketing/insider.md) for how the two fit together.

## Getting started

Chord loads the Insider One Web SDK (`ins.js`) for you, so you don't need to install a script yourself. Get your partner name and, if you have one, your partner ID from your Insider One account. Both are in **InOne Panel > Settings > Account Preferences**. The partner name is the subdomain in your SDK URL, for example `mystore` in `mystore.api.useinsider.com`.

## Settings

* **Destination Name** (required): a name to tell this destination apart.
* **Partner Name** (required): your Insider partner name (account slug), the subdomain used in your Insider SDK URL. Found in your Insider One account settings.
* **Partner ID** (optional): your Insider partner ID. When you provide it, Chord adds it as the `id` query parameter on the SDK script URL (`ins.js?id=<partnerId>`).
* **Consent Requirements** (optional): the consent categories a visitor must accept before Chord sends data to this destination. See [Consent](/activate/event-streaming/consent.md).

## Connect

Add **Insider Pixel** from the destination catalog, using the settings above. See [Connect a destination](/activate/event-streaming/connect-a-destination.md) for the full steps.

## Event mapping

| Chord event         | Insider One event                    | Notes                                                   |
| ------------------- | ------------------------------------ | ------------------------------------------------------- |
| `identify`          | `user` → `init`                      | Updates user attributes; no event recorded              |
| `page`              | `user` → `other` → `init`            | Sends a generic page view with the page title           |
| `track` (ecommerce) | `user` → *(event-specific)* → `init` | See [Ecommerce event mapping](#ecommerce-event-mapping) |
| `track` (other)     | `user` → `custom_event` → `init`     | Sent as a custom event                                  |

Chord silently drops other event types, such as `group`, `screen` and `alias`.

## Ecommerce event mapping

Six Chord ecommerce track event names map to dedicated Insider SDK queue types:

| Chord event           | Insider One event  | Notes                                                                                         |
| --------------------- | ------------------ | --------------------------------------------------------------------------------------------- |
| `Product Viewed`      | `product`          | The event's product: its top-level product fields, or the first item in `properties.products` |
| `Product List Viewed` | `category`         | Category breadcrumb from `properties.category` or first product's category                    |
| `Cart Viewed`         | `cart`             | Full product list with totals                                                                 |
| `Product Added`       | `add_to_cart`      | The event's product, as for `Product Viewed`                                                  |
| `Product Removed`     | `remove_from_cart` | The event's product, as for `Product Viewed`                                                  |
| `Order Completed`     | `purchase`         | Full product list with order totals. Chord skips it when the order has no products            |

If a product event has no product, Chord pushes only the user data. All other track event names are sent as `custom_event` (see [Custom events](#custom-events)).

## User data

Chord pushes user data on **every** event (not only `identify`), so Insider always has the latest profile context regardless of event order. Chord only pushes a field it finds a value for.

| Chord source (priority order)                                                                        | Insider One field             | Notes                                                                                             |
| ---------------------------------------------------------------------------------------------------- | ----------------------------- | ------------------------------------------------------------------------------------------------- |
| `userId`                                                                                             | `uuid`                        | Primary user identifier                                                                           |
| `properties.email` > `properties.emailAddress` > `context.traits.email` > `traits.email`             | `email`                       |                                                                                                   |
| `properties.phone` > `properties.phoneNumber` > `context.traits.phone` > `traits.phone`              | `phone_number`                |                                                                                                   |
| `properties.first_name` > `properties.firstName` > `context.traits.first_name` > `traits.first_name` | `name`                        | If none is present, Chord uses the first word of `address.name`                                   |
| `properties.last_name` > `properties.lastName` > `context.traits.last_name` > `traits.last_name`     | `surname`                     | If none is present, Chord uses the second word of `address.name`                                  |
| `properties.gender` > `context.traits.gender` > `traits.gender`                                      | `gender`                      |                                                                                                   |
| `properties.birthday` > `context.traits.birthday` > `traits.birthday`                                | `birthday`                    |                                                                                                   |
| `address.city`                                                                                       | `city`                        | The address comes from `properties.address`, then `context.traits.address`, then `traits.address` |
| `address.country`                                                                                    | `country`                     | Same address order as `city`                                                                      |
| `context.locale`                                                                                     | `language`                    | Hyphens converted to underscores, e.g. `en-US` → `en_US`                                          |
| `anonymousId`                                                                                        | `custom.segment_anonymous_id` | Always included                                                                                   |

## Identify events

Identify events push user attributes then trigger an `init` flush:

```
InsiderQueue.push({ type: "user", value: <user object> })
InsiderQueue.push({ type: "init" })
```

See the [User data](#user-data) table for the full field mapping.

## Page events

Page events push a generic page view using the `other` queue type:

```
InsiderQueue.push({ type: "user", value: <user object> })
InsiderQueue.push({ type: "other", value: { name: <page title> } })
InsiderQueue.push({ type: "init" })
```

| Chord source (priority order)                                        | Insider One field | Notes                                     |
| -------------------------------------------------------------------- | ----------------- | ----------------------------------------- |
| `context.page.title` > `properties.title` > the browser's page title | `other.name`      | Page title sent as the `other` event name |

URL and referrer are not included in the queue push. The Insider SDK reads these automatically from the browser.

## Ecommerce events

Each ecommerce event type pushes a specific SDK payload. Chord pushes the currency separately. It uses `properties.currency`, then `properties.meta.i18n.currency`, then `USD`. See the [User data](#user-data) table for user field mappings shared across all events.

**Product Viewed (`product` type)**

Uses the event's product. See the [Product object](#product-object) table for field mappings.

```
InsiderQueue.push({ type: "user", value: <user object> })
InsiderQueue.push({ type: "currency", value: <currency> })
InsiderQueue.push({ type: "product", value: <product object> })
InsiderQueue.push({ type: "init" })
```

| Chord source (priority order)                           | Insider One field | Notes                                 |
| ------------------------------------------------------- | ----------------- | ------------------------------------- |
| `properties.currency` > `properties.meta.i18n.currency` | `currency`        | Defaults to `USD`                     |
| The event's product                                     | `product.*`       | See [Product object](#product-object) |

**Product List Viewed (`category` type)**

```
InsiderQueue.push({ type: "user", value: <user object> })
InsiderQueue.push({ type: "category", value: { breadcrumb: [<category>] } })
InsiderQueue.push({ type: "init" })
```

| Chord source (priority order)                      | Insider One field     | Notes                                           |
| -------------------------------------------------- | --------------------- | ----------------------------------------------- |
| `properties.category` > first product's `category` | `category.breadcrumb` | Wrapped in array. Empty if there is no category |

**Cart Viewed (`cart` type)**

```
InsiderQueue.push({ type: "user", value: <user object> })
InsiderQueue.push({ type: "currency", value: <currency> })
InsiderQueue.push({ type: "cart", value: { total, items, shipping_cost } })
InsiderQueue.push({ type: "init" })
```

| Chord source (priority order)                                                                          | Insider One field    | Notes                                                           |
| ------------------------------------------------------------------------------------------------------ | -------------------- | --------------------------------------------------------------- |
| `properties.currency` > `properties.meta.i18n.currency`                                                | `currency`           | Defaults to `USD`                                               |
| `properties.total` > `properties.value` > `properties.price` > sum of the item prices times quantities | `cart.total`         | `0` if none is present                                          |
| `properties.shipping`                                                                                  | `cart.shipping_cost` | Only pushed when present                                        |
| `properties.products`                                                                                  | `cart.items`         | Array of product objects. See [Product object](#product-object) |

**Product Added / Product Removed (`add_to_cart` / `remove_from_cart` type)**

Uses the event's product. See the [Product object](#product-object) table for field mappings.

```
InsiderQueue.push({ type: "user", value: <user object> })
InsiderQueue.push({ type: "add_to_cart" | "remove_from_cart", value: <product object> })
InsiderQueue.push({ type: "init" })
```

**Order Completed (`purchase` type)**

```
InsiderQueue.push({ type: "user", value: <user object> })
InsiderQueue.push({ type: "currency", value: <currency> })
InsiderQueue.push({ type: "purchase", value: { order_id, total, items, shipping_cost } })
InsiderQueue.push({ type: "init" })
```

| Chord source (priority order)                                                                          | Insider One field        | Notes                                                                                                      |
| ------------------------------------------------------------------------------------------------------ | ------------------------ | ---------------------------------------------------------------------------------------------------------- |
| `properties.currency` > `properties.meta.i18n.currency`                                                | `currency`               | Defaults to `USD`                                                                                          |
| `properties.order_id` > `properties.orderId` > `properties.id`                                         | `purchase.order_id`      | If none is present, Chord uses the cart ID (`cart_id` or `cartId`). An order ID always wins over a cart ID |
| `properties.total` > `properties.value` > `properties.price` > sum of the item prices times quantities | `purchase.total`         | `0` if none is present                                                                                     |
| `properties.shipping`                                                                                  | `purchase.shipping_cost` | Only pushed when present                                                                                   |
| `properties.products`                                                                                  | `purchase.items`         | Array of product objects. See [Product object](#product-object)                                            |

## Product object

The product object is used for `product`, `add_to_cart`, `remove_from_cart`, and each item in the `cart` and `purchase` `items` arrays.

| Chord source (priority order)           | Insider One field   | Notes                                                 |
| --------------------------------------- | ------------------- | ----------------------------------------------------- |
| `product_id` > `sku` > `id`             | `id`                | At least one identifier required                      |
| `name` > `productName` > `product_name` | `name`              |                                                       |
| `category`                              | `taxonomy`          | Wrapped in array; omitted if not present              |
| `price`                                 | `unit_sale_price`   | Chord doesn't read a separate `unit_sale_price` field |
| `price`                                 | `unit_price`        | Same value as `unit_sale_price`                       |
| `quantity`                              | `quantity`          | Defaults to `1`                                       |
| `url`                                   | `url`               |                                                       |
| `image_url`                             | `product_image_url` |                                                       |

Chord leaves out items without a resolvable ID from `cart` and `purchase` items.

## Custom events

All track events not in the ecommerce map are sent as `custom_event`:

```
InsiderQueue.push({ type: "user", value: <user object> })
InsiderQueue.push({ type: "custom_event", value: [{ event_name, event_parameters }] })
InsiderQueue.push({ type: "init" })
```

| Chord source (priority order) | Insider One field         | Notes                                                                    |
| ----------------------------- | ------------------------- | ------------------------------------------------------------------------ |
| `event`                       | `event_name`              | Lowercased, spaces replaced with underscores                             |
| `properties`                  | `event_parameters.custom` | All properties forwarded as-is, except the `meta` field and empty values |

Property keys are not lowercased or aliased for custom events. Chord forwards them as received.

## Initialization

On the first event, Chord:

1. Sets `window.InsiderQueue = window.InsiderQueue || []` to ensure the queue exists before the SDK loads
2. Constructs the SDK URL: `https://<partnerName>.api.useinsider.com/ins.js`, with `?id=<partnerId>` appended if a Partner ID is configured. Chord lowercases the Partner Name. If it contains anything other than letters, numbers and hyphens, Chord doesn't load the SDK
3. Loads the script via a `<script>` tag injection
4. Tracks SDK loading state (`fresh` → `loading` → `loaded` / `failed`) using `window.__chordCDPInsiderPixelState` to prevent duplicate script loads

Events arriving after the first load reuse the already-loaded SDK. If the script fails to load, subsequent events are silently dropped.

## CSP requirements

If your site uses a Content Security Policy, allow the following domains:

| Directive     | Domain                         |
| ------------- | ------------------------------ |
| `script-src`  | `https://*.api.useinsider.com` |
| `connect-src` | `https://*.api.useinsider.com` |
| `img-src`     | `https://*.api.useinsider.com` |

## Testing and validation

Because this destination runs in the browser, events are sent directly from the browser. They do not appear in the **Live Events** tab in Chord. Validate using browser developer tools instead.

After connecting the destination:

1. Load your storefront and open browser developer tools (**Network** tab, filter by `useinsider`).
2. Confirm `ins.js` is loaded from `<partnerName>.api.useinsider.com` and the **Initiator** column points to the Chord snippet.
3. In the browser **Console**, inspect `window.InsiderQueue` immediately after page load (before the SDK initializes) to verify queue items are being pushed with the correct `type` and `value` structure.
4. Check the network requests the SDK fires after initialization: `hit` and `insert` for page and user events, `set-purchase-stats` for purchase events.
5. In Insider One, navigate to **InOne Panel > Audience** and verify the user profile was created or updated.

## Troubleshooting

### SDK not loading

**Problem:** The Insider SDK script is not being injected into the page.

* Confirm the destination is enabled in Chord and that your storefront is loading the Chord snippet.
* Verify the **Partner Name** is correct — it must match the subdomain of your Insider account (e.g. `mystore`, not `mystore.api.useinsider.com`).
* Check your browser's Content Security Policy — a missing `script-src` or `connect-src` allowance for `*.api.useinsider.com` will block the script.
* Inspect the browser console for script load errors.

### Events not appearing in Insider One

**Problem:** The SDK loads but events do not appear in the Insider One panel.

* In the browser console, inspect `window.InsiderQueue` before SDK initialization to confirm queue items are being pushed.
* Verify that Insider's Web SDK "new IO mode" (`inioa`) is enabled for your account. The `InsiderQueue` integration requires this to be active — contact Insider support to confirm or enable it.
* Confirm that a `userId` is present on events. Without a UUID, Insider cannot match events to a profile.

### Duplicate profiles

**Problem:** Insider One is creating multiple profiles for the same customer.

* Confirm that events consistently include the same `userId`. Inconsistent identifiers cause Insider to create separate profiles.
* If your store captures both anonymous and logged-in sessions, ensure an identify call is sent when a user logs in.

### Existing Insider pixel conflict

**Problem:** The Insider SDK was already installed directly on the storefront before switching to Chord's browser destination.

* Remove the native `ins.js` script tag (or tag manager rule) from the storefront. Running both the native pixel and Chord's browser destination simultaneously causes duplicate SDK loads and can prevent Chord's queue items from being processed correctly.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.chord.co/activate/event-streaming/destinations/email-and-marketing/insider/insider-pixel.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
