> 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/collect-data/everyone-else/sdk-reference.md).

# SDK reference

Reference for `@chordcommerce/analytics`, Chord's browser SDK. To install it, see [Browser events](/collect-data/everyone-else/browser-events.md).

## Configuration

### Initialization options

| Property                 | Required | Default   | Description                                                                                                                                                |
| ------------------------ | -------- | --------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `cdpDomain`              | Yes\*    | —         | Your Chord domain (provided by the Chord team)                                                                                                             |
| `cdpWriteKey`            | Yes\*    | —         | Your Chord write key (provided by the Chord team)                                                                                                          |
| `cdp`                    | No\*     | —         | Reference to an external analytics library. If provided, events are also sent to that library.                                                             |
| `formatters`             | Yes      | —         | Functions for transforming your platform's data into the Chord tracking plan format                                                                        |
| `metadata`               | Yes      | —         | Event metadata identifying your store and platform                                                                                                         |
| `consent`                | No       | —         | Consent adapter: `"cookiebot"`, `"ketch"`, `"onetrust"`, `"segment"` or `"shopify"`. See [Consent](/collect-data/everyone-else/browser-events/consent.md). |
| `debug`                  | No       | `false`   | Validates events against the tracking plan and logs warnings when `enableLogging` is on. Recommended during development.                                   |
| `enableLogging`          | No       | `false`   | Logs events, errors and `debug` warnings to the browser console. Turn it on with `debug` while testing.                                                    |
| `namespace`              | No       | `"chord"` | The global namespace where the Chord instance is available (e.g., `window.chord`)                                                                          |
| `stripNull`              | No       | `true`    | Removes properties with null values from events before sending                                                                                             |
| `enableWebPixelListener` | No       | `true`    | Receives events from Chord's Shopify custom web pixel. Disable if not using the web pixel.                                                                 |

{% hint style="info" %}
\*At least one of `cdpDomain`/`cdpWriteKey` or `cdp` must be provided. If all three are omitted, no events are sent.
{% endhint %}

### Metadata

Metadata is included with every event and identifies your store to Chord.

```typescript
metadata: {
  i18n: {
    currency: 'USD',      // ISO 4217 currency code (uppercase)
    locale: 'en-US',      // Locale string
  },
  ownership: {
    omsId: '...',          // UUID assigned by Chord
    storeId: '...',        // UUID assigned by Chord
    tenantId: '...',       // UUID assigned by Chord
  },
  platform: {
    name: 'Shopify',       // Your commerce platform name
    type: 'web',           // 'web' or 'pos'
  },
  store: {
    domain: 'my-store',    // Store slug (for Shopify: the part before .myshopify.com)
  },
}
```

#### Metadata fields

| Property                      | Required | Description                                                   |
| ----------------------------- | -------- | ------------------------------------------------------------- |
| `metadata.i18n.currency`      | Yes      | ISO 4217 currency code, uppercase (e.g., `USD`, `GBP`, `EUR`) |
| `metadata.i18n.locale`        | Yes      | Locale string (e.g., `en-US`, `fr-FR`)                        |
| `metadata.ownership.omsId`    | Yes      | UUID assigned by Chord (unique per store)                     |
| `metadata.ownership.storeId`  | Yes      | UUID assigned by Chord (unique per store)                     |
| `metadata.ownership.tenantId` | Yes      | UUID assigned by Chord (unique per organization)              |
| `metadata.platform.name`      | Yes      | Commerce platform name (e.g., `shopify`, `custom`)            |
| `metadata.platform.type`      | Yes      | Platform type: `web` or `pos`                                 |
| `metadata.store.domain`       | Yes      | Store domain or slug                                          |

## Methods

### Page views

#### `chord.page()`

Sends a page view event to Chord.

```typescript
chord.page()
```

***

### User identity

#### `chord.identify(userId, traits)`

Sends an identify event to associate a user with their traits. Call this after account creation, login, or when a user submits identifying information.

```typescript
chord.identify(userId, { email, phone, firstName, lastName })
// or without userId:
chord.identify({ email, phone })
```

| Property | Type     | Required | Description                            |
| -------- | -------- | -------- | -------------------------------------- |
| `userId` | `string` | No       | The user's unique identifier           |
| `traits` | `object` | No       | User traits (email, phone, name, etc.) |

{% hint style="info" %}
**Best practice:** Send `identify` before `track` events when both occur at the same time. Some downstream integrations require identity to be established before processing track events.
{% endhint %}

#### `chord.reset()`

Resets the user session. The user receives a new anonymous identifier and previous user data is cleared. Call this after logout.

```typescript
chord.reset()
```

***

### Product events

#### `chord.trackProductViewed({ cart, product })`

Sends a "Product Viewed" event. Call this whenever a product page is viewed.

| Property            | Type     | Required | Description                 |
| ------------------- | -------- | -------- | --------------------------- |
| `cart`              | `any`    | Yes      | The current cart            |
| `product.product`   | `any`    | Yes      | Product and variant details |
| `product.position`  | `number` | No       | Position in a list          |
| `product.quantity`  | `number` | No       | Quantity                    |
| `product.variantId` | `any`    | No       | Product variant identifier  |

#### `chord.trackProductAdded({ cart, product })`

Sends a "Product Added" event when a product is first added to cart (not for quantity changes).

Same parameters as `trackProductViewed`.

#### `chord.trackProductRemoved({ cart, lineitem })`

Sends a "Product Removed" event when a product is removed from cart.

| Property   | Type  | Required | Description            |
| ---------- | ----- | -------- | ---------------------- |
| `cart`     | `any` | Yes      | The cart after removal |
| `lineitem` | `any` | Yes      | The removed line item  |

#### `chord.trackProductClicked({ cart, product, listId, listName })`

Sends a "Product Clicked" event when a product link is clicked.

| Property           | Type     | Required | Description          |
| ------------------ | -------- | -------- | -------------------- |
| `cart`             | `any`    | Yes      | The current cart     |
| `product.product`  | `any`    | Yes      | Product details      |
| `product.position` | `number` | No       | Position in the list |
| `listId`           | `any`    | No       | List identifier      |
| `listName`         | `string` | No       | List name            |

#### `chord.trackProductListViewed({ category, listId, listName, products })`

Sends a "Product List Viewed" event.

| Property   | Type     | Required | Description          |
| ---------- | -------- | -------- | -------------------- |
| `category` | `string` | No       | Product category     |
| `listId`   | `string` | No       | List identifier      |
| `listName` | `string` | No       | List name            |
| `products` | `array`  | Yes      | Products in the list |

#### `chord.trackProductListFiltered({ category, listId, listName, filters, sorts })`

Sends a "Product List Filtered" event when filters are applied.

| Property   | Type     | Required | Description                           |
| ---------- | -------- | -------- | ------------------------------------- |
| `category` | `string` | No       | Product category                      |
| `listId`   | `string` | No       | List identifier                       |
| `listName` | `string` | No       | List name                             |
| `filters`  | `array`  | No       | Applied filters (`[{ type, value }]`) |
| `sorts`    | `array`  | No       | Applied sorts (`[{ type, value }]`)   |

#### `chord.trackProductsSearched({ query })`

Sends a "Products Searched" event.

| Property    | Type     | Required | Description             |
| ----------- | -------- | -------- | ----------------------- |
| `query`     | `string` | No       | Search query            |
| `productId` | `any`    | No       | Product ID searched for |
| `currency`  | `string` | No       | ISO 4217 currency code  |
| `price`     | `number` | No       | Product price           |
| `quantity`  | `number` | No       | Quantity                |

***

### Cart events

#### `chord.trackCartViewed({ cart })`

Sends a "Cart Viewed" event.

| Property | Type  | Required | Description      |
| -------- | ----- | -------- | ---------------- |
| `cart`   | `any` | Yes      | The current cart |

***

### Checkout events

#### `chord.trackCheckoutStarted({ checkout })`

Sends a "Checkout Started" event.

| Property   | Type  | Required | Description          |
| ---------- | ----- | -------- | -------------------- |
| `checkout` | `any` | Yes      | The current checkout |

#### `chord.trackCheckoutStepViewed({ checkoutId, step })`

Sends a "Checkout Step Viewed" event.

| Property         | Type     | Required | Description         |
| ---------------- | -------- | -------- | ------------------- |
| `checkoutId`     | `string` | Yes      | Checkout identifier |
| `step`           | `number` | Yes      | Step number         |
| `paymentMethod`  | `string` | No       | Payment method      |
| `shippingMethod` | `string` | No       | Shipping method     |

#### `chord.trackCheckoutStepCompleted({ checkoutId, step })`

Sends a "Checkout Step Completed" event.

Same parameters as `trackCheckoutStepViewed`.

#### `chord.trackPaymentInfoEntered({ checkoutId, step })`

Sends a "Payment Info Entered" event.

| Property         | Type     | Required | Description          |
| ---------------- | -------- | -------- | -------------------- |
| `checkoutId`     | `string` | No       | Checkout identifier  |
| `step`           | `number` | Yes      | Step number          |
| `paymentMethod`  | `string` | No       | Payment method used  |
| `shippingMethod` | `string` | No       | Shipping method      |
| `coupon`         | `string` | No       | Coupon code          |
| `currency`       | `string` | No       | Currency code        |
| `orderId`        | `string` | No       | Order identifier     |
| `value`          | `number` | No       | Total value          |
| `products`       | `array`  | No       | Products in checkout |

***

### Order events

#### `chord.trackOrderCompleted({ orderId, orderDate, currency, revenue, total, products })`

Sends an "Order Completed" event.

| Property    | Type     | Required | Description                  |
| ----------- | -------- | -------- | ---------------------------- |
| `orderId`   | `string` | Yes      | Order identifier             |
| `orderDate` | `string` | Yes      | Date of completion           |
| `currency`  | `string` | Yes      | Currency code                |
| `revenue`   | `number` | Yes      | Revenue (subtotal)           |
| `total`     | `number` | Yes      | Total with discounts/coupons |
| `products`  | `array`  | Yes      | Products in the order        |

***

### Coupon events

#### `chord.trackCouponApplied({ cartId, couponId, couponName, discount, orderId })`

Sends a "Coupon Applied" event after successful application.

| Property     | Type     | Required | Description              |
| ------------ | -------- | -------- | ------------------------ |
| `cartId`     | `string` | No       | Cart identifier          |
| `couponId`   | `string` | No       | Coupon identifier        |
| `couponName` | `string` | No       | Coupon name              |
| `discount`   | `number` | No       | Monetary discount amount |
| `orderId`    | `string` | No       | Order identifier         |

#### `chord.trackCouponDenied({ cartId, couponId, couponName, orderId, reason })`

Sends a "Coupon Denied" event.

Same parameters as `trackCouponApplied`, plus `reason` (`string`, optional).

#### `chord.trackCouponEntered({ cartId, couponId, couponName, discount, orderId })`

Sends a "Coupon Entered" event immediately after entry, before approval/denial.

Same parameters as `trackCouponApplied`.

#### `chord.trackCouponRemoved({ cartId, couponId, couponName, discount, orderId })`

Sends a "Coupon Removed" event.

Same parameters as `trackCouponApplied`.

***

### Email & login events

#### `chord.trackEmailCaptured({ email, placementComponent, placementPage })`

Sends an "Email Captured" event when a customer enters an email address.

| Property             | Type     | Required | Description                                         |
| -------------------- | -------- | -------- | --------------------------------------------------- |
| `email`              | `string` | No       | Email address captured                              |
| `placementComponent` | `string` | No       | UI component identifier (e.g., `footer-newsletter`) |
| `placementPage`      | `string` | No       | Page identifier (e.g., `homepage`)                  |

#### `chord.trackLoginStarted({ email })`

Sends a "Login Started" event.

| Property | Type     | Required | Description          |
| -------- | -------- | -------- | -------------------- |
| `email`  | `string` | No       | Email used for login |

***

### Authentication events

#### `chord.trackSignedIn({ email, method })`

Sends a "Signed In" event after successful login.

| Property | Type     | Required | Description  |
| -------- | -------- | -------- | ------------ |
| `email`  | `string` | No       | User's email |
| `method` | `string` | No       | Login method |

#### `chord.trackSignedUp({ email, method })`

Sends a "Signed Up" event after successful signup.

Same parameters as `trackSignedIn`.

#### `chord.trackSignedOut({ email })`

Sends a "Signed Out" event after successful logout.

| Property | Type     | Required | Description  |
| -------- | -------- | -------- | ------------ |
| `email`  | `string` | No       | User's email |

***

### Navigation events

#### `chord.trackNavigationClicked({ category, label, navigationPlacement, navigationTitle, navigationUrl })`

Sends a "Navigation Clicked" event.

| Property              | Type     | Required | Description                          |
| --------------------- | -------- | -------- | ------------------------------------ |
| `category`            | `string` | No       | Navigation category                  |
| `label`               | `string` | No       | Navigation label                     |
| `navigationPlacement` | `string` | No       | Placement (e.g., `header`, `footer`) |
| `navigationTitle`     | `string` | No       | Navigation title                     |
| `navigationUrl`       | `string` | No       | Target URL                           |

***

### Variant events

#### `chord.trackVariantClicked({ product, cart, lineItemId, coupon })`

Sends a "Variant Clicked" event.

| Property     | Type     | Required | Description          |
| ------------ | -------- | -------- | -------------------- |
| `product`    | `any`    | Yes      | The variant clicked  |
| `cart`       | `any`    | Yes      | The current cart     |
| `lineItemId` | `string` | No       | Line item identifier |
| `coupon`     | `string` | No       | Coupon code          |

***

### Subscription events

#### `chord.trackSubscriptionCancelled({ subscriptionId, ... })`

Sends a "Subscription Cancelled" event.

| Property         | Type     | Required | Description                    |
| ---------------- | -------- | -------- | ------------------------------ |
| `subscriptionId` | `string` | No       | Subscription identifier        |
| `email`          | `string` | No       | Associated email               |
| `brand`          | `string` | No       | Associated brand               |
| `currency`       | `string` | No       | Currency code                  |
| `intervalLength` | `number` | No       | Subscription interval length   |
| `intervalUnits`  | `string` | No       | Interval units (e.g., `month`) |
| `state`          | `string` | No       | Subscription state             |
| `products`       | `array`  | No       | Products in subscription       |
| `actionableDate` | `string` | No       | Actionable date                |
| `endDate`        | `string` | No       | End date                       |
| `address`        | `object` | No       | Associated address             |

***

### Generic track method

#### `chord.track(eventName, properties)`

Sends a custom event directly to Chord. This bypasses formatters and sends properties as-is.

```typescript
chord.track('Custom Event Name', {
  custom_property: 'value',
  another_property: 123,
})
```

{% hint style="info" %}
\*\*Important: \*\*This method does not use formatters or transform property names. Use snake\_case for all property names. Prefer event-specific methods when available.
{% endhint %}

## Formatters

Formatters are Javascript functions that are used to construct tracking event data. There are two types of formatters, `objects` and `events`. You must define `object` formatters. `event` formatters are optional.

### Object formatters

When you look at Chord's tracking events, you'll see some event properties are used over and over. Names and values of event properties are expected to be consistent between events. In other words, different events have different properties, but a given property name should have the same value wherever it's used.

For example, the two events `Product Added` and `Product Clicked` share most of the same event properties. `product_id` is a property of both events, and the value of `product_id` is expected to be the same for both events. It should not be a product SKU for one event and a database identifier for another event.

Chord ensures consistency in property names and values by creating a standard set of object models that are used over and over throughout events. There are four: `cart`, `checkout`, `lineItem`, and `product`. When you install Chord's analytics library, you write a formatter function for each of these four types. Your formatter function will receive as an argument the input from the event tracking function, and your formatter must return an object in the format that Chord expects. Then Chord uses this formatter to generate the correct event payload.

#### Available object formatters

| Method   | Type                                   | Description                        |
| -------- | -------------------------------------- | ---------------------------------- |
| cart     | (props: `CartInput`) => `Cart`         | Returns a Chord `Cart` object.     |
| checkout | (props: `CheckoutInput`) => `Checkout` | Returns a Chord `Checkout` object. |
| lineItem | (props: `LineItemInput`) => `LineItem` | Returns a Chord `LineItem` object. |
| product  | (props: `ProductInput`) => `Product`   | Returns a Chord `Product` object.  |

#### Example object formatter

Let's walk through an example of a `cart` formatter.

In your website code, you might want to send a `Cart Viewed` tracking event. The code used to send `Cart Viewed` looks like this:

```typescript
var cart = await getCartFromShopifyStorefrontApi() // the `cart` object here can be any type
chord.trackCartViewed({ cart })
```

But how does Chord create a standard `Cart Viewed` event when you can pass any arbitrary cart object as the value? You'll define a formatter that converts your `cart` object into a format that Chord understands. See the `Cart` Typescript type exported by `@chordcommerce/analytics` to see what the return type of the cart formatter should be. Here's an example of a cart formatter that converts a [Shopify Storefront API cart response](https://shopify.dev/docs/api/storefront/2023-10/objects/Cart) into Chord's `Cart` object:

```typescript
import { CartInput, Cart, ChordAnalytics } from '@chordcommerce/analytics'

const cartFormatter: (props: CartInput) => Cart = ({ cart }) => {
  const products = cart?.lines?.map((line, i) => {
    const lineItem = line?.node
    return {
      ...lineItemFormatter({ lineItem }), // your `lineItem` formatter
      position: i + 1,
    }
  })

  return {
    cart_id: cart?.id?.replace('gid://shopify/Cart/', ''),
    currency: 'USD',
    products,
    value: Number(cart?.cost?.subtotalAmount?.amount) || 0,
  }
}

// When creating an instance of `ChordAnalytics`, set `formatters.objects.cart` to `cartFormatter`
const chord = new ChordAnalytics({
  ...
  formatters: {
    objects: {
      cart: cartFormatter,
      ...
    },
  }
})
```

### Event formatters

Event formatters are optional. You can supply an event formatter for any event-specific tracking method of `ChordAnalytics`; for example, for `chord.trackProductAdded`, you can set an event formatter with the key `productAdded`.

Chord's library will call your event formatter after constructing the tracking event but before sending to the CDP. This is the easiest way to customize a Chord tracking event, if you're not able to get the effect you want with object formatters. A common use case is to add additional properties to a specific tracking event.

#### Available event formatters

All event formatters are optional. Event formatters have two arguments: `props`, which is the argument passed to the related tracking function (for example, `chord.trackProductClicked(props))`, and `event`, which is the finished event payload Chord has constructed to send to the CDP.

| Method                | Type                                                                                   | Description                                              |
| --------------------- | -------------------------------------------------------------------------------------- | -------------------------------------------------------- |
| `cartViewed`          | `(props: CartViewedInput, event: CartViewed) => CartViewed`                            | Event triggered when a cart is viewed.                   |
| `checkoutStarted`     | `(props: CheckoutStartedInput, event: CheckoutStarted) => CheckoutStarted`             | Event triggered when the checkout process starts.        |
| `couponApplied`       | `(props: CouponAppliedInput, event: CouponApplied) => CouponApplied`                   | Event triggered when a coupon is successfully applied.   |
| `couponDenied`        | `(props: CouponDeniedInput, event: CouponDenied) => CouponDenied`                      | Event triggered when a coupon is denied.                 |
| `couponEntered`       | `(props: CouponEnteredInput, event: CouponEntered) => CouponEntered`                   | Event triggered when a coupon code is entered.           |
| `couponRemoved`       | `(props: CouponRemovedInput, event: CouponRemoved) => CouponRemoved`                   | Event triggered when a coupon is removed.                |
| `emailCaptured`       | `(props: EmailCapturedInput, event: EmailCaptured) => EmailCaptured`                   | Event triggered when an email is captured.               |
| `productAdded`        | `(props: ProductAddedInput, event: ProductAdded) => ProductAdded`                      | Event triggered when a product is added to the cart.     |
| `productClicked`      | `(props: ProductClickedInput, event: ProductClicked) => ProductClicked`                | Event triggered when a product is clicked.               |
| `productListFiltered` | `(props: ProductListFilteredInput, event: ProductListFiltered) => ProductListFiltered` | Event triggered when a product list is filtered.         |
| `productListViewed`   | `(props: ProductListViewedInput, event: ProductListViewed) => ProductListViewed`       | Event triggered when a product list is viewed.           |
| `productRemoved`      | `(props: ProductRemovedInput, event: ProductRemoved) => ProductRemoved`                | Event triggered when a product is removed from the cart. |
| `productViewed`       | `(props: ProductViewedInput, event: ProductViewed) => ProductViewed`                   | Event triggered when a product is viewed.                |
| `productsSearched`    | `(props: ProductsSearchedInput, event: ProductsSearched) => ProductsSearched`          | Event triggered when products are searched.              |
| `signedIn`            | `(props: SignedInInput, event: SignedIn) => SignedIn`                                  | Event triggered when a user signs in.                    |
| `signedOut`           | `(props: SignedOutInput, event: SignedOut) => SignedOut`                               | Event triggered when a user signs out.                   |
| `signedUp`            | `(props: SignedUpInput, event: SignedUp) => SignedUp`                                  | Event triggered when a user signs up.                    |

#### Example event formatter

In this example, let's add an additional property to the "Signed In" event to track whether the user signed in by clicking the yellow button or the purple button.

The code used to send "Signed In" looks like this:

```typescript
chord.trackSignedIn({ email: 'hello@chord.co', button: 'purple' }) 
```

As written, Chord will ignore the `button` property and not include it in the event sent to the CDP, because it's not part of Chord's tracking plan. To include the `button` property in the event, add an event formatter:

```typescript
import { CartInput, Cart, ChordAnalytics } from '@chordcommerce/analytics'

const signedInFormatter: (props: SignedInInput, event: SignedIn) => SignedIn = (props, event) => {
  return {
    ...event,
    button: props.button
  }
}

const chord = new ChordAnalytics({
  ...
  formatters: {
    events: {
      signedIn: signedInFormatter,
      ...
    },
  }
})
```

## TypeScript support

The library accepts generic type parameters for your own data types:

```typescript
interface MyObjectTypes {
  Cart: MyCartType
  Checkout: MyCheckoutType
  LineItem: MyLineItemType
  Product: MyProductType
}

const chord = new ChordAnalytics<MyObjectTypes>(options)

// chord.trackProductViewed now expects { product: MyProductType }
```

Formatter types take the same parameters, so each formatter is checked against your data type:

```typescript
import type { CartFormatter, ProductFormatter } from '@chordcommerce/analytics'

const cartFormatter: CartFormatter<MyCartType> = ({ cart }) => {
  // `cart` is typed as MyCartType
  return { /* ... */ }
}
```

## More

* [Custom events](/collect-data/everyone-else/sdk-reference/custom-events.md): sending events that aren't in the tracking plan, and how destinations handle them.
* [Context object](/collect-data/everyone-else/sdk-reference/context-object.md): the environment data attached to every event.


---

# 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/collect-data/everyone-else/sdk-reference.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.
