# React Native 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/react-native/](https://docs.rokt.com/integration-guides/ecommerce/sdk/react-native/)
>
> 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 React Native SDK+. The SDK+ passes user and transaction data to Rokt on configured screens so Rokt can render relevant experiences, such as offers on confirmation screens.

Use the **Target** and **Language** selectors above to choose your deployment platform and the native code examples you want to follow.

> **Note**
>
> You'll write a few lines of native code when you initialize the SDK+ in [Step 2](https://docs.rokt.com/integration-guides/ecommerce/sdk/react-native/#initialize-rn). Every other step uses JavaScript through the `react-native-mparticle` package.

## 1. Add the Rokt SDK+ to Your React Native App

### 1. Install the React Native package

Add the React Native SDK+ as a dependency to your application:

#### Install the React Native package

```shell
npm install react-native-mparticle --save
```

### 2. Import the package into your app

Import the package into your React Native app code and get an instance of the SDK:

#### Import the React Native package

```javascript
import MParticle from 'react-native-mparticle';
```

Continue setting up the SDK+ on your native project. Use the **Target** pill above to switch between iOS and Android.

### Target: iOS

The NPM install step above automatically pulls in the React framework and the core iOS framework. The Rokt SDK+ for iOS is added as a pod dependency in your `ios/Podfile`.

#### 3. Add the Rokt SDK pod to your Podfile

Add the Rokt SDK+ pod to your `ios/Podfile`:

##### ios/Podfile

```ruby
pod 'RoktSDKPlus', '~> 9.2'
```

Because Rokt's iOS SDK contains Swift code, you need to either keep React Native's default static linking with a `pre_install` exception, or switch your project to frameworks. Pick the path that matches your project:

#### Linkage: Static (React Native default)

##### 4. Configure your Podfile

Add the following `pre_install` block to your `ios/Podfile`:

###### ios/Podfile (pre\_install block)

```ruby
pre_install do |installer|
installer.pod_targets.each do |pod|
  if pod.name == 'RoktSDKPlus' || pod.name == 'mParticle-Apple-SDK' || pod.name == 'mParticle-Rokt' || pod.name == 'Rokt-Widget'
    def pod.build_type
      Pod::BuildType.new(:linkage => :dynamic, :packaging => :framework)
    end
  end
end
end
```

##### 5. Install pods

Run `pod install` to apply the changes:

###### Install pods

```shell
bundle exec pod install
```

#### Linkage: Frameworks

##### 4. Configure your Podfile

If your `ios/Podfile` has a Flipper config line, comment it out:

###### ios/Podfile (comment out Flipper)

```ruby
# :flipper_configuration => flipper_config,
```

##### 5. Install pods

Run `pod install` with `USE_FRAMEWORKS` to apply the changes. Pick `static` or `dynamic` based on your project:

###### Install pods with USE\_FRAMEWORKS

```shell
USE_FRAMEWORKS=static bundle exec pod install
# or
USE_FRAMEWORKS=dynamic bundle exec pod install
```

### Target: Android

The NPM install step above automatically pulls in the React framework and the core Android library. The Rokt Kit is added as an implementation dependency in your app project.

#### 3. Add the Rokt Kit Gradle dependency

Add the Rokt Kit to your app's gradle dependencies:

##### Gradle DSL: Kotlin DSL

###### android/app/build.gradle.kts

```kotlin
dependencies {
  implementation("com.mparticle:android-rokt-kit:6.0.0")
}
```

##### Gradle DSL: Groovy

###### android/app/build.gradle

```groovy
dependencies {
  implementation "com.mparticle:android-rokt-kit:6.0.0"
}
```

## 2. Initialize the Rokt SDK+

Initialize the Rokt SDK+ on the native side. The SDK+ must be initialized before any other SDK+ API calls. Use the **Target** pill above to switch between iOS and Android.

### Target: iOS

Insert the initialization snippet in your `AppDelegate` file. Replace `your-key` and `your-secret` with the values provided by your Rokt account manager.

> **Caution**
>
> Call `registerPaymentExtension` after `MParticle.sharedInstance().start(with:)` and before `selectShoppableAds`. It is required for Shoppable Ads placements on iOS.

#### AppDelegate initialization (Swift)

```swift
import mParticle_Apple_SDK
import RoktPaymentExtension

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
  // Initialize the SDK
  let options = MParticleOptions(key: "your-key",
  secret: "your-secret")
  // Specify the data environment with environment:
  // Set it to .development if you are still testing your integration.
  // Set it to .production if your integration is ready for production data.
  // The default is .autoDetect which attempts to detect the environment automatically
  options.environment = .development
  MParticle.sharedInstance().start(with: options)

  // Register after MParticle.sharedInstance().start(), before selectShoppableAds
  if let paymentExt = RoktPaymentExtension(
      applePayMerchantId: "merchant.com.yourapp.rokt"
  ) {
      MParticle.sharedInstance().rokt.registerPaymentExtension(paymentExt)
  }
  return true
}
```

#### AppDelegate initialization (Objective-C)

```objectivec
#import <mParticle_Apple_SDK/mParticle.h>

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

  // Initialize the SDK
  MParticleOptions *options = [MParticleOptions optionsWithKey:@"your-key"
  secret:@"your-secret"];
  // Specify the data environment with environment:
  // Set it to MPEnvironmentDevelopment if you are still testing your integration.
  // Set it to MPEnvironmentProduction if your integration is ready for production data.
  // The default is MPEnvironmentAutoDetect which attempts to detect the environment automatically
  options.environment = MPEnvironmentDevelopment;
  [[MParticle sharedInstance] startWithOptions:options];

  return YES;
}
```

When inserting the initialization snippet, you will see customizable fields for:

#### 1. Entering your Rokt key and secret

Set `your-key` and `your-secret` in `MParticleOptions(key:secret:)` to the values provided by your Rokt account manager.

#### 2. Setting your data environment

Set `options.environment` to `.development` while testing to route data to the Development environment, and `.production` to send live customer activity to Production.

#### 3. Registering the payment extension

Register `RoktPaymentExtension` after `MParticle.sharedInstance().start(with:)` and before `selectShoppableAds` to enable Shoppable Ads payments (including Apple Pay). Replace `merchant.com.yourapp.rokt` with your Apple Pay merchant ID. Required for all Shoppable Ads placements on iOS. The Stripe publishable key is configured in your **mParticle Rokt kit** settings (mParticle dashboard) — you only pass the Apple Pay merchant ID in code. `RoktPaymentExtension` is a Swift type; if your `AppDelegate` is Objective-C, do this from a small Swift file.

### Target: Android

Configure the Android SDK using an `MParticleOptions` object and a builder class in the `onCreate()` of your `Application` class.

> **Caution**
>
> Make sure to replace `your-key` and `your-secret` with the key and secret provided by your dedicated Rokt account representative.

#### Application.onCreate initialization (Kotlin)

```kotlin
import com.mparticle.MParticle
import com.mparticle.MParticleOptions

class YourApplicationClass : Application() {
  override fun onCreate() {
      super.onCreate()
      val options: MParticleOptions = MParticleOptions.builder(this)
      .credentials(
          "your-key",   // The key provided by your Rokt account representative
          "your-secret" // The secret provided by your Rokt account representative
      ).environment(MParticle.Environment.Development)  // Specify the data environment with environment:
      // Set it to .development if you are still testing your integration.
      // Set it to .production if your integration is ready for production data.
      // The default is .autoDetect which attempts to detect the environment automatically
      .build()

      MParticle.start(options)
  }
}
```

#### Application.onCreate initialization (Java)

```java
import com.mparticle.MParticle;
import com.mparticle.MParticleOptions;
public class YourApplicationClass extends Application {
  @Override
  public void onCreate() {
      super.onCreate();
      MParticleOptions options = MParticleOptions.builder(this)
      .credentials(
          "your-key", // The key provided by your Rokt account representative
          "your-secret" // The secret provided by your Rokt account representative
      ).environment(MParticle.Environment.Production) // Specify the data environment with environment:
      // Set it to .development if you are still testing your integration.
      // Set it to .production if your integration is ready for production data.
      // The default is .autoDetect which attempts to detect the environment automatically
      .build();
      MParticle.start(options);
  }
}
```

When inserting the initialization snippet, you will see customizable fields for:

#### 1. Entering your Rokt key and secret

Set `your-key` and `your-secret` in `.credentials(...)` to the values provided by your Rokt account manager.

#### 2. Setting your data environment

Set `.environment(...)` to `MParticle.Environment.Development` while testing to route data to the Development environment, and `MParticle.Environment.Production` to send live customer activity to Production.

> **Note**
>
> To identify the user and set additional user attributes, see [Step 3: Identify the User](https://docs.rokt.com/integration-guides/ecommerce/sdk/react-native/#identify-rn) below. If you don't have the user's email at initialization, you can identify the user later — see [Error handling](https://docs.rokt.com/integration-guides/ecommerce/sdk/react-native/#error-handling-rn) for how to handle identity errors.

## 3. Identify the User

The [SDK+ initialization script](https://docs.rokt.com/integration-guides/ecommerce/sdk/react-native/#initialize-rn) 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 | Pass the customer's raw, unhashed email address.                                                                                                                 |
| `mobile`       | string | Pass the customer's phone number in E.164 format.                                                                                                                |
| `customerid`   | string | Pass your internal customer/account identifier. Send on every screen for logged-in users.                                                                        |
| `other`        | string | Pass a SHA-256-hashed email. **Only use when the raw email cannot be provided — do not pass both `email` and `other`.** (Android path only.)                     |
| `other2`       | string | Pass a SHA-256-hashed mobile number. **Only use when the raw mobile number cannot be provided — do not pass both `mobile` and `other2`.** (Android path only.)   |
| `emailSha256`  | string | Pass a SHA-256-hashed email. **Only use when the raw email cannot be provided — do not pass both `email` and `emailSha256`.** (iOS path only.)                   |
| `mobileSha256` | string | Pass a SHA-256-hashed mobile number. **Only use when the raw mobile number cannot be provided — do not pass both `mobile` and `mobileSha256`.** (iOS path only.) |

To identify the user:

### 1. Create an IdentityRequest object

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

### 2. Set additional attributes via the identity callback

To set additional user attributes, use the identity callback. If the `identifyRequest` succeeds, 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`:

#### Identify Jane Smith

```javascript
// 1. Create the identifyRequest object
const request = new MParticle.IdentityRequest();
// Preferred: pass the customer's raw, unhashed email.
// If you can only provide a SHA-256-hashed email, remove .email and use other instead — do not pass both.
request.email = 'j.smith@example.com';
request.other = 'SHA-256 hashed email';  // only if raw email unavailable
// If you can only provide a SHA-256-hashed mobile number, use other2 instead of mobile — do not pass both.
// (Called 'other2' on Android and 'mobileSha256' on iOS; both use this same field.)
request.other2 = 'SHA-256 hashed mobile number';  // only if raw mobile unavailable
request.mobile = '+13125551515';
request.customerId = 'cust_10482';

// 2. User attributes are set using the identity callback
const identityCallback = (error, userId) => {
  if (error) {
      console.debug(error);
  } else {
      const user = new MParticle.User(userId);
      user.setUserAttribute('firstname', 'Jane');
      user.setUserAttribute('lastname', 'Smith');
  }
};
// 3. Call one of the following methods that best matches the user's action:
MParticle.Identity.login(request, identityCallback); // Call when the user logs in or creates an account
MParticle.Identity.identify(request, 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
```

## 4. Set User Attributes

Set user attributes **progressively** as the user navigates your app, not just at checkout. The more attributes you set, the better Rokt can resolve the customer and deliver relevant offers.

### Set user attributes

```javascript
import MParticle from 'react-native-mparticle';

// Retrieve the current user. This will only succeed if you have identified the user during SDK+ initialization or by calling the identify method.
MParticle.Identity.getCurrentUser((currentUser) => {
  if (currentUser) {
      // Once you have the current user, you can set user attributes with:
      currentUser.setUserAttribute('custom-attribute-name', 'custom-attribute-value');
      // Note: all user attributes (including list attributes and tags) must have distinct names.

      // Rokt recommends setting as many of the following user attributes as possible:
      currentUser.setUserAttribute('firstname', 'John');
      currentUser.setUserAttribute('lastname', 'Doe');
      // Phone numbers can be formatted either as '1234567890', or '+1 (234) 567-8901'
      currentUser.setUserAttribute('mobile', '3125551515');
      currentUser.setUserAttribute('age', '33');
      currentUser.setUserAttribute('gender', 'M');
      currentUser.setUserAttribute('billingcity', 'Brooklyn');
      currentUser.setUserAttribute('billingstate', 'NY');
      currentUser.setUserAttribute('billingzipcode', '123456');
      currentUser.setUserAttribute('dob', 'yyyymmdd');
      currentUser.setUserAttribute('title', 'Mr');
      currentUser.setUserAttribute('language', 'en');
      currentUser.setUserAttribute('predictedltv', '136.23');

      // You can create a user attribute to contain a list of values
      currentUser.setUserAttributeArray('favorite-genres', ['documentary', 'comedy', 'romance', 'drama']);

      // To remove a user attribute, call removeUserAttribute and pass in the attribute name.
      currentUser.removeUserAttribute('attribute-to-remove');
  }
});
```

### User attributes

Set as many of the following 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`             | string  | Phone number formatted as `1112345678` or `+1 (222) 345-6789`. Used for identity resolution and relevance.             |
| `age`                | integer | Customer's age. Alternate to `dob`. Used for eligibility and relevance.                                                |
| `dob`                | string  | Date of birth, `yyyymmdd`. Alternate to `age`. 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.                                              |
| `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.                             |
| `billingaddress1`    | string  | Billing street address line 1. Used for identity resolution and relevance.                                             |
| `billingaddress2`    | string  | Billing street address line 2. Used for identity resolution.                                                           |
| `country`            | string  | ISO 3166-1 alpha-2 country code (e.g. `US`, `GB`, `AU`). Used for eligibility and relevance.                           |
| `birthyear`          | integer | Customer's birth year (e.g. `1990`). Used for eligibility and 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.                                         |
| `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 from a partner ML 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  | Channel through which the customer was acquired. Used for relevance.                                                   |

All user attributes (including list attributes) must have distinct names.

## 5. Track Funnel Events

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

### Event category: Screen views

Call `MParticle.logScreenEvent()` with the name of the screen (e.g. `"homepage"`, `"product_detail_page"`). Include any additional custom attributes in the info object.

#### Log a screen view

```javascript
import MParticle from 'react-native-mparticle';

MParticle.logScreenEvent('homepage', {
  'custom-attribute': 'custom-value',
});
```

### Event category: Commerce events

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

Investing in full commerce event coverage is one of the highest-leverage things you can do during your integration. Each event tells Rokt something different about where the customer is in their journey: a product view signals exploration, an add-to-cart signals consideration, a checkout start signals purchase intent, and a completed purchase confirms conversion. With a richer signal, Rokt can personalize offers more effectively, measure placement performance accurately, and attribute conversions to the right touchpoints. Doing this work during your initial integration also avoids a retrofit later. The signal compounds over time: each event Rokt receives adds context used to sharpen personalization, improve attribution accuracy, and better resolve and segment your customer base on future visits.

Commerce events are logged with `MParticle.CommerceEvent.createProductActionEvent`, using a product action type that identifies the customer action (viewing a product, adding to cart, starting checkout, completing a purchase, etc.).

#### Show all product action types

| Customer action            | Product action type                              |
| -------------------------- | ------------------------------------------------ |
| Product detail page viewed | `MParticle.ProductActionType.ViewDetail`         |
| Product clicked            | `MParticle.ProductActionType.Click`              |
| Item added to cart         | `MParticle.ProductActionType.AddToCart`          |
| Item removed from cart     | `MParticle.ProductActionType.RemoveFromCart`     |
| Item added to wishlist     | `MParticle.ProductActionType.AddToWishlist`      |
| Item removed from wishlist | `MParticle.ProductActionType.RemoveFromWishlist` |
| Checkout flow initiated    | `MParticle.ProductActionType.Checkout`           |
| Checkout option selected   | `MParticle.ProductActionType.CheckoutOption`     |
| Order confirmed            | `MParticle.ProductActionType.Purchase`           |
| Order refunded             | `MParticle.ProductActionType.Refund`             |

Tracking a commerce event takes three phases:

#### 1. Define the product

Create an `MParticle.Product` with the product's name, SKU, price, and quantity. Set additional fields like `category`, `brand`, and `position` directly on the instance.

##### Define a product

```javascript
const product = new MParticle.Product(
  'Double Room - Econ Rate',
  'econ-1',
  100.00,
  4
);
product.category = 'room';
product.brand = 'lodge-o-rama';
product.variant = 'standard';
```

#### 2. Summarize the transaction

Create an `MParticle.TransactionAttributes` for `Purchase`, `Checkout`, and `CheckoutOption` events. Include shipping and order-level coupons when applicable — order-level coupons belong here, not on individual products.

##### Summarize the transaction

```javascript
const transactionAttributes = new MParticle.TransactionAttributes('ORDER-12345')
  .setRevenue(149.99)
  .setTax(12.50)
  .setShipping(5.99)
  .setCouponCode('SUMMER20');
```

#### 3. Log the commerce event

Build a commerce event with `MParticle.CommerceEvent.createProductActionEvent`, passing the product action type, your product(s), and (when applicable) the `transactionAttributes`. Then call `MParticle.logCommerceEvent`. Pick the customer action you want to log:

##### Commerce event: PLP impression

Log a product listing (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 `MParticle.Product`. 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
import MParticle from 'react-native-mparticle';

const product = new MParticle.Product('Trail Runner v3', 'SKU-001', 129.95, 1);
product.position = 1; // 1-indexed rank in the list

const impression = new MParticle.Impression('Mens Running Shoes', [product]);

const commerceEvent = MParticle.CommerceEvent.createImpressionEvent([impression]);
commerceEvent.currency = 'USD';
MParticle.logCommerceEvent(commerceEvent);
```

##### 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
import MParticle from 'react-native-mparticle';

const product = new MParticle.Product('Trail Runner v3', 'SKU-001', 129.95, 1);

const commerceEvent = MParticle.CommerceEvent.createProductActionEvent(
  MParticle.ProductActionType.ViewDetail,
  [product],
);
commerceEvent.currency = 'USD';
commerceEvent.customAttributes = { 'listname': 'PLP-Running' };
MParticle.logCommerceEvent(commerceEvent);
```

##### 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
import MParticle from 'react-native-mparticle';

const product = new MParticle.Product('Trail Runner v3', 'SKU-001', 129.95, 1);

const commerceEvent = MParticle.CommerceEvent.createProductActionEvent(
  MParticle.ProductActionType.AddToCart,
  [product],
);
commerceEvent.currency = 'USD';
MParticle.logCommerceEvent(commerceEvent);
```

##### 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
import MParticle from 'react-native-mparticle';

const product = new MParticle.Product('Trail Runner v3', 'SKU-001', 129.95, 1);

const commerceEvent = MParticle.CommerceEvent.createProductActionEvent(
  MParticle.ProductActionType.RemoveFromCart,
  [product],
);
commerceEvent.currency = 'USD';
MParticle.logCommerceEvent(commerceEvent);
```

##### 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.Event` with the event name `"view_cart"` and `Other` event type. Pass the full cart contents as custom attributes.

| Field           | Type      | Required | Description                                                     |
| --------------- | --------- | -------- | --------------------------------------------------------------- |
| `event_name`    | string    | yes      | Always `"view_cart"`.                                           |
| `event_type`    | EventType | yes      | Use `MParticle.EventType.Other`.                                |
| `cartitems`     | string    | yes      | JSON-serialized array of cart-line objects. Used for relevance. |
| `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.                                  |

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.                                                                                                                                   |

###### Example cart page view event

```javascript
import MParticle from 'react-native-mparticle';

const 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 },
];

const event = new MParticle.Event()
  .setName('view_cart')
  .setType(MParticle.EventType.Other)
  .setInfo({
      cartitemcount: 3,
      totalprice: 169.85,
      currency: 'USD',
      couponcode: 'SUMMER20',
      cartitems: JSON.stringify(cartitems),
  });
MParticle.logMPEvent(event);
```

##### Commerce event: Checkout

Log when the customer enters the checkout flow. Send all cart products and a transaction summary covering the cart total and any order-level coupon.

| 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
import MParticle from 'react-native-mparticle';

const product1 = new MParticle.Product('Trail Runner v3', 'SKU-001', 129.95, 1);
const product2 = new MParticle.Product('Cushion Insole',  'SKU-002', 19.95,  2);

const transactionAttributes = new MParticle.TransactionAttributes('YOUR_CHECKOUT_ID')
  .setRevenue(169.85)
  .setCouponCode('SUMMER20');

const commerceEvent = MParticle.CommerceEvent.createProductActionEvent(
  MParticle.ProductActionType.Checkout,
  [product1, product2],
  transactionAttributes,
);
commerceEvent.currency = 'USD';
commerceEvent.customAttributes = { cartitemcount: 3 };
MParticle.logCommerceEvent(commerceEvent);
```

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

Log when the customer completes the shipping step. Set `checkoutOption` to `"shipping"` and pass the shipping selection as custom attributes.

| 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
import MParticle from 'react-native-mparticle';

const product1 = new MParticle.Product('Trail Runner v3', 'SKU-001', 129.95, 1);
const product2 = new MParticle.Product('Cushion Insole',  'SKU-002', 19.95,  2);

const commerceEvent = MParticle.CommerceEvent.createProductActionEvent(
  MParticle.ProductActionType.CheckoutOption,
  [product1, product2],
);
commerceEvent.setCheckoutOptions('shipping');
commerceEvent.currency = 'USD';
commerceEvent.customAttributes = {
  shippingmethod: 'express',
  zipcode: '94103',
  country: 'US',
  totalprice: 169.85,
};
MParticle.logCommerceEvent(commerceEvent);
```

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

Log when the customer completes the payment step. Set `checkoutOption` to `"payment"` and pass the payment method selected as custom attributes.

| 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
import MParticle from 'react-native-mparticle';

const product1 = new MParticle.Product('Trail Runner v3', 'SKU-001', 129.95, 1);
const product2 = new MParticle.Product('Cushion Insole',  'SKU-002', 19.95,  2);

const commerceEvent = MParticle.CommerceEvent.createProductActionEvent(
  MParticle.ProductActionType.CheckoutOption,
  [product1, product2],
);
commerceEvent.setCheckoutOptions('payment');
commerceEvent.currency = 'USD';
commerceEvent.customAttributes = {
  paymenttype: 'credit_card',
  payment_method: 'visa',
  paymentServiceProvider: 'stripe',
  ccbin: '424242',
  totalprice: 169.85,
};
MParticle.logCommerceEvent(commerceEvent);
```

##### Commerce event: Purchase

Log when an order is confirmed. Send the full cart and a transaction summary identifying the order, revenue, tax, shipping, and any order-level coupon.

| 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.                |

###### Example Purchase event

```javascript
import MParticle from 'react-native-mparticle';

const product1 = new MParticle.Product('Trail Runner v3', 'SKU-001', 129.95, 1);
const product2 = new MParticle.Product('Cushion Insole',  'SKU-002', 19.95,  2);

const transactionAttributes = new MParticle.TransactionAttributes('ORDER-10482')
  .setRevenue(169.85)
  .setTax(14.20)
  .setShipping(5.99)
  .setCouponCode('SUMMER20');

const commerceEvent = MParticle.CommerceEvent.createProductActionEvent(
  MParticle.ProductActionType.Purchase,
  [product1, product2],
  transactionAttributes,
);
commerceEvent.currency = 'USD';
commerceEvent.customAttributes = { cartitemcount: 3 };
MParticle.logCommerceEvent(commerceEvent);
```

##### Commerce event: Refund

Log when an order (or a line within it) is refunded. Send only the products being refunded plus a transaction summary referencing the original order ID.

| 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
import MParticle from 'react-native-mparticle';

const refundedProduct = new MParticle.Product('Trail Runner v3', 'SKU-001', 129.95, 1);

const transactionAttributes = new MParticle.TransactionAttributes('ORDER-10482') // original order id
  .setRevenue(129.95); // refunded amount

const commerceEvent = MParticle.CommerceEvent.createProductActionEvent(
  MParticle.ProductActionType.Refund,
  [refundedProduct],
  transactionAttributes,
);
commerceEvent.currency = 'USD';
MParticle.logCommerceEvent(commerceEvent);
```

### Event category: Custom events

Track custom events using `MParticle.Event`, passing an event name, event type, and optional custom attributes.

#### Show custom event types

| Type                                 | Use for                                                       |
| ------------------------------------ | ------------------------------------------------------------- |
| `MParticle.EventType.Navigation`     | User navigation flows and screen transitions within your app. |
| `MParticle.EventType.Location`       | Location-based interactions and movements.                    |
| `MParticle.EventType.Search`         | Search queries and search-related actions.                    |
| `MParticle.EventType.Transaction`    | Financial transactions and purchase-related activity.         |
| `MParticle.EventType.UserContent`    | User-generated content like reviews, comments, or posts.      |
| `MParticle.EventType.UserPreference` | User settings, preferences, and customization choices.        |
| `MParticle.EventType.Social`         | Social media interactions and sharing activities.             |
| `MParticle.EventType.Other`          | Anything that doesn't fit the categories above.               |

#### Log a custom event

```javascript
import MParticle from 'react-native-mparticle';

const event = new MParticle.Event()
  .setName('video_watched')
  .setType(MParticle.EventType.Navigation)
  .setInfo({ category: 'Destination Intro', title: 'Paris' });
MParticle.logMPEvent(event);
```

## 6. Show a Placement

Call `selectPlacements` on every payment and confirmation screen you want Rokt to render content on. Include one of the following page identifiers to specify the screen type and whether it's for testing or production:

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

Call `selectPlacements` as early as the screen loads and once all relevant attributes are available. At minimum, pass `email`, `firstname`, `lastname`, `billingzipcode`, and `confirmationref`. See [Placement attributes](https://docs.rokt.com/integration-guides/ecommerce/sdk/react-native/#placement-attributes) for the full list.

> **Caution: Pay+**
>
> For Pay+ placements, include `paymenttype` and `paymentServiceProvider` in the `selectPlacements` call on each screen. `paymentServiceProvider` communicates what payment methods are available on the payment screen; `paymenttype` communicates what method the user paid with.

### Placement attributes

Pass these attributes in the `attributes` map of `selectPlacements`. Always supply the most recent value — attributes passed here override any earlier `setUserAttribute` calls.

### Show all placement attributes

| Field                    | Type    | Description                                                                                                                                                                                                                                                                                                                                                           |
| ------------------------ | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `email`                  | string  | Customer email (unhashed). Used for identity resolution.                                                                                                                                                                                                                                                                                                              |
| `firstname`              | string  | Customer first name. Used for personalization.                                                                                                                                                                                                                                                                                                                        |
| `lastname`               | string  | Customer last name. Used for personalization.                                                                                                                                                                                                                                                                                                                         |
| `mobile`                 | string  | Customer mobile number in E.164 format. Used for identity resolution.                                                                                                                                                                                                                                                                                                 |
| `confirmationref`        | string  | Order / confirmation reference number. Used for relevance and deduplication.                                                                                                                                                                                                                                                                                          |
| `currency`               | string  | Transaction currency (ISO 4217, e.g. `USD`, `GBP`, `AUD`). Used for relevance.                                                                                                                                                                                                                                                                                        |
| `country`                | string  | ISO 3166-1 alpha-2 country code. Used for eligibility and relevance.                                                                                                                                                                                                                                                                                                  |
| `language`               | string  | Customer's preferred language (ISO 639-1). Used for relevance.                                                                                                                                                                                                                                                                                                        |
| `totalprice`             | decimal | Total cart value including tax and shipping. Used for relevance.                                                                                                                                                                                                                                                                                                      |
| `amount`                 | string  | Cart subtotal before tax and shipping. Distinct from `totalprice`. Used for relevance.                                                                                                                                                                                                                                                                                |
| `couponCode`             | string  | Promo code applied to the order, if any. Used for relevance.                                                                                                                                                                                                                                                                                                          |
| `newcustomer`            | boolean | Whether this is a first-time buyer. Used for relevance.                                                                                                                                                                                                                                                                                                               |
| `customertype`           | string  | `guest` or `logged_in`. Used for relevance.                                                                                                                                                                                                                                                                                                                           |
| `value`                  | decimal | Customer's cumulative purchase value (e.g. `"2340.00"`). 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.                                                                                                                                                                                                                                                                      |
| `paymenttype`            | string  | Payment method selected (`credit_card`, `paypal`, `apple_pay`, etc.). Used for Pay+ eligibility.                                                                                                                                                                                                                                                                      |
| `paymentServiceProvider` | string  | Comma-separated list of payment methods accepted on the page (e.g. `applepay,paypal,cardpayment`). Values must be lowercase with no spaces. See [Payment Service Provider](https://docs.rokt.com/developer-reference/product-deep-dives/pay-plus/partners/data-integration#payment-service-provider) for the full list of accepted values. Used for Pay+ eligibility. |
| `ccbin`                  | string  | Credit card BIN (6-8 digits). Used for relevance.                                                                                                                                                                                                                                                                                                                     |
| `billingname`            | string  | Billing name. Used for identity resolution.                                                                                                                                                                                                                                                                                                                           |
| `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 or province. Used for relevance.                                                                                                                                                                                                                                                                                                                        |
| `billingzipcode`         | string  | Billing ZIP / postcode. Used for identity resolution and relevance.                                                                                                                                                                                                                                                                                                   |
| `shippingmethod`         | string  | Shipping method selected (`standard`, `express`, `next_day`). Used for relevance.                                                                                                                                                                                                                                                                                     |
| `shippingname`           | string  | Shipping name. Used for relevance.                                                                                                                                                                                                                                                                                                                                    |
| `shippingaddress1`       | string  | Shipping street address. Used for relevance.                                                                                                                                                                                                                                                                                                                          |
| `shippingcity`           | string  | Shipping city. Used for relevance.                                                                                                                                                                                                                                                                                                                                    |
| `shippingstate`          | string  | Shipping state or province. Used for relevance.                                                                                                                                                                                                                                                                                                                       |
| `shippingzipcode`        | string  | Shipping ZIP or postcode. Used for relevance.                                                                                                                                                                                                                                                                                                                         |
| `shippingcountry`        | string  | Shipping country (ISO 3166-1 alpha-2). Used for relevance.                                                                                                                                                                                                                                                                                                            |
| `cartItems`              | array   | Structured array of cart-line objects. Used for relevance.                                                                                                                                                                                                                                                                                                            |
| `adsexperience`          | string  | Pass `"shoppable"` when deliberately targeting a Shoppable Ads experience.                                                                                                                                                                                                                                                                                            |

### Placement position: Overlay placements

Overlay placements render on top of your confirmation screen in a Rokt-managed container, requiring no changes to your app's existing layout.

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

#### Overlay placement

```javascript
import MParticle from 'react-native-mparticle';

const attributes = {
  // Identity
  'email': 'j.smith@example.com',
  'firstname': 'Jenny',
  'lastname': 'Smith',
  'mobile': '+13125551515',

  // Transaction
  'confirmationref': '54321',
  '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 and paymentServiceProvider for Pay+)
  'paymenttype': 'credit_card',
  'paymentServiceProvider': 'cardpayment',
  'ccbin': '411112',

  // Billing address
  'billingaddress1': '123 Main St',
  'billingcity': 'Brooklyn',
  'billingstate': 'NY',
  'billingzipcode': '11201',

  // Shipping
  'shippingmethod': 'express',
  'shippingaddress1': '175 Varick St',
  'shippingcity': 'New York',
  'shippingstate': 'NY',
  'shippingzipcode': '10014',
  'shippingcountry': 'US',
};

const roktConfig = MParticle.Rokt.createRoktConfig('light');

MParticle.Rokt.selectPlacements(
  'RoktExperience', // identifier
  attributes,       // attributes map
  {},               // placeholders (empty for overlay)
  roktConfig,       // configuration
);
```

### Placement position: Embedded placements

Embedded placements render inline at a fixed position in your app that you control (for example, above the payment options on a cart screen). Both Thanks and Pay+ use embedded placements, but Pay+ must use embedded placements.

#### 1. Add RoktLayoutView to your view hierarchy

Place a `RoktLayoutView` in your screen at the position where you want the placement to render. Hold a `ref` to it so you can resolve its native node handle when calling `selectPlacements`.

#### 2. Resolve the node handle and call selectPlacements

Resolve the native node handle with `findNodeHandle`, build your attributes, and pass `placeholders` to `selectPlacements`. Trigger this when the embedded screen is ready to display offers.

#### Embedded placement

```javascript
import React, { ComponentRef } from 'react';
import { findNodeHandle } from 'react-native';
import MParticle, { RoktLayoutView } from 'react-native-mparticle';

const placeholder1 = React.createRef<ComponentRef<typeof RoktLayoutView>>();

const showRoktLayout = () => {
  const placeholders = {
      RoktEmbedded1: findNodeHandle(placeholder1.current),
  };

  const attributes = {
      'email': 'j.smith@example.com',
      'firstname': 'Jenny',
      'lastname': 'Smith',
      'billingzipcode': '90210',
      'confirmationref': '54321',
  };

  MParticle.Rokt.selectPlacements(
      'RoktExperience',
      attributes,
      placeholders,
  );
};

// Integrate the RoktLayoutView in the view hierarchy
<RoktLayoutView ref={placeholder1} placeholderName="RoktEmbedded1" />
```

For a declarative approach using the `RoktLayoutView` component without manually managing node handles, see [Appendix B: RoktLayoutView component](https://docs.rokt.com/integration-guides/ecommerce/sdk/react-native/#appendix-b-roktlayoutview-component).

> **Caution: Pay+**
>
> For Pay+ placements, include `paymenttype` and `paymentServiceProvider` in the `selectPlacements` call on each screen. `paymentServiceProvider` communicates what payment methods are available on the payment screen; `paymenttype` communicates what method the user paid with.

### Placement position: Interstitial placements (iOS only)

Interstitial placements are rendered between the payment and confirmation screens, allowing customers to purchase additional products. Interstitial placements are used by Shoppable Ads.

> **Note**
>
> Interstitial placements are supported on **iOS only** in the React Native SDK+. The Android path of this SDK+ does not support interstitial placements. The code below must only be invoked on the iOS path of your app.

To enable interstitial placements on iOS, first ensure the iOS-specific setup is complete:

1. Configure Apple Pay for your iOS app — create an Apple Pay merchant ID, configure your Xcode project, and generate a Payment Processing Certificate by following [Apple Pay — iOS setup](https://docs.rokt.com/developer-reference/product-deep-dives/shoppable-ads/payment-methods/apple-pay#ios-setup).
2. Register `RoktPaymentExtension` in your React Native iOS `AppDelegate` after `MParticle.sharedInstance().start()` and before `selectShoppableAds`. The registration snippet is included in the [iOS initialization code in Step 2](https://docs.rokt.com/integration-guides/ecommerce/sdk/react-native/#initialize-rn). If no payment extension is registered, Shoppable Ads can fire a `PlacementFailure` event.

> **Note: Expo**
>
> If you use Expo, include the Rokt kit in your config plugin (for example `iosKits: ["mParticle-Rokt"]` in `app.json`). The config plugin does not add the payment-extension registration automatically — after `expo prebuild`, add it to the generated `AppDelegate` on the same launch path as mParticle initialization, and re-apply it if you regenerate native projects with `--clean`.

Then call `selectShoppableAds` from your React Native JavaScript layer with the confirmation-screen identifier. The method returns a Promise and renders the Shoppable Ads experience as an overlay — no embedded placeholders are required. On iOS, the SDK+ renders it when an eligible offer is available.

#### Display Shoppable Ads (iOS only)

```javascript
import { Platform } from 'react-native';
import MParticle from 'react-native-mparticle';

// Interstitial placements are iOS only — do not invoke on Android
if (Platform.OS === 'ios') {
  const attributes = {
      // Identity
      'email': 'j.smith@example.com',
      'firstname': 'Jenny',
      'lastname': 'Smith',
      'mobile': '+13125551515',

      // Transaction
      'confirmationref': '54321',
      'currency': 'USD',
      'country': 'US',
      'language': 'en',
      'totalprice': '149.99',
      'amount': '137.50',

      // Customer context
      'newcustomer': 'false',
      'customertype': 'logged_in',
      'value': '2340.00',

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

      // Billing address
      'billingaddress1': '123 Main St',
      'billingcity': 'Brooklyn',
      'billingstate': 'NY',
      'billingzipcode': '11201',

      // Shipping (required for Shoppable Ads order fulfillment)
      'shippingaddress1': '175 Varick St',
      'shippingcity': 'New York',
      'shippingstate': 'NY',
      'shippingzipcode': '10014',
      'shippingcountry': 'US',
  };

  const roktConfig = MParticle.Rokt.createRoktConfig('system');

  // selectShoppableAds returns a Promise; listen for native Rokt events for purchase outcomes
  MParticle.Rokt.selectShoppableAds(
      'prod.rokt.conf', // use 'stg.rokt.conf' in test environments
      attributes,
      roktConfig,
  ).catch((error) => console.debug(error));
}
```

Subscribe to the `CartItemInstantPurchase` and related Shoppable Ads events via the [Events API](https://docs.rokt.com/integration-guides/ecommerce/sdk/react-native/#events-api) to handle purchase flows initiated from the interstitial experience.

### Optional functions

| Function                 | Purpose                        |
| ------------------------ | ------------------------------ |
| `MParticle.Rokt.close()` | Auto-close overlay placements. |

### Additional configuration

Pass optional parameters such as `RoktConfig` to customize the placement UI (e.g. dark/light mode, caching).

### selectPlacements with RoktConfig

```javascript
import MParticle from 'react-native-mparticle';

const roktConfig = MParticle.Rokt.createRoktConfig(
  'light',
  MParticle.Rokt.createCacheConfig(1200, { 'email': 'j.smith@example.com', 'orderNumber': '123' }),
);

MParticle.Rokt.selectPlacements(
  'RoktExperience',
  attributes,
  {},
  roktConfig,
);
```

> **Note**
>
> If you want to update the identifier `RoktExperience` or embedded identifier `RoktEmbedded1` with a different value, contact your Rokt account manager to ensure Rokt placements are configured consistently.

### Events API

The SDK+ provides placement lifecycle events through the `NativeEventEmitter` mechanism.

### Subscribe to placement events

```javascript
import { NativeEventEmitter } from 'react-native';
import MParticle from 'react-native-mparticle';

const eventManagerEmitter = new NativeEventEmitter(MParticle.RoktEventManager);

eventManagerEmitter.addListener('RoktEvents', data => {
  console.log(`event received ${JSON.stringify(data)}`);
});
```

#### Standard events

### Show all standard events

| Event                   | Description                                                                                                                                                                                                               | Params                                                                                                                                                                                  |
| ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| ShowLoadingIndicator    | Triggered before the SDK+ calls the Rokt backend.                                                                                                                                                                         |                                                                                                                                                                                         |
| HideLoadingIndicator    | Triggered when the SDK+ receives a success or failure from the Rokt backend.                                                                                                                                              |                                                                                                                                                                                         |
| PlacementInteractive    | Triggered when a placement has been rendered and is interactable.                                                                                                                                                         | placementId: String                                                                                                                                                                     |
| PlacementReady          | Triggered when a placement is ready to display but has not rendered content yet.                                                                                                                                          | placementId: String                                                                                                                                                                     |
| OfferEngagement         | Triggered when the user engages with the offer.                                                                                                                                                                           | placementId: String                                                                                                                                                                     |
| PositiveEngagement      | Triggered when the user positively engages with the offer.                                                                                                                                                                | placementId: String                                                                                                                                                                     |
| FirstPositiveEngagement | Triggered when the user positively engages with the offer for the first time.                                                                                                                                             | placementId: String                                                                                                                                                                     |
| OpenUrl                 | Triggered when the user presses a URL that is configured to be sent to the partner app.                                                                                                                                   | placementId: String, url: String                                                                                                                                                        |
| PlacementClosed         | Triggered when a placement is closed by the user.                                                                                                                                                                         | placementId: String                                                                                                                                                                     |
| PlacementCompleted      | Triggered when the offer progression reaches the end and no more offers are available to display. Also triggered when cache is hit but the retrieved placement will not be displayed as it has previously been dismissed. | placementId: String                                                                                                                                                                     |
| PlacementFailure        | Triggered when a placement could not be displayed due to some failure or when no placements are available to show.                                                                                                        | placementId: String (optional)                                                                                                                                                          |
| CartItemInstantPurchase | Triggered when the catalog item purchase is initiated by the user (iOS only).                                                                                                                                             | placementId: String, cartItemId: String, catalogItemId: String, currency: String, description: String, linkedProductId: String, totalPrice: number, quantity: number, unitPrice: number |

## 7. Appendix

### Appendix A: App configuration

Applications can pass configuration settings through `RoktConfig` so the SDK+ uses your app's custom configuration instead of system defaults.

#### ColorMode object

| Value    | Description                               |
| -------- | ----------------------------------------- |
| `light`  | Application is in Light Mode              |
| `dark`   | Application is in Dark Mode               |
| `system` | Application defaults to System Color Mode |

#### EdgeToEdgeDisplay (Android only)

This boolean controls whether the Rokt SDK+ renders in edge-to-edge display mode on Android (default `true`). Set to `false` if your app does not support edge-to-edge display.

```kotlin title="EdgeToEdgeDisplay"
import com.mparticle.rokt.RoktConfig

val roktConfig = RoktConfig.Builder()
    .edgeToEdgeDisplay(true)
    .build()
```

#### CacheConfig object

| Parameter         | Description                                                                                                                                                              |
| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `cacheDuration`   | Optional duration in seconds for which the Rokt SDK+ should cache the experience. Maximum allowed value is 90 minutes; default is 90 minutes if not provided or invalid. |
| `cacheAttributes` | Optional attributes to be used as cache key. If null, all attributes sent in `selectPlacements` will be used as the cache key.                                           |

```javascript title="RoktConfig with ColorMode and CacheConfig"
import MParticle from 'react-native-mparticle';

// Cache the experience for 1200 seconds, using email and orderNumber as the cache key.
const roktConfig = MParticle.Rokt.createRoktConfig(
    'light',
    MParticle.Rokt.createCacheConfig(
        1200,
        { 'email': 'j.smith@example.com', 'orderNumber': '123' }
    ),
);

MParticle.Rokt.selectPlacements(
    'RoktExperience',
    attributes,
    {},
    roktConfig,
);
```

### Appendix B: RoktLayoutView component

For embedded placements, the React Native SDK+ provides the `RoktLayoutView` component for a declarative approach to integrating Rokt placements in your app's view hierarchy. `RoktLayoutView` supports embedded placement types without the need to manually manage node handles.

```javascript title="Embedded placement with RoktLayoutView"
import React from 'react';
import { findNodeHandle, View } from 'react-native';
import MParticle, { RoktLayoutView } from 'react-native-mparticle';

const MyConfirmationScreen = () => {
    const placeholder1 = React.createRef();

    const handleSelectPlacements = () => {
        const placeholders = {
            RoktEmbedded1: findNodeHandle(placeholder1.current),
        };

        const attributes = {
            'email': 'j.smith@example.com',
            'firstname': 'Jenny',
            'lastname': 'Smith',
            'billingzipcode': '90210',
            'confirmationref': '54321',
        };

        MParticle.Rokt.selectPlacements(
            'RoktExperience',
            attributes,
            placeholders,
        );
    };

    return (
        <View>
            {/* Your confirmation screen content */}
            <RoktLayoutView ref={placeholder1} placeholderName="RoktEmbedded1" />
        </View>
    );
};
```

#### Parameters

| Parameter         | Type   | Description                                                                                                                     |
| ----------------- | ------ | ------------------------------------------------------------------------------------------------------------------------------- |
| `ref`             | Ref    | React ref used to get the native node handle for the placeholder map.                                                           |
| `placeholderName` | string | The embedded view identifier (e.g. `"RoktEmbedded1"`), must match the key in the placeholders map passed to `selectPlacements`. |

### Appendix C: Error handling

The IDSync API is intended to be central to your app's state and is designed to be fast and highly-available. Similar to how your app may prevent users from logging in, logging out, or modifying their state without an internet connection — treat these APIs as gating operations to maintain a consistent user state. The SDK+ will not retry API calls automatically, but provides callback APIs so you can do so according to your business logic.

If you do not implement error handling, you may see data consistency issues at scale.

```javascript title="IDSync error handling"
import MParticle from 'react-native-mparticle';

const request = new MParticle.IdentityRequest();
request.email = 'j.smith@example.com';

MParticle.Identity.identify(request, (error, userId) => {
    if (error) {
        // Inspect error.code to determine the cause:
        // - Network errors: retry the request
        // - Throttle errors (429): retry with backoff
        console.debug('Identity error:', error);
    } else {
        // Proceed with the identified user
        const user = new MParticle.User(userId);
        user.setUserAttribute('firstname', 'Jane');
    }
});
```

#### iOS error codes

On iOS, the native `MPIdentityErrorResponseCode` enum defines the following client-side codes. Inspect `error.code` in the native `onIdentifyComplete` callback to determine the cause:

| `MPIdentityErrorResponseCode`                   | Description                                                                            |
| ----------------------------------------------- | -------------------------------------------------------------------------------------- |
| `MPIdentityErrorResponseCodeRequestInProgress`  | An IDSync HTTP request was not performed because one is already in progress.           |
| `MPIdentityErrorResponseCodeClientSideTimeout`  | The IDSync HTTP request failed due to a TCP connection timeout.                        |
| `MPIdentityErrorResponseCodeClientNoConnection` | The IDSync HTTP request failed due to lack of network coverage.                        |
| `MPIdentityErrorResponseCodeSSLError`           | The IDSync HTTP request failed due to an SSL configuration issue.                      |
| `MPIdentityErrorResponseCodeOptOut`             | The IDSync HTTP request was not performed because the SDK+ is disabled due to opt-out. |
| `MPIdentityErrorResponseCodeUnknown`            | The IDSync HTTP request failed due to an unknown error.                                |

In addition to the client-side codes above, `error.code` may contain a server-generated HTTP status code:

| Value | Description                                                                                                                                                                                          |
| ----- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 400   | The IDSync HTTP call failed due to an invalid request body. Inspect the error details for more information.                                                                                          |
| 401   | The IDSync HTTP call failed due to an authentication error. Verify that your API key is correct.                                                                                                     |
| 403   | The IDSync HTTP call failed because this operation is not provisioned for your account. Contact your Rokt account manager to enable it.                                                              |
| 429   | The IDSync HTTP call was throttled and should be retried with exponential backoff. This may indicate a user "hotkey" or an incorrect implementation resulting in higher than expected IDSync volume. |
| 5xx   | The IDSync HTTP call failed due to a Rokt server-side issue. Contact your account representative for additional information.                                                                         |

#### Android error codes

On Android, the IDSync API always returns the HTTP status code and body of the underlying HTTP response. For client-side failures (device offline, timeout, invalid request), the SDK+ returns `IdentityApi.UNKNOWN_ERROR`. For throttling (HTTP 429), it returns `IdentityApi.THROTTLE_ERROR`. Handle both in your failure listener:

```kotlin title="Android IDSync error handling (Kotlin)"
MParticle.getInstance()?.Identity()?.identify(identifyRequest)
    ?.addFailureListener { identityHttpResponse ->
        if (identityHttpResponse?.httpCode == IdentityApi.UNKNOWN_ERROR) {
            // Device is likely offline — retry the request
        } else if (identityHttpResponse?.httpCode == IdentityApi.THROTTLE_ERROR) {
            // Throttled (429) — retry with backoff
        }
    }
```

### Appendix D: Passing session ID from web to native

When a user journey spans both web and native platforms, you can maintain a consistent Rokt session by passing the session ID from the Web SDK+ to the React Native SDK+. This is useful for hybrid flows where users complete an action in a WebView (such as a payment page) and return to the native app for confirmation.

#### Getting the session ID from Web SDK+

After calling `selectPlacements`, the session ID is available on the selection context:

```javascript title="Retrieve sessionId from the selection context"
const selection = await launcher.selectPlacements({
    identifier: "checkout",
    attributes: {
        email: "user@example.com",
        // ... other attributes
    }
});

const sessionId = await selection.context.sessionId;
```

> **Note**
>
> The **session ID** is a unique GUID assigned to the current user journey. It is useful for debugging and for correlating a user's activity across your web and native surfaces.

#### Passing to native app via deep link

Pass the session ID to your native app using a deep link:

```javascript title="Deep-link to native app"
const deepLink = `myapp://confirmation?sessionId=${encodeURIComponent(sessionId)}`;
window.location.href = deepLink;
```

#### Setting the session ID

Extract the session ID from the deep link in your native platform code and pass it to the SDK+ before calling `selectPlacements`. Handle this in your native AppDelegate (iOS) or Activity (Android) before the React Native layer loads:

```javascript title="Set sessionId from deep link (React Native)"
import { Linking } from 'react-native';
import MParticle from 'react-native-mparticle';

// Listen for incoming deep links
Linking.addEventListener('url', ({ url }) => {
    const sessionId = new URL(url).searchParams.get('sessionId');
    if (sessionId) {
        void MParticle.Rokt.setSessionId(sessionId);
    }
});
```

#### Notes

- Call `setSessionId` before `selectPlacements` to ensure the session is used.
- Empty strings are ignored and will not update the session.
- Always URL-encode the session ID when passing as a query parameter.

## 8. Test Your Integration

To confirm the SDK+ initializes and events log correctly:

### 1. Enable verbose SDK+ logging

Enable verbose SDK+ logging before initialization so you can see what's being sent.

```javascript title="Enable verbose SDK+ logging"
// For iOS verbose logging, add to your Swift AppDelegate:
// MParticle.sharedInstance().logLevel = .verbose

// For Android verbose logging, add to your Application class before MParticle.start():
// MParticle.setLogLevel(MParticle.LogLevel.VERBOSE)
```

### 2. Build and run against a development key

Build and run your app with the environment set to `Development`.

### 3. Trigger selectPlacements

Trigger `selectPlacements` on the screen where the placement should render and confirm the placement loads.

### 4. Verify events

Verify the events are logged and the `identifyRequest` call succeeds.

### Troubleshooting

If the placement doesn't render or events don't appear, check the native console (Xcode for iOS, Logcat for Android) for Rokt SDK+ errors. Common issues:

#### Initialization errors

- Confirm the key and secret in your native initialization match the values from your Rokt account manager.
- Confirm the native SDK+ `start` call runs before any `selectPlacements` or event logging calls.
- For iOS Shoppable Ads, confirm `RoktPaymentExtension` is registered after `start()` and before `selectShoppableAds`.

#### Identity errors

If the identity callback fires with an error, see [Error handling](https://docs.rokt.com/integration-guides/ecommerce/sdk/react-native/#error-handling-rn) for error codes and retry guidance. Without error handling you may see data consistency issues at scale.

#### Placement not rendering

- Confirm the placement `identifier` (e.g. `RoktExperience`) matches what your Rokt account manager configured.
- For embedded placements, confirm the embedded view identifier (e.g. `RoktEmbedded1`) matches the `placeholderName` on the `RoktLayoutView` component.
- Check that the attributes map contains at least `email`, `firstname`, `lastname`, `billingzipcode`, and `confirmationref`.
- For interstitial placements, confirm `Platform.OS === 'ios'` before calling `selectShoppableAds` — interstitial placements are not supported on Android.
