# Web SDK+ Integration Guide

> Product: Rokt Ecommerce
>
> Intended implementer: Rokt Ecommerce partner
>
> Integration surface: The partner’s owned website, app, or transaction experience
>
> Not intended for: Advertisers implementing Rokt Ads
>
> Canonical documentation: [https://docs.rokt.com/integration-guides/ecommerce/sdk/web/](https://docs.rokt.com/integration-guides/ecommerce/sdk/web/)
>
> This is a complete machine-readable guide generated from the same MDX source as the rendered documentation. Read the complete guide before implementing the integration, and do not edit this generated file directly.

These SDK+ integration guides are for Rokt Ecommerce partners—ecommerce businesses integrating Rokt into transaction experiences they own, including websites, apps, carts, checkouts, payment pages, and confirmation flows.
They are not implementation guides for advertisers using Rokt Ads to acquire customers across the Rokt Network. References to advertiser offers describe content rendered within an ecommerce partner’s owned experience. Advertisers should use the [Rokt Ads integration guides](https://docs.rokt.com/integration-guides/ads/).

This page explains how to implement the Rokt Ecommerce Web SDK+. The SDK+ passes user and transaction data to Rokt on configured pages so Rokt can render relevant experiences, such as offers on confirmation pages.

## 1. Initialize the Rokt SDK+

Include the SDK+ initialization script on every page of your site. Browser caching means the SDK+ loads from cache on subsequent pages rather than re-fetching.

**For single-page apps:** Insert the script into the head of your main `index.html`, or wherever your content is rendered.

**For multi-page apps:** Place the script in your primary shared layout file. If you don't use a template-based rendering system, add it to each HTML file.

> **Note: First-Party Domain Configuration**
>
> Using a first-party domain when integrating the Web SDK+ into your site ensures that the SDK+ uses your own domain when making calls to Rokt's API, providing your customers with a seamless experience and minimizing the risk of blocked content. To learn how to configure a first-party domain for your SDK+ integration, see [First Party Domain Integration](https://docs.rokt.com/developer-reference/sdks/web-sdk/first-party-domains/).

### Rokt Web SDK+ initialization

```html
<script type="text/javascript">

// Enter your Rokt API key
const API_KEY = "YOUR_API_KEY";

// Enter your custom subdomain if you are using a first-party domain configuration (optional)
const ROKT_DOMAIN = "https://apps.rokt-api.com";

window.mParticle = {
  config: {
      // Set the data environment:
      // Set isDevelopmentMode to true if you are still testing your integration. 
      // Set isDevelopmentMode to false if your integration is ready for production data.
      isDevelopmentMode: true,
      // Identify the current user:
      // If you do not have the user's email address, you can pass in a null value
      identifyRequest: {
          userIdentities: {
              // If you're using an un-hashed email address, set it in 'email' (preferred).
              email: 'j.smith@example.com',
              // If you're using a hashed email address, set it in 'email_sha256' instead of 'email'.
              email_sha256: 'sha256 hashed email goes here',
              // Customer phone number in E.164 format.
              mobile_number: '+13125551515',
              // If you're using a hashed mobile number, set it in 'mobile_sha256' instead of 'mobile_number'.
              mobile_sha256: 'sha256 hashed mobile goes here',
              // Partner's internal customer/account identifier (if the user is logged in).
              customerid: 'cust_10482'
          }
      },
      // If the user is identified with their email address, set additional user attributes.
      identityCallback: function(result) {
          if (result.getUser()) {
              result.getUser().setUserAttribute('attribute_key', 'attribute_value');
          }
      }
  }
};

// Load the SDK+
(function(e) { window.mParticle = window.mParticle || {}; window.mParticle.EventType = { Unknown: 0, Navigation: 1, Location: 2, Search: 3, Transaction: 4, UserContent: 5, UserPreference: 6, Social: 7, Other: 8, Media: 9 }; window.mParticle.eCommerce = { Cart: {} }; window.mParticle.Identity = {}; window.mParticle.Rokt = {}; window.mParticle.config = window.mParticle.config || {}; window.mParticle.config.rq = []; window.mParticle.config.snippetVersion = 2.8; window.mParticle.ready = function(e) { window.mParticle.config.rq.push(e); }; ["endSession", "logError", "logBaseEvent", "logEvent", "logForm", "logLink", "logPageView", "setSessionAttribute", "setAppName", "setAppVersion", "setOptOut", "setPosition", "startNewSession", "startTrackingLocation", "stopTrackingLocation"].forEach(function(e) { window.mParticle[e] = function() { var t = Array.prototype.slice.call(arguments); t.unshift(e); window.mParticle.config.rq.push(t); }; }); ["setCurrencyCode", "logCheckout"].forEach(function(e) { window.mParticle.eCommerce[e] = function() { var t = Array.prototype.slice.call(arguments); t.unshift("eCommerce." + e); window.mParticle.config.rq.push(t); }; }); ["identify", "login", "logout", "modify"].forEach(function(e) { window.mParticle.Identity[e] = function() { var t = Array.prototype.slice.call(arguments); t.unshift("Identity." + e); window.mParticle.config.rq.push(t); }; }); ["selectPlacements","hashAttributes","hashSha256","setExtensionData","use","getVersion","terminate","onShoppableAdsReady"].forEach(function(e) { window.mParticle.Rokt[e] = function() { var t = Array.prototype.slice.call(arguments); t.unshift("Rokt." + e); window.mParticle.config.rq.push(t); }; }); var t = window.mParticle.config.isDevelopmentMode ? 1 : 0, n = "?env=" + t, a = window.mParticle.config.dataPlan; if (a) { var o = a.planId, r = a.planVersion; o && (r && (r < 1 || r > 1e3) && (r = null), n += "&plan_id=" + o + (r ? "&plan_version=" + r : "")); } var i = window.mParticle.config.versions, s = []; i && Object.keys(i).forEach(function(e) { s.push(e + "=" + i[e]); }); var c = document.createElement("script"); c.type = "text/javascript"; c.async = !0; window.ROKT_DOMAIN = ROKT_DOMAIN || 'https://apps.rokt-api.com'; mParticle.config.domain = ROKT_DOMAIN.split('//')[1]; c.src = ROKT_DOMAIN + "/js/v2/" + e + "/app.js" + n + "&" + s.join("&"); c.onerror = function() { var u = ["https://apps.","rokt","ecommerce",".com"].join(""); window.ROKT_DOMAIN = u; mParticle.config.domain = u.split("//")[1]; var d = document.createElement("script"); d.type = "text/javascript"; d.async = !0; d.src = u + "/js/v2/" + e + "/app.js" + n + "&" + s.join("&"); var f = document.getElementsByTagName("script")[0]; f.parentNode.insertBefore(d, f); }; var l = document.getElementsByTagName("script")[0]; l.parentNode.insertBefore(c, l); })(API_KEY);
</script>
```

When inserting the initialization script into your site, you will see customizable fields for:

### 1. Entering your Rokt API key

Set `API_KEY` to the Rokt API key provided by your Rokt account manager.

### 2. Entering a custom first-party domain

Follow the instructions in [First-Party Domain Configuration](https://docs.rokt.com/developer-reference/sdks/web-sdk/first-party-domains/), and set `ROKT_DOMAIN` to your custom subdomain. Routing the Rokt SDK+ through your own domain reduces the risk of ad blockers and browsers from blocking ads or data.

### 3. Setting your data environment

Set `isDevelopmentMode` to `true` while testing to route data to the Development environment, and `false` to send live customer activity to Production.

### 4. Identifying your user and setting attributes

In `identifyRequest`, pass the user's raw, un-hashed email in the `email` field. Include `mobile_number` and `customerid` when available — more signals improve identity resolution. Once identified, use the `identityCallback` to set additional user attributes. For a list of recommended attributes, see [User attributes](https://docs.rokt.com/integration-guides/ecommerce/sdk/web/#user-attributes).

#### identityCallback

```javascript
// The identityCallback determines if the identifyRequest was successful.
identityCallback: function(result) {
    if (result.getUser()) {
        // If the user was identified, set additional user attributes with setUserAttribute.
        result.getUser().setUserAttribute('attribute_key', 'attribute_value');
    }
}
```

> **Note**
>
> Always include `identifyRequest` in the initialization script. If you don't have the user's email at initialization, set `email` to `null` — the SDK+ will still initialize, and you can identify the user later via [Step 2](https://docs.rokt.com/integration-guides/ecommerce/sdk/web/#identify).

## 2. Identify the User

The [SDK+ initialization script](https://docs.rokt.com/integration-guides/ecommerce/sdk/web/#initialize) identifies the current user using the identifiers you provided in the script's `identifyRequest` object. After SDK initialization, you should keep the user's identity in sync whenever they log in, log out, or otherwise provide an identifier (for example, during checkout) using the appropriate method as described below.

### Supported user identifiers

### Show supported user identifiers

| Field           | Type   | Description                                                                                          |
| --------------- | ------ | ---------------------------------------------------------------------------------------------------- |
| `email`         | string | Raw, unhashed email address.                                                                         |
| `email_sha256`  | string | SHA-256 hashed email. Use instead of `email` when only the hashed form is available.                 |
| `mobile_sha256` | string | SHA-256 hashed mobile number. Use instead of `mobile_number` when only the hashed form is available. |
| `mobile_number` | string | Phone number in E.164 format (e.g. `+13125551515`).                                                  |
| `customerid`    | string | Internal customer/account identifier. Send on every page for logged-in users.                        |

To identify the user:

### 1. Create an identifyRequest object

Create an `identifyRequest` object to contain the user's identifiers. You should integrate the user's raw, unhashed email address into the `email` field.

### 2. Create an identityCallback

To set additional user attributes, create an `identityCallback`. If the `identifyRequest` succeeds, then any user attributes you set inside the callback are assigned to the identified user.

### 3. Send the request using the method that matches the user's action

Pass the `identifyRequest` (and optional `identityCallback`) to the method that matches the user's action:

- **`mParticle.Identity.login`:** call when the user logs in or creates an account.
- **`mParticle.Identity.identify`:** call when you obtain the user's email mid-session without a login transition (for example, a guest enters their email at checkout).
- **`mParticle.Identity.logout`:** call when the user logs out.

Calling these methods transitions the SDK's record of the current user's state. The `login` and `logout` methods also automatically log a corresponding event to improve Rokt's attribution.

For example, to identify a user named Jane Smith with the email address `j.smith@example.com`, mobile number `+13125551515`, and customer ID `cust_10482`:

#### Example user identification

```javascript
// 1. Create the identifyRequest object
const identifyRequest = {
  userIdentities: {
      email: 'j.smith@example.com',
      // If you are passing a hashed email address, set it inside the 'email_sha256' field instead of 'email'.
      email_sha256: 'SHA-256 hashed email address',
      mobile_number: '+13125551515',
      // If you are passing a hashed mobile number, set it inside the 'mobile_sha256' field instead of 'mobile_number'.
      mobile_sha256: 'SHA-256 hashed mobile number',
      customerid: 'cust_10482'
  }
};
// 2. User attributes are set using identityCallback
const identityCallback = function(result) {
  if (result.getUser()) {
      result.getUser().setUserAttribute('firstname', 'Jane');
      result.getUser().setUserAttribute('lastname', 'Smith');
  }
};
// 3. Call one of the following methods that best matches the user's action:
mParticle.Identity.login(identifyRequest, identityCallback); // Call when the user logs in or creates an account
mParticle.Identity.identify(identifyRequest, identityCallback); // Call when you obtain the user's email mid-session, but not during a login
mParticle.Identity.logout({}); // Call when the user logs out
```

## 3. Set User Attributes

Set user attributes progressively throughout the complete customer journey, not just at checkout. The more attributes you set, the better Rokt can resolve the customer's identity and deliver relevant offers.

> **Tip: Set attributes as early as possible**
>
> Set new user attributes as they become available. Earlier attribute collection gives Rokt more signals with which to improve the speed and relevance of placements rendered on the confirmation page.

### Set User Attributes

```javascript
// To retrieve the current user, call getCurrentUser.
const currentUser = mParticle.Identity.getCurrentUser();

// Once you have successfully set the current user to a const called `currentUser`, you can set user attributes with:
currentUser.setUserAttribute("firstname", "Jane");
currentUser.setUserAttribute("lastname", "Smith");
currentUser.setUserAttribute("mobile_number", "+13125551515");
currentUser.setUserAttribute("birthyear", 1990);
currentUser.setUserAttribute("gender", "F");

// Address attributes (collect the billing address at checkout)
currentUser.setUserAttribute("billingaddress1", "123 Main St");
currentUser.setUserAttribute("billingaddress2", "Apt 4B");
currentUser.setUserAttribute("billingcity", "Brooklyn");
currentUser.setUserAttribute("billingstate", "NY");
currentUser.setUserAttribute("billingzipcode", "11201");
currentUser.setUserAttribute("country", "US");

// Lifecycle and loyalty attributes
currentUser.setUserAttribute("customertype", "logged_in");
currentUser.setUserAttribute("newcustomer", false);
currentUser.setUserAttribute("loyaltytier", "gold");
currentUser.setUserAttribute("loyaltyid", "LOY-7781");
currentUser.setUserAttribute("customersegment", "vip");

// Marketing attribution
currentUser.setUserAttribute("utmsource", "google");
currentUser.setUserAttribute("utmmedium", "cpc");
currentUser.setUserAttribute("utmcampaign", "spring_sale");

// To set a list attribute, set the value of the attribute to an array of strings. For example:
currentUser.setUserAttribute("favorite_genres", ["documentary", "comedy", "romance", "drama"]);

// To remove a user attribute, call removeUserAttribute and pass in the attribute name. All user attributes share the same key space.
currentUser.removeUserAttribute("attribute_to_remove");
```

### User attributes

Set as many of the following attributes as you can collect.

### Show all user attributes

| Field                | Type    | Description                                                                                                                                    |
| -------------------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
| `firstname`          | string  | Customer's first name. Used for personalization.                                                                                               |
| `lastname`           | string  | Customer's last name. Used for personalization.                                                                                                |
| `mobile_number`      | string  | Phone number formatted as `1112345678` or `+1 (222) 345-6789`. Used for identity resolution and relevance.                                     |
| `birthyear`          | integer | Customer's birth year (e.g. `1990`). Preferred date-of-birth field. Alternates: `dob` (`yyyymmdd`), `age`. Used for eligibility and relevance. |
| `dob`                | string  | Date of birth, `yyyymmdd`. Alternate to `birthyear`. Used for eligibility and relevance.                                                       |
| `age`                | integer | Customer's age. Alternate to `birthyear`. Used for eligibility and relevance.                                                                  |
| `gender`             | string  | Customer's gender. For example, `M`, `F`, `Male`, or `Female`. Used for relevance.                                                             |
| `title`              | string  | Honorific. For example, `Mr`, `Mrs`, `Ms`. Used for personalization.                                                                           |
| `language`           | string  | ISO 639-1 language code associated with the purchase. Used for relevance.                                                                      |
| `billingaddress1`    | string  | Street address (e.g. `123 Main St`). Used for identity resolution and relevance.                                                               |
| `billingaddress2`    | string  | Apartment/unit (e.g. `Apt 4B`). Used for identity resolution.                                                                                  |
| `billingcity`        | string  | Billing city. Used for relevance.                                                                                                              |
| `billingstate`       | string  | Billing state / province / region. Used for relevance and eligibility.                                                                         |
| `billingzipcode`     | string  | Full ZIP or postcode (US preference is ZIP+4). Used for identity resolution and relevance.                                                     |
| `country`            | string  | ISO 3166-1 alpha-2 country code (e.g. `US`, `GB`, `AU`). Used for eligibility and relevance.                                                   |
| `newcustomer`        | boolean | Whether this is a first-time buyer (`true` / `false`). Used for relevance.                                                                     |
| `customertype`       | string  | Whether the user is authenticated (`guest` / `logged_in`). Used for relevance.                                                                 |
| `loyaltytier`        | string  | Partner loyalty program tier. Used for relevance and eligibility.                                                                              |
| `loyaltyid`          | string  | Loyalty program member ID. Used for identity resolution.                                                                                       |
| `predictedltv`       | decimal | Predicted total lifetime value, typically produced by a partner machine-learning model. Used for relevance.                                    |
| `subscriptionstatus` | string  | Subscription state if applicable (`active`, `trial`, `churned`, `paused`, `none`). Used for relevance and eligibility.                         |
| `customersegment`    | string  | Partner internal segmentation (e.g. `vip`, `at_risk`, `new`, `reactivated`). Used for relevance.                                               |
| `acquisitionchannel` | string  | How the customer was originally acquired. Used for relevance.                                                                                  |
| `utmsource`          | string  | Marketing attribution source. Used for relevance.                                                                                              |
| `utmmedium`          | string  | Marketing attribution medium. Used for relevance.                                                                                              |
| `utmcampaign`        | string  | Marketing attribution campaign. Used for relevance.                                                                                            |
| `utmcontent`         | string  | Marketing attribution content variant. Used for relevance.                                                                                     |
| `utmterm`            | string  | Marketing attribution term / keyword. Used for relevance.                                                                                      |
| `referrer`           | string  | Referring URL — intent signal. Used for relevance.                                                                                             |

> **Note**
>
> All user attributes (including list attributes and tags) must have distinct names.

## 4. Log Events

Log page views, commerce events, and custom events so Rokt can understand where each customer is in their journey.

### Event category: Page view

Page views tell Rokt which page the customer is on. Wrap each call in `mParticle.ready()` so it fires after the SDK+ initializes. On transactional pages (PLP, PDP, cart, checkout, confirmation), also fire the matching commerce event from **Commerce events** to send product- and order-level details.

#### Page type: home

Log this when the customer lands on your site's home page, including empty-path roots like `/`.

| Field           | Type   | Description                                                                                               |
| --------------- | ------ | --------------------------------------------------------------------------------------------------------- |
| `screenname`    | string | Last segment of the URL path (e.g. `/products/shoes` → `shoes`). Defaults to `home` if the path is empty. |
| `pagetype`      | string | Type of page being viewed: `home`, `PLP`, `PDP`, `cart`, `checkout`, `confirmation`.                      |
| `url`           | string | Full URL of the current page.                                                                             |
| `title`         | string | Page title (from `document.title`).                                                                       |
| `sitesection`   | string | Top-level site section (e.g. `mens`, `womens`, `support`).                                                |
| `referringpage` | string | Referring URL captured from `document.referrer`.                                                          |

##### Example home page view

```javascript
window.mParticle.ready(function() {
mParticle.logPageView("page_view", {
  screenname: "home",
  pagetype: "home",
  url: window.location.toString(),
  title: document.title,
  sitesection: "root",
  referringpage: document.referrer
});
});
```

#### Page type: PLP

Log this on a product listing page (PLP): a category, collection, or search-results page where the customer is browsing multiple products at once.

| Field           | Type   | Description                                                                                               |
| --------------- | ------ | --------------------------------------------------------------------------------------------------------- |
| `screenname`    | string | Last segment of the URL path (e.g. `/products/shoes` → `shoes`). Defaults to `home` if the path is empty. |
| `pagetype`      | string | Type of page being viewed: `home`, `PLP`, `PDP`, `cart`, `checkout`, `confirmation`.                      |
| `url`           | string | Full URL of the current page.                                                                             |
| `title`         | string | Page title (from `document.title`).                                                                       |
| `sitesection`   | string | Top-level site section (e.g. `mens`, `womens`, `support`).                                                |
| `referringpage` | string | Referring URL captured from `document.referrer`.                                                          |

##### Example PLP page view

```javascript
window.mParticle.ready(function() {
mParticle.logPageView("page_view", {
  screenname: "shoes",
  pagetype: "PLP",
  url: window.location.toString(),
  title: document.title,
  sitesection: "mens",
  referringpage: document.referrer
});
});
```

#### Page type: PDP

Log this on a product detail page (PDP) when the customer opens a single product to view its details, price, and options.

| Field           | Type   | Description                                                                                               |
| --------------- | ------ | --------------------------------------------------------------------------------------------------------- |
| `screenname`    | string | Last segment of the URL path (e.g. `/products/shoes` → `shoes`). Defaults to `home` if the path is empty. |
| `pagetype`      | string | Type of page being viewed: `home`, `PLP`, `PDP`, `cart`, `checkout`, `confirmation`.                      |
| `url`           | string | Full URL of the current page.                                                                             |
| `title`         | string | Page title (from `document.title`).                                                                       |
| `sitesection`   | string | Top-level site section (e.g. `mens`, `womens`, `support`).                                                |
| `referringpage` | string | Referring URL captured from `document.referrer`.                                                          |

##### Example PDP page view

```javascript
window.mParticle.ready(function() {
mParticle.logPageView("page_view", {
  screenname: "trail-runner-v3",
  pagetype: "PDP",
  url: window.location.toString(),
  title: document.title,
  sitesection: "mens",
  referringpage: document.referrer
});
});
```

#### Page type: cart

Log this when the customer opens the cart page to review the items they've added.

| Field           | Type   | Description                                                                                               |
| --------------- | ------ | --------------------------------------------------------------------------------------------------------- |
| `screenname`    | string | Last segment of the URL path (e.g. `/products/shoes` → `shoes`). Defaults to `home` if the path is empty. |
| `pagetype`      | string | Type of page being viewed: `home`, `PLP`, `PDP`, `cart`, `checkout`, `confirmation`.                      |
| `url`           | string | Full URL of the current page.                                                                             |
| `title`         | string | Page title (from `document.title`).                                                                       |
| `sitesection`   | string | Top-level site section (e.g. `mens`, `womens`, `support`).                                                |
| `referringpage` | string | Referring URL captured from `document.referrer`.                                                          |

##### Example cart page view

```javascript
window.mParticle.ready(function() {
mParticle.logPageView("page_view", {
  screenname: "cart",
  pagetype: "cart",
  url: window.location.toString(),
  title: document.title,
  sitesection: "checkout",
  referringpage: document.referrer
});
});
```

#### Page type: checkout

Log this when the customer enters the checkout flow to finalize their order, entering shipping, billing, or payment details.

| Field           | Type   | Description                                                                                               |
| --------------- | ------ | --------------------------------------------------------------------------------------------------------- |
| `screenname`    | string | Last segment of the URL path (e.g. `/products/shoes` → `shoes`). Defaults to `home` if the path is empty. |
| `pagetype`      | string | Type of page being viewed: `home`, `PLP`, `PDP`, `cart`, `checkout`, `confirmation`.                      |
| `url`           | string | Full URL of the current page.                                                                             |
| `title`         | string | Page title (from `document.title`).                                                                       |
| `sitesection`   | string | Top-level site section (e.g. `mens`, `womens`, `support`).                                                |
| `referringpage` | string | Referring URL captured from `document.referrer`.                                                          |

##### Example checkout page view

```javascript
window.mParticle.ready(function() {
mParticle.logPageView("page_view", {
  screenname: "checkout",
  pagetype: "checkout",
  url: window.location.toString(),
  title: document.title,
  sitesection: "checkout",
  referringpage: document.referrer
});
});
```

#### Page type: confirmation

Log this on the order confirmation page after a successful purchase. This is the primary surface where Rokt renders post-transaction offers.

| Field           | Type   | Description                                                                                               |
| --------------- | ------ | --------------------------------------------------------------------------------------------------------- |
| `screenname`    | string | Last segment of the URL path (e.g. `/products/shoes` → `shoes`). Defaults to `home` if the path is empty. |
| `pagetype`      | string | Type of page being viewed: `home`, `PLP`, `PDP`, `cart`, `checkout`, `confirmation`.                      |
| `url`           | string | Full URL of the current page.                                                                             |
| `title`         | string | Page title (from `document.title`).                                                                       |
| `sitesection`   | string | Top-level site section (e.g. `mens`, `womens`, `support`).                                                |
| `referringpage` | string | Referring URL captured from `document.referrer`.                                                          |

##### Example confirmation page view

```javascript
window.mParticle.ready(function() {
mParticle.logPageView("page_view", {
  screenname: "order-10482",
  pagetype: "confirmation",
  url: window.location.toString(),
  title: document.title,
  sitesection: "checkout",
  referringpage: document.referrer
});
});
```

### Event category: Commerce events

Commerce events carry product-level details for each step of the customer journey. Trigger a separate commerce event for each product action the customer takes.

> **Note**
>
> Commerce-event attributes use flatcase (e.g. `cartitems`, `productsku`, `itemprice`). The `createProduct` method and `transactionAttributes` object use PascalCase (e.g. `Name`, `SKU`, `Id`). Both conventions appear in the sub-sections below.

Tracking a commerce event takes three phases:

#### 1. Define the product

Build a product with `mParticle.eCommerce.createProduct`. The positional arguments cover name, SKU, price, quantity, variant, category, brand, and position.

##### Define a product

```javascript
const product = mParticle.eCommerce.createProduct(
'Double Room - Econ Rate', // Name
'econ-1',                  // SKU
100.00,                    // Price
4,                         // Quantity
'standard',                // Variant
'room',                    // Category
'lodge-o-rama'             // Brand
);
```

#### 2. Summarize the transaction

Build a `transactionAttributes` object for `Purchase`, `Checkout`, and `CheckoutOption` events. Use PascalCase keys (`Id`, `Revenue`, `Tax`, `Shipping`, `Coupon`). Order-level coupons belong here, not on individual products.

##### Summarize the transaction

```javascript
const transactionAttributes = {
Id:       'ORDER-12345',
Revenue:  149.99,
Tax:      12.50,
Shipping: 5.99,
Coupon:   'SUMMER20'
};
```

#### 3. Log the commerce event

Call `mParticle.eCommerce.logProductAction`, passing the product action type, your product(s), event-level attributes, optional custom flags, and (when applicable) the `transactionAttributes`. For impressions, call `mParticle.eCommerce.logImpression` instead. Pick the customer action you want to log:

##### Commerce event: PLP impression

Log a product listing page (or category page) view as a product impression. Pass every visible product in a single call, and set the impression's `Name` to the list / category name (Rokt uses this as `listname`).

| Field      | Type   | Required | Description                                                                         |
| ---------- | ------ | -------- | ----------------------------------------------------------------------------------- |
| `Name`     | string | yes      | List or category name (e.g. `"Mens Running Shoes"`). Becomes `listname`.            |
| `Products` | array  | yes      | Product objects from `createProduct`. Set `Position` to each item's 1-indexed rank. |
| `currency` | string | yes      | ISO 4217 currency code (passed as event-level customAttribute).                     |

###### Example PLP impression

```javascript
// Position (8th positional arg) is the 1-indexed rank in the list.
const product = mParticle.eCommerce.createProduct(
'Trail Runner v3', // Name
'SKU-001',         // SKU
129.95,            // Price
null, null,        // Quantity, Variant
'Shoes',           // Category
'BrandX',          // Brand
1                  // Position in list
);

mParticle.eCommerce.logImpression(
{ Name: 'Mens Running Shoes', Product: [product] }, // Name -> listname
{ currency: 'USD' }                                  // event-level attrs
);
```

##### Commerce event: ViewDetail

Log when a customer opens a product detail page.

| Field         | Type    | Required | Description                         |
| ------------- | ------- | -------- | ----------------------------------- |
| `productsku`  | string  | yes      | Product SKU.                        |
| `productname` | string  | yes      | Display name.                       |
| `itemprice`   | decimal | yes      | Per-unit price at the time of view. |
| `currency`    | string  | yes      | ISO 4217 currency code.             |
| `listname`    | string  | no       | Set if the user arrived from a PLP. |

###### Example ViewDetail event

```javascript
const product = mParticle.eCommerce.createProduct(
'Trail Runner v3', // Name
'SKU-001',         // SKU
129.95,            // Price
1                  // Quantity
);

mParticle.eCommerce.logProductAction(
mParticle.ProductActionType.ViewDetail,
[product],
{ currency: 'USD', listname: 'PLP-Running' }, // event-level attrs
null,                                          // custom flags
null                                           // no transactionAttributes
);
```

##### Commerce event: AddToCart

Log when a customer adds an item to the cart.

| Field        | Type    | Required | Description                                 |
| ------------ | ------- | -------- | ------------------------------------------- |
| `productsku` | string  | yes      | Product SKU.                                |
| `quantity`   | integer | yes      | Units added.                                |
| `itemprice`  | decimal | yes      | Per-unit price at time of add.              |
| `currency`   | string  | yes      | ISO 4217 currency code.                     |
| `couponCode` | string  | no       | Order-level coupon, if applied at add-time. |

###### Example AddToCart event

```javascript
const product = mParticle.eCommerce.createProduct(
'Trail Runner v3', // Name
'SKU-001',         // SKU
129.95,            // Price
1                  // Quantity
);

mParticle.eCommerce.logProductAction(
mParticle.ProductActionType.AddToCart,
[product],
{ currency: 'USD' },
null,
null
);
```

##### Commerce event: RemoveFromCart

Log when a customer removes an item from the cart.

| Field        | Type    | Required | Description             |
| ------------ | ------- | -------- | ----------------------- |
| `productsku` | string  | yes      | Product SKU.            |
| `quantity`   | integer | yes      | Units removed.          |
| `currency`   | string  | yes      | ISO 4217 currency code. |

###### Example RemoveFromCart event

```javascript
const product = mParticle.eCommerce.createProduct(
'Trail Runner v3', // Name
'SKU-001',         // SKU
129.95,            // Price
1                  // Quantity removed
);

mParticle.eCommerce.logProductAction(
mParticle.ProductActionType.RemoveFromCart,
[product],
{ currency: 'USD' },
null,
null
);
```

##### Commerce event: Cart page view

Log when the customer arrives on the cart page. Since cart page views do not have a native `ProductActionType`, use `mParticle.logEvent` with the event name `"view_cart"` and `EventType.Other`. Pass the full cart contents as event attributes.

| Field           | Type      | Required | Description                                                |
| --------------- | --------- | -------- | ---------------------------------------------------------- |
| `event_name`    | string    | yes      | Always `"view_cart"`.                                      |
| `event_type`    | EventType | yes      | Use `mParticle.EventType.Other`.                           |
| `cartitems`     | array     | yes      | Full cart contents as a real JSON array (don't stringify). |
| `cartitemcount` | integer   | yes      | Number of cart lines.                                      |
| `totalprice`    | decimal   | yes      | Cart total.                                                |
| `currency`      | string    | yes      | ISO 4217 currency code.                                    |
| `couponcode`    | string    | no       | Order-level promo, if applied.                             |

#### Cart items

Each entry in the `cartitems` array has the following shape:

| Field             | Type    | Description                                                                                                                                                                                      |
| ----------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `cartitemid`      | string  | Stable partner-side cart-line identifier. Usually equals `productsku` when there is one line per SKU; use a unique value if you allow multiple lines for the same SKU (e.g. gift-wrap variants). |
| `productsku`      | string  | Product SKU / stock identifier.                                                                                                                                                                  |
| `productname`     | string  | Product display name.                                                                                                                                                                            |
| `productcategory` | string  | Product category / taxonomy leaf.                                                                                                                                                                |
| `productbrand`    | string  | Product brand.                                                                                                                                                                                   |
| `productvariant`  | string  | Variant identifier (size, color, etc.).                                                                                                                                                          |
| `itemprice`       | decimal | Per-unit price at event time.                                                                                                                                                                    |
| `unitprice`       | decimal | Per-unit list price pre-discount. Omit if equal to `itemprice`.                                                                                                                                  |
| `quantity`        | integer | Units in this line.                                                                                                                                                                              |
| `currency`        | string  | ISO 4217 code. Omit if matches the top-level currency.                                                                                                                                           |
| `couponcode`      | string  | Coupon applied to this line (if any). Order-level promos belong in `transactionAttributes.Coupon`.                                                                                               |
| `productposition` | integer | 1-indexed rank of the product within a list or search results.                                                                                                                                   |

> **Note**
>
> Do not send cart items as comma-separated strings or as a stringified JSON blob. Send a real JSON array so the fields stay typed.

###### Example cart page view event

```javascript
mParticle.logEvent(
"view_cart",
mParticle.EventType.Other,
{
  cartitemcount: 3,
  totalprice: 169.85,
  currency: "USD",
  couponcode: "SUMMER20",
  cartitems: [
    { cartitemid: "SKU-001", productsku: "SKU-001", productname: "Trail Runner v3", itemprice: 129.95, quantity: 1 },
    { cartitemid: "SKU-002", productsku: "SKU-002", productname: "Cushion Insole",  itemprice: 19.95,  quantity: 2 }
  ]
}
);
```

##### Commerce event: Checkout

Log when the customer enters the checkout flow. Send the full `cartitems` array along with cart-level totals.

| Field           | Type    | Required | Description                     |
| --------------- | ------- | -------- | ------------------------------- |
| `cartitems`     | array   | yes      | Full cart contents.             |
| `totalprice`    | decimal | yes      | Cart total before tax/shipping. |
| `cartitemcount` | integer | yes      | Number of cart lines.           |
| `currency`      | string  | yes      | ISO 4217 currency code.         |
| `couponCode`    | string  | no       | Order-level promo, if applied.  |

###### Example Checkout event

```javascript
const product1 = mParticle.eCommerce.createProduct('Trail Runner v3', 'SKU-001', 129.95, 1);
const product2 = mParticle.eCommerce.createProduct('Cushion Insole',  'SKU-002', 19.95, 2);

mParticle.eCommerce.logProductAction(
mParticle.ProductActionType.Checkout,
[product1, product2],
{
  currency: 'USD',
  cartitemcount: 3,
  totalprice: 169.85,
  couponCode: 'SUMMER20'
},
null,
null
);
```

##### Commerce event: CheckoutOption (shipping)

Log when the customer completes the shipping step. Pass `option: 'shipping'` along with the shipping selections.

| Field            | Type    | Required | Description                          |
| ---------------- | ------- | -------- | ------------------------------------ |
| `cartitems`      | array   | yes      | Full cart contents.                  |
| `option`         | string  | yes      | Always `"shipping"` for this event.  |
| `shippingmethod` | string  | yes      | `standard` / `express` / `next_day`. |
| `zipcode`        | string  | yes      | Shipping ZIP / postcode.             |
| `country`        | string  | yes      | ISO 3166-1 alpha-2 country code.     |
| `totalprice`     | decimal | yes      | Cart total.                          |
| `currency`       | string  | yes      | ISO 4217 currency code.              |

###### Example CheckoutOption (shipping) event

```javascript
const product1 = mParticle.eCommerce.createProduct('Trail Runner v3', 'SKU-001', 129.95, 1);
const product2 = mParticle.eCommerce.createProduct('Cushion Insole',  'SKU-002', 19.95, 2);

mParticle.eCommerce.logProductAction(
mParticle.ProductActionType.CheckoutOption,
[product1, product2],
{
  option: 'shipping',
  shippingmethod: 'express',
  zipcode: '94103',
  country: 'US',
  totalprice: 169.85,
  currency: 'USD'
},
null,
null
);
```

##### Commerce event: CheckoutOption (payment)

Log when the customer completes the payment step. Pass `option: 'payment'` along with the payment method selected.

| Field                    | Type    | Required | Description                                        |
| ------------------------ | ------- | -------- | -------------------------------------------------- |
| `cartitems`              | array   | yes      | Full cart contents.                                |
| `option`                 | string  | yes      | Always `"payment"` for this event.                 |
| `paymenttype`            | string  | yes      | `credit_card` / `paypal` / `apple_pay` / etc.      |
| `payment_method`         | string  | no       | Specific method when relevant (e.g. card brand).   |
| `paymentServiceProvider` | string  | no       | PSP identifier (e.g. `stripe`). Must be camelCase. |
| `ccbin`                  | string  | no       | First 6-8 digits of the card, if a card was used.  |
| `totalprice`             | decimal | yes      | Cart total.                                        |
| `currency`               | string  | yes      | ISO 4217 currency code.                            |

###### Example CheckoutOption (payment) event

```javascript
const product1 = mParticle.eCommerce.createProduct('Trail Runner v3', 'SKU-001', 129.95, 1);
const product2 = mParticle.eCommerce.createProduct('Cushion Insole',  'SKU-002', 19.95, 2);

mParticle.eCommerce.logProductAction(
mParticle.ProductActionType.CheckoutOption,
[product1, product2],
{
  option: 'payment',
  paymenttype: 'credit_card',
  payment_method: 'visa',
  paymentServiceProvider: 'stripe',
  ccbin: '424242',
  totalprice: 169.85,
  currency: 'USD'
},
null,
null
);
```

##### Commerce event: Purchase

Log when an order is confirmed. Send the full `cartitems` array plus a `transactionAttributes` object summarizing the order.

| Field           | Type    | Required | Description                          |
| --------------- | ------- | -------- | ------------------------------------ |
| `cartitems`     | array   | yes      | Full cart contents at time of order. |
| `transactionId` | string  | yes      | Order / transaction identifier.      |
| `totalprice`    | decimal | yes      | Order total (Revenue).               |
| `tax`           | decimal | yes      | Total tax on the order.              |
| `shipping`      | decimal | yes      | Shipping cost.                       |
| `currency`      | string  | yes      | ISO 4217 currency code.              |
| `couponCode`    | string  | no       | Order-level promo, if applied.       |
| `cartitemcount` | integer | no       | Number of cart lines.                |

> **Note**
>
> Order-level coupons belong on `transactionAttributes.CouponCode`. When a single order has multiple SKUs with different promos, attach per-line coupons to the product object as a custom attribute named `couponcode`.

###### Example Purchase event

```javascript
const product1 = mParticle.eCommerce.createProduct('Trail Runner v3', 'SKU-001', 129.95, 1);
const product2 = mParticle.eCommerce.createProduct('Cushion Insole',  'SKU-002', 19.95, 2);

const transactionAttributes = {
Id:       'ORDER-10482',  // transactionId
Revenue:  169.85,         // totalprice (order-level)
Tax:      14.20,          // tax
Shipping: 5.99,           // shipping
CouponCode:   'SUMMER20'      // couponCode (order-level promo)
};

mParticle.eCommerce.logProductAction(
mParticle.ProductActionType.Purchase,
[product1, product2],
{ currency: 'USD', cartitemcount: 3 },
null,
transactionAttributes
);
```

##### Commerce event: Refund

Log when an order (or a line within it) is refunded. Send only the products being refunded, plus a `transactionAttributes` object referencing the original order.

| Field           | Type    | Required | Description                               |
| --------------- | ------- | -------- | ----------------------------------------- |
| `productsku`    | string  | yes      | SKU of the refunded line(s).              |
| `quantity`      | integer | yes      | Units refunded.                           |
| `transactionId` | string  | yes      | Original order ID being refunded against. |
| `totalprice`    | decimal | yes      | Refunded amount.                          |
| `currency`      | string  | yes      | ISO 4217 currency code.                   |

###### Example Refund event

```javascript
const refundedProduct = mParticle.eCommerce.createProduct(
'Trail Runner v3', // Name
'SKU-001',         // SKU
129.95,            // Price
1                  // Quantity refunded
);

const transactionAttributes = {
Id:      'ORDER-10482', // transactionId (original order)
Revenue: 129.95         // totalprice (refunded amount)
};

mParticle.eCommerce.logProductAction(
mParticle.ProductActionType.Refund,
[refundedProduct],
{ currency: 'USD' },
null,
transactionAttributes
);
```

##### Commerce event: Site search

Log when the customer runs a site search. Since site searches do not have a native `ProductActionType`, use `mParticle.logEvent` with the event name `"search"` and `EventType.Search`. Include the search string and the number of results returned.

| Field          | Type      | Required | Description                                |
| -------------- | --------- | -------- | ------------------------------------------ |
| `event_name`   | string    | yes      | Always `"search"`.                         |
| `event_type`   | EventType | yes      | Use `mParticle.EventType.Search`.          |
| `searchstring` | string    | yes      | What the customer typed in the search box. |
| `resultcount`  | integer   | yes      | Number of results returned.                |

###### Example site search event

```javascript
mParticle.logEvent(
"search",
mParticle.EventType.Search,
{
  searchstring: "blue running shoes",
  resultcount: 24
}
);
```

### Event category: Custom event

Track anything else with `mParticle.logEvent`. Pass an event name, an `EventType` that categorizes it, and a free-form attributes object describing what happened.

| Field        | Type      | Required | Description                                                                                                                                                                |
| ------------ | --------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `event_name` | string    | yes      | A name identifying the event (e.g. `"video_play"`, `"newsletter_subscribed"`).                                                                                             |
| `event_type` | EventType | yes      | Categorizes the event. Supported: `Navigation`, `Location`, `Search`, `Transaction`, `UserContent`, `UserPreference`, `Social`, `Other`. Defaults to `Unknown` if omitted. |
| `attributes` | object    | no       | Key-value pairs describing the event. Any string keys and values are supported.                                                                                            |

One custom event Rokt recommends firing is **Ready to Checkout** — log this at the point in the checkout flow where the customer has entered their payment details and is about to confirm the order, but before they click **Place Order** or **Buy Now**. This helps Rokt optimize the selection process so that offers are displayed as quickly as possible on the following page.

Trigger the event once all of the following conditions are met:

- The cart is finalized (items and quantities confirmed).
- A shipping method has been selected.
- A payment method has been entered or selected.
- The user is on the final review/payment screen, prior to order submission.

Include any final attributes that were not available earlier in the session (for example, `payment_method_type`, which is typically only known at this stage).

#### Example custom event: Ready to Checkout

```javascript
window.mParticle.ready(function() {
mParticle.logEvent(
  'Ready to Checkout',
  mParticle.EventType.Transaction,
  {
    checkout_ready: 'true',
    payment_method_type: 'credit_card',
    shipping_address_verified: 'true',
    shippingmethod: 'express',
    cartitemcount: '3',
    cart_total: '430.00',
    currency: 'USD',
  },
);
});
```

## 5. Show a Placement

On every payment and confirmation page where you want Rokt to render content, call `selectPlacements` with one of the supported page identifiers and the customer + transaction attributes. Rokt uses these signals to choose and render the most relevant offer.

Attributes passed in `selectPlacements` override any earlier values set via `setUserAttribute`. Always supply the most recent value.

**Page identifiers**

- `stg.rokt.conf`: A confirmation page in a staging (or testing) environment.
- `prod.rokt.conf`: A confirmation page in a production environment.
- `stg.rokt.payments`: A payments page in a staging (or testing) environment.
- `prod.rokt.payments`: A payments page in a production environment.

Pass the same set of attributes regardless of placement position. The full attribute reference is below.

### Show all placement attributes

| Field                     | Type    | Description                                                                                                                                                                                                                                                                                |
| ------------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `email`                   | string  | Customer email address (unhashed). Used for identity resolution and Shoppable Ads order confirmation.                                                                                                                                                                                      |
| `firstname`               | string  | Customer first name. Used for personalization and Shoppable Ads order fulfillment.                                                                                                                                                                                                         |
| `lastname`                | string  | Customer last name. Used for personalization and Shoppable Ads order fulfillment.                                                                                                                                                                                                          |
| `mobile_number`           | string  | Customer mobile number (E.164 format, e.g. `+13125551515`). Used for identity resolution and Shoppable Ads.                                                                                                                                                                                |
| `confirmationref`         | string  | Order / confirmation reference number. Used for relevance, deduplication, and Shoppable Ads order reconciliation.                                                                                                                                                                          |
| `currency`                | string  | Transaction currency (ISO 4217, e.g. `USD`, `GBP`, `AUD`, `JPY`). Used for relevance and Shoppable Ads.                                                                                                                                                                                    |
| `country`                 | string  | ISO 3166-1 alpha-2 country code. Used for eligibility and relevance.                                                                                                                                                                                                                       |
| `language`                | string  | Customer's preferred language (ISO 639-1, e.g. `en`, `de`, `fr`). Used for relevance.                                                                                                                                                                                                      |
| `totalprice`              | decimal | Total cart value including tax and shipping. Used for relevance.                                                                                                                                                                                                                           |
| `amount`                  | decimal | Cart subtotal before tax and shipping. Distinct from `totalprice`. Required for Pay+ on the payments page; also used by Shoppable Ads.                                                                                                                                                     |
| `cartItems`               | array   | Structured array of cart-line objects. See Cart items reference under Commerce Events. Used for relevance.                                                                                                                                                                                 |
| `couponcode`              | string  | Promo code applied, if any. Used for relevance.                                                                                                                                                                                                                                            |
| `newcustomer`             | boolean | Whether this is a first-time buyer. Used for relevance.                                                                                                                                                                                                                                    |
| `customertype`            | string  | Whether the user is authenticated (`guest` / `logged_in`). Used for relevance.                                                                                                                                                                                                             |
| `value`                   | decimal | Customer cumulative purchase value. Used for relevance.                                                                                                                                                                                                                                    |
| `subscriptionstatus`      | string  | Subscription state if applicable (`active`, `trial`, `churned`, `paused`, `none`). Used for relevance and eligibility.                                                                                                                                                                     |
| `customersegment`         | string  | Partner internal segmentation (`vip`, `at_risk`, `new`, `reactivated`). Used for relevance.                                                                                                                                                                                                |
| `paymenttype`             | string  | Payment method selected (`credit_card`, `paypal`, `apple_pay`, `gift_card`). Used for Pay+ eligibility and Shoppable Ads payment method prioritization.                                                                                                                                    |
| `paymentServiceProvider`  | string  | Comma-separated list of payment methods accepted on the page (e.g. `"cardpayment,paypal"`). Accepted values: `applepay`, `googlepay`, `paypal`, `venmo`, `affirm`, `afterpay`, `klarna`, `alipay`, `amazonpay`, `cardpayment`, `rakutenpay`. Must be camelCase. Used for Pay+ eligibility. |
| `ccbin`                   | string  | Credit card BIN (6-8 digits). Used for relevance.                                                                                                                                                                                                                                          |
| `billingaddress1`         | string  | Billing street address. Used for identity resolution and relevance.                                                                                                                                                                                                                        |
| `billingaddress2`         | string  | Billing apartment/unit. Used for identity resolution.                                                                                                                                                                                                                                      |
| `billingcity`             | string  | Billing city. Used for relevance.                                                                                                                                                                                                                                                          |
| `billingstate`            | string  | Billing state / region. Used for relevance.                                                                                                                                                                                                                                                |
| `billingzipcode`          | string  | Billing ZIP / postcode. Used for identity resolution, relevance, and Shoppable Ads.                                                                                                                                                                                                        |
| `billingname`             | string  | Full cardholder name on the billing address. Used for identity resolution and payment validation.                                                                                                                                                                                          |
| `shippingmethod`          | string  | Shipping method selected (`standard`, `express`, `next_day`). Used for relevance.                                                                                                                                                                                                          |
| `shippingname`            | string  | Full recipient name on the shipping address. Used for Shoppable Ads order fulfillment.                                                                                                                                                                                                     |
| `shippingaddress1`        | string  | Shipping street address. Used for relevance and Shoppable Ads order fulfillment.                                                                                                                                                                                                           |
| `shippingcity`            | string  | Shipping city. Used for relevance and Shoppable Ads order fulfillment.                                                                                                                                                                                                                     |
| `shippingstate`           | string  | Shipping state / region. Used for relevance and Shoppable Ads order fulfillment.                                                                                                                                                                                                           |
| `shippingzipcode`         | string  | Shipping ZIP / postcode. Used for relevance and Shoppable Ads order fulfillment.                                                                                                                                                                                                           |
| `shippingcountry`         | string  | Shipping country (ISO 3166-1 alpha-2). Used for relevance and Shoppable Ads order fulfillment.                                                                                                                                                                                             |
| `partnerpaymentreference` | string  | Non-guessable identifier used to look up the customer's vaulted payment method. Required for Shoppable Ads card forwarding; if absent, card forwarding is unavailable.                                                                                                                     |
| `last4digits`             | string  | Last 4 digits of the card used on the primary transaction. Displayed to the customer for confirmation during Shoppable Ads.                                                                                                                                                                |
| `plcc`                    | string  | `"yes"` or `"no"` — whether the customer has a private-label credit card with the partner. Used for Pay+ relevance.                                                                                                                                                                        |
| `discountamount`          | decimal | Order-level discount applied (e.g. `10.00`). Used for Pay+ relevance.                                                                                                                                                                                                                      |
| `prescreen`               | string  | `"yes"` or `"no"` — whether the customer has pre-qualified for a credit offer. Used for Pay+ relevance.                                                                                                                                                                                    |

> **Note**
>
> Do not send cart items as comma-separated strings or as a stringified JSON blob. Send a real JSON array so the fields stay typed. For the full cart-item field reference, see the Cart items section under Commerce Events.

### Placement position: Overlay

Overlay placements render on top of your confirmation page in a Rokt-managed container, requiring no changes to your page's DOM. Used for standard Thanks Ads and Shoppable Ads.

To insert an overlay placement, call `selectPlacements` once the confirmation page loads:

#### Example overlay selectPlacements call

```javascript
window.mParticle.ready(async function () {
const selection = await window.mParticle.Rokt.selectPlacements({
  identifier: "prod.rokt.conf",
  attributes: {
    // Identity
    email: "j.smith@example.com",
    firstname: "Jenny",
    lastname: "Smith",
    mobile_number: "+13125551515",

    // Transaction
    confirmationref: "ORDER-10482",
    currency: "USD",
    country: "US",
    language: "en",
    totalprice: 149.99,
    couponcode: "SUMMER20",

    // Customer context
    newcustomer: false,
    customertype: "logged_in",
    value: 2340.00,
    subscriptionstatus: "active",
    customersegment: "vip",

    // Payment (include paymenttype + paymentServiceProvider for Pay+)
    paymenttype: "credit_card",
    paymentServiceProvider: "cardpayment",
    ccbin: "411112",

    // Cart contents — see the Placement Attributes reference for the full
    // attribute set and the Cart items reference for the per-line shape.
    cartItems: [
      { cartitemid: "SKU-001", productsku: "SKU-001", productname: "Trail Runner v3", itemprice: 129.95, quantity: 1 }
    ]
  }
});
});
```

### Placement position: Embedded

Embedded placements render inline at a fixed position you control on the page (for example, above the payment options on a cart page). Both Thanks and Pay+ use embedded placements; Pay+ must use embedded placements.

#### 1. Add a placeholder div

Add a `<div>` with the container ID provided by your Rokt account manager at the position where you want the placement to render. Coordinate with your Rokt account manager to choose the container name.

##### Embedded placeholder div

```html
<div id="rokt-{container-name}"></div>
```

#### 2. Call selectPlacements

Call `selectPlacements` with the corresponding page identifier. For SPA navigations, close the placement when the customer leaves the page so it doesn't linger on back-navigation.

##### Example embedded selectPlacements call

```javascript
window.mParticle.ready(async function () {
const selection = await window.mParticle.Rokt.selectPlacements({
  identifier: "prod.rokt.payments",
  attributes: {
    // Identity
    email: "j.smith@example.com",
    firstname: "Jenny",
    lastname: "Smith",
    mobile_number: "+13125551515",

    // Transaction
    currency: "USD",
    country: "US",
    language: "en",
    totalprice: 149.99,
    amount: 129.95,
    couponcode: "SUMMER20",

    // Customer context
    newcustomer: false,
    customertype: "logged_in",
    value: 2340.00,
    subscriptionstatus: "active",
    customersegment: "vip",

    // Payment (paymenttype + paymentServiceProvider required for Pay+)
    paymenttype: "credit_card",
    paymentServiceProvider: "cardpayment",
    ccbin: "411112",

    // Cart contents — see the Placement Attributes reference for the full
    // attribute set and the Cart items reference for the per-line shape.
    cartItems: [
      { cartitemid: "SKU-001", productsku: "SKU-001", productname: "Trail Runner v3", itemprice: 129.95, quantity: 1 }
    ]
  }
});

// For SPA navigations, close the placement when the customer leaves the page.
if (selection) {
  selection.close();
}
});
```

> **Caution: Pay+**
>
> If you are using Pay+, you must close your placement after the user navigates away to prevent it from lingering on back-navigation.

> **Note**
>
> Pay+ requires that your existing confirmation-page `selectPlacements` call already passes `paymenttype` along with the rest of the placement attributes above. Without `paymenttype` on the confirmation page, Rokt cannot attribute share-of-wallet correctly. Validate your confirmation-page integration with your Rokt account manager before enabling Pay+ in production.

### Placement position: Interstitial

Interstitial placements render between the payment and confirmation pages, allowing customers to purchase additional products. Used by Shoppable Ads.

#### 1. Wrap your page content

Wrap your confirmation page content in the `<rokt-thank-you>` tag. Rokt strips the wrapped content when an offer is available and renders the full-screen experience in its place. If no offer is eligible, the wrapped content renders normally.

##### Interstitial wrapper

```html
<body>
<!-- Your header -->
<rokt-thank-you id="rokt-thank-you">
  <!-- Your confirmation page content -->
</rokt-thank-you>
<!-- Your footer -->
</body>
```

#### 2. Call selectPlacements

Call `selectPlacements` with the confirmation-page identifier and include all available placement attributes so Rokt can evaluate eligibility and render the offer.

##### Example interstitial selectPlacements call

```javascript
window.mParticle.ready(async function () {
await window.mParticle.Rokt.selectPlacements({
  identifier: "prod.rokt.conf",   // use stg.rokt.conf in test environments
  attributes: {
    // Identity
    email: "j.smith@example.com",
    firstname: "Jenny",
    lastname: "Smith",
    mobile_number: "+13125551515",

    // Transaction
    confirmationref: "ORDER-10482",
    currency: "USD",
    country: "US",
    language: "en",
    totalprice: 149.99,
    couponcode: "SUMMER20",

    // Customer context
    newcustomer: false,
    customertype: "logged_in",
    value: 2340.00,
    subscriptionstatus: "active",
    customersegment: "vip",

    // Payment
    paymenttype: "credit_card",
    paymentServiceProvider: "cardpayment",
    ccbin: "411112",

    // Cart contents — see the Placement Attributes reference for the full
    // attribute set and the Cart items reference for the per-line shape.
    cartItems: [
      { cartitemid: "SKU-001", productsku: "SKU-001", productname: "Trail Runner v3", itemprice: 129.95, quantity: 1 }
    ]
  }
});
});
```

The `<rokt-thank-you>` wrapper also emits lifecycle events you can subscribe to for custom behavior (covered in a future step).

> **Note**
>
> If your site embeds Rokt inside a cross-origin iframe, add `allow="payment"` to the iframe element so payment APIs work inside the Interstitial experience.

**`<rokt-thank-you>` attributes**

The `<rokt-thank-you>` element accepts the following optional attributes to customize loading behavior:

| Attribute          | Description                                                                                                                                                | Default                |
| ------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------- |
| `loader`           | Optional URL to a loading-indicator GIF displayed while Rokt selects a placement for the confirmation page. Supply your own asset to override the default. | Rokt loading indicator |
| `fallback-timeout` | Duration in milliseconds before placement selection times out and the native confirmation page renders.                                                    | `5000`                 |
| `partner-opt-in`   | Force-enable the Interstitial experience. Usage: `<rokt-thank-you partner-opt-in>`.                                                                        | —                      |
| `partner-opt-out`  | Force-skip the Interstitial experience. Usage: `<rokt-thank-you partner-opt-out>`.                                                                         | —                      |

## 6. Subscribe to Placement Events

The SDK+ emits events throughout the placement lifecycle. Subscribe to these events to run custom logic when a placement is ready, when a customer engages with a placement, or when an interstitial placement wrapper transitions between states.

### Lifecycle event source: Placement lifecycle

By subscribing to a [placement event](https://docs.rokt.com/developer-reference/sdks/web-sdk/event-based-integration) you can receive notifications that are triggered when a placement is ready or when a customer engages with an offer.

#### Subscribe to Placement Events

```javascript
window.mParticle.ready(async function () {
const selection = await window.mParticle.Rokt.selectPlacements({
  // add attributes
});

// Listen for when the placement becomes interactive/ready to display
selection.on('PLACEMENT_INTERACTIVE').subscribe(() => {
  // Logic to run after Placement has become interactive
});

// Listen for when user engages positively or negatively with an offer
selection.on('OFFER_ENGAGEMENT').subscribe(function () {
  // Logic to run after offer is engaged with
});
});
```

### Lifecycle event source: Interstitial lifecycle

The `<rokt-thank-you>` element used by the interstitial format emits lifecycle events you can subscribe to for custom behavior. Register listeners with `window.mParticle.Rokt.onShoppableAdsReady()` — this callback fires as soon as the element is ready, so listeners registered before `mParticle.ready()` are never missed.

#### Show rokt-thank-you lifecycle events

| Event                                 | Emitted when                                                             |
| ------------------------------------- | ------------------------------------------------------------------------ |
| `THANK_YOU_ELEMENT_LOADING_INITIATED` | The `<rokt-thank-you>` element enters its loading state.                 |
| `THANK_YOU_ELEMENT_COMPLETE`          | The `<rokt-thank-you>` element renders the partner confirmation content. |

#### Subscribe to rokt-thank-you events

```javascript
// Register listeners before mParticle.ready() so events are never missed.
window.mParticle.Rokt.onShoppableAdsReady(() => {
window.RoktThankYouElement.on('THANK_YOU_ELEMENT_LOADING_INITIATED').subscribe(() => {
  // Triggered when the Thank You element enters its loading state
});

window.RoktThankYouElement.on('THANK_YOU_ELEMENT_COMPLETE').subscribe(() => {
  // Triggered when the Thank You element renders the partner confirmation
});
});

window.mParticle.ready(() => {
// Standard mParticle initialization continues here
});
```

## 7. Appendix

Reference for closing placements in single-page apps, enabling extensions for advanced features, and configuring optional launcher behavior.

### Close a placement

In single-page apps, call `.close()` on the placement object after the user navigates away so the placement doesn't linger on back-navigation.

### Close a placement

```javascript
// Closes the placement called 'selection'
selection.close();
```

> **Caution: Pay+**
>
> If you are using Pay+, you must close your placement after the user navigates away.

### Additional functionality via extensions

Some features require extensions. Enable them by calling `mParticle.Rokt.use()` before `selectPlacements()`. For example, to display upsell placements on a Thank You page, enable the `ThankYouPageJourney` extension first:

### Enable the ThankYouPageJourney extension

```javascript
window.mParticle.ready(async function() {
// Enable the necessary extension prior to selecting placements
await window.mParticle.Rokt.use("ThankYouPageJourney");

const selection = await mParticle.Rokt.selectPlacements({
  identifier: "yourPageIdentifier",
  attributes: {
    "email": "j.smith@example.com"
    // Any additional user attributes you want to pass to Rokt
  },
});
})
```

### Passing additional integration launcher options

Configure optional behavior by setting `window.mParticle.config.launcherOptions` in the initialization script:

### launcherOptions config

```javascript
// Include this as part of the initialization script in step 1 above
window.mParticle.config.launcherOptions = {
  noFunctional: true,
  noTargeting: true,
  // See all optional launcher options that can be set below
};
```

#### Manage customer cookie preferences

Use these options to respect customer opt-out preferences by disabling functional or targeting cookies.

| Parameter      | Type    | Default | Description                                                                                                                                                                                                                |
| -------------- | ------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `noFunctional` | boolean | `false` | Set to `true` to prevent Rokt from using first-party tracking IDs when the customer has opted out of functional cookies. Functional cookies power first-party personalization and advanced checkout features like Upsells. |
| `noTargeting`  | boolean | `false` | Set to `true` to prevent Rokt from using cross-site tracking IDs for the session when the customer has opted out of targeting cookies. Functional identifiers remain active unless `noFunctional` is also set to `true`.   |

For a more detailed discussion, see [Cookie Consent Flags](https://docs.rokt.com/developer-reference/sdks/web-sdk/cookie-consent-flags).

#### Measure page load performance in single-page apps

Provide the timestamp of when a virtual page loads so Rokt can accurately measure performance in SPAs and detect anomalies that could impact the customer experience.

| Parameter           | Type | Default                                                                                                                     |
| ------------------- | ---- | --------------------------------------------------------------------------------------------------------------------------- |
| `pageInitTimestamp` | Date | [`PerformanceNavigationTiming.responseStart`](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceNavigationTiming) |

When the launcher initializes on a virtual page in an SPA, pass the timestamp of when that page was initialized so Rokt can measure load performance relative to the page that triggered it.

#### Link customer activity with a Rokt session ID

Pass a previously generated Rokt session ID to ensure activity across different parts of the experience is tied together correctly.

| Parameter   | Type   | Default |
| ----------- | ------ | ------- |
| `sessionId` | string | —       |

If you've generated a Rokt session ID from a prior backend interaction, pass it here so Rokt can pair it with front-end activity.

#### Customize how links open in your experience

Enable this option when you want full control over how Rokt and advertiser links open (for example, inside a WebView instead of a browser).

| Parameter                | Type    | Default |
| ------------------------ | ------- | ------- |
| `overrideLinkNavigation` | boolean | `false` |

When set to `true`, Rokt stops handling link openings directly and instead emits a `LINK_NAVIGATION_REQUEST` partner event. To distinguish Rokt and advertiser links from your own, check whether the URL contains `"rokt.com"`.

Subscribe to the event on the selection returned by `selectPlacements`. Each event carries a single `url` string — the link the customer activated. Open it immediately, in whichever context you need (a browser tab, a WebView, and so on), to avoid degrading the customer experience.

### Handle LINK\_NAVIGATION\_REQUEST

```javascript
const selection = await window.mParticle.Rokt.selectPlacements({
  // identifier and attributes as in the examples above
});

selection.on("LINK_NAVIGATION_REQUEST").subscribe((event) => {
  // event.url is the link the customer activated — open it immediately
  window.open(event.url);
});
```

If a `LINK_NAVIGATION_REQUEST` event is not consumed within 3 seconds, an error is raised — make sure an active subscription exists to process the event.

## 8. Test Your Integration

To confirm the SDK+ initializes, identifies the user, logs events, and requests offers correctly:

### 1. Open a new browser window

Open a new browser window so you start with a clean state.

### 2. Open developer tools

Open your browser's developer tools panel. For most browsers, you can do this by right-clicking on your screen and clicking **Inspect**.

Enable the option that keeps network requests across page loads (**Preserve log** in Chrome, Edge, and Safari, or **Persist Logs** in Firefox).

### 3. Filter network requests

From the developer tools panel, go to the **Network** tab and filter for `rokt-api.com`. If you use a [custom first-party domain](https://docs.rokt.com/developer-reference/sdks/web-sdk/first-party-domains/), filter for your custom subdomain instead.

To find a specific request, you can also filter by its endpoint name: `/identity`, `/events`, `/experiences`, or `/offers`.

### 4. Run the test journey

With the **Network** tab recording, complete a test journey through the pages where you integrated the SDK+.

> **Note**
>
> Open the developer tools panel before navigating to your site so the browser records all SDK+ requests.

### 5. Verify the identity request

Filter for `/identity`, then select the request that matches the identity action you performed, such as `identify` or `login`. Confirm that it has a successful status, then check the **Payload** or **Request** tab for the test identifiers you expected to send.

### 6. Verify page-view and commerce events

Filter for `/events`, then select the request generated during your test journey. Confirm that it has a successful status. Check the **Payload** or **Request** tab to verify that the request contains the page-view or commerce event and the attributes you expected to send.

Event requests can contain multiple events, so inspect the complete request payload when checking for a specific action.

### 7. Verify the selection request

Filter for `/experiences`, then for `/offers`. Depending on your SDK+ routing, a successful selection uses one of these endpoints:

- `/v1/experiences`
- `/v2/sessions/offers`

You only need to see one of these requests. Select the request with a 200 status, then check the **Payload** or **Request** tab to verify the data being shared with Rokt.

> **Note**
>
> During testing, you might also see a `/v1/experiences` request with a 204 status. Use the request with a 200 status when checking the payload.

### Troubleshooting

If your integration isn't working, check the **Console** tab in your browser's developer tools for Rokt SDK+ errors. Common issues include:

#### Initialization errors

- Make sure the SDK+ initialization script has been placed on the correct page.
- If you integrated using a tag manager, make sure you configured your tag triggers so that initialization loads on the right pages, and that your `selectPlacements` and conversion logging tags are firing after the SDK+ has initialized.

#### Syntax errors

Make sure you are not missing any commas in your integration code.

To check for syntax errors:

### 1. Open the Console tab

Go to your browser's developer tools panel and select the **Console** tab.

### 2. Find the error

If the file where you placed the Web SDK+ has an error, it should be logged in the console. Click the file to see the code and reported error.

### 3. Verify commas

Any error is indicated in the file. In particular, check that all attributes are separated by commas as shown below.

#### Missing comma (incorrect)

```javascript
email: ''
mobile_number: '',
```

#### Correct

```javascript
email: '',
mobile_number: '',
```
