> For the complete documentation index, see [llms.txt](https://docs.firework.com/firework-for-developers/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.firework.com/firework-for-developers/react-native-sdk/integration-guide-v2/analytics.md).

# Analytics (React Native)

## Video playback events

As follows, you could set `FireworkSDK.getInstance().onVideoPlayback` to receive video playback events. The event type is [VideoPlaybackEvent](https://eng.firework.com/react-native-firework-sdk/v2/interfaces/VideoPlaybackEvent.html).

```typescript
FireworkSDK.getInstance().onVideoPlayback = (event) => {
  console.log('[example] onVideoPlayback', event);
};
```

## Video feed click events

As follows, you could set `FireworkSDK.getInstance().onVideoFeedClick` to receive video feed click events. The event type is [VideoFeedClickEvent](https://eng.firework.com/react-native-firework-sdk/v2/interfaces/VideoFeedClickEvent.html).

```typescript
FireworkSDK.getInstance().onVideoFeedClick = (event) => {
  console.log('[example] onVideoFeedClick', event);
};
```

## Live stream events

As follows, you could set `FireworkSDK.getInstance().liveStream.onLiveStreamEvent` to receive live stream events. The event type is [LiveStreamEvent](https://eng.firework.com/react-native-firework-sdk/v2/interfaces/LiveStreamEvent.html).

```typescript
FireworkSDK.getInstance().liveStream.onLiveStreamEvent = (event) => {
  console.log('[example] onLiveStreamEvent', event);
};
```

## Live stream chat events

As follows, you could set `FireworkSDK.getInstance().liveStream.onLiveStreamChatEvent` to receive live stream chat events. The event type is [LiveStreamChatEvent](https://eng.firework.com/react-native-firework-sdk/v2/interfaces/LiveStreamChatEvent.html).

```typescript
FireworkSDK.getInstance().liveStream.onLiveStreamChatEvent = (event) => {
  console.log('[example] onLiveStreamChatEvent', event);
};
```

## Product click events

### Outstream PDP

If you would like to customize the product click event handling, you could use [onCustomTapProductCard](https://docs.firework.com/home/react-native-sdk/integration-guide-v2/shopping#oncustomtapproductcard) to support this use case. For example, you could open your product detail page when the user clicks on the product. We call this outstream PDP.

### Instream PDP

If you would like to use the SDK default behavior to handle the product click event, you could use [onClickProduct](https://eng.firework.com/react-native-firework-sdk/v2/classes/VideoShopping.html#onClickProduct) to support this use case. The SDK default behavior is opening Firework product detail page when the user clicks on the product. We call this instream PDP.

```typescript
FireworkSDK.getInstance().shopping.onClickProduct = async (event) => {};
```

## Shopping CTA click events

You could use [onShoppingCTA](https://docs.firework.com/home/react-native-sdk/integration-guide-v2/shopping#onshoppingcta) callback to receive shopping CTA click events.

## Video overlay CTA click events

1. If you would like to customize the overlay CTA click event handling, you could use [onCustomCTAClick](https://docs.firework.com/home/react-native-sdk/integration-guide-v2/video-feed#oncustomctaclick) to receive video overlay CTA click events. For example, you could open your product detail page when the user clicks on the overlay CTA.
2. If you would like to use the SDK default behavior to handle the overlay CTA click event, you could use [onVideoPlayback](https://docs.firework.com/home/react-native-sdk/integration-guide-v2/analytics#video-playback-events)(eventName is `VideoPlaybackEventName.ClickCTA`) to receive video overlay CTA click events. The SDK default behavior is opening the CTA link using the SDK webview or system browser when the user clicks the overlay CTA.

## Purchase tracking

The host app can record a purchase which will help get a full picture of the user journey flow. To do this, call [FireworkSDK.getInstance().trackPurchase](https://eng.firework.com/react-native-firework-sdk/v2/classes/FireworkSDK.html#trackPurchase) whenever the purchase happens.

{% hint style="info" %}
Call `trackPurchase` once per completed order, on the order confirmation step. Report **every** purchase without any client-side filtering — Firework identifies attributed vs non-attributed purchases server-side.
{% endhint %}

### Required fields

For Shopping V2 purchase tracking (parity with the Web `analytics.purchase` API), the following fields are required:

| Field          | Description                                                                             |
| -------------- | --------------------------------------------------------------------------------------- |
| `orderId`      | A unique identifier for the user's order.                                               |
| `value`        | The final amount paid, including taxes, shipping, and discounts. Sent as `order_value`. |
| `currencyCode` | The ISO 4217 currency code of the purchase value, e.g. `USD`.                           |
| `subtotal`     | The items cost before discounts, taxes, and shipping.                                   |
| `products`     | The purchased items, must be non-empty. Sent as `line_items`.                           |

Each entry in `products` requires `price` (the unit price, including line-level discounts), `quantity`, and at least one of `sku` or `extProductId`. `sku` can be the SKU, barcode, GTIN, MPN, or external id; when present it takes precedence over `extProductId`.

If any required field is missing, the SDK still forwards the event but logs a warning listing the missing fields.

### Sample code

```typescript
FireworkSDK.getInstance().trackPurchase({
  orderId: '<Order ID of User Purchase>', // Required
  value: 100, // Required. The final amount paid, including taxes, shipping and discounts
  currencyCode: 'USD', // Required. The ISO 4217 currency code
  subtotal: 90, // Required. The items cost before discounts, taxes and shipping
  countryCode: 'US', // Optional. The country code of the purchase
  shippingPrice: 10, // Optional. The shipping price of the order
  totalDiscounts: 5, // Optional. The total discounts applied to the order
  // Required, must be non-empty.
  products: [
    {
      extProductId: '<External Product ID>',
      price: 45, // The unit price, including line-level discounts
      quantity: 2,
      productName: '<Product Variant or Unit Name>', // Optional
    },
    // If you only have a SKU and no external product id, pass `sku` instead.
    // When both are present, `sku` takes precedence over `extProductId`.
    {
      sku: '<SKU/barcode/GTIN/MPN>',
      price: 19.99,
      quantity: 1,
    },
  ],
  // Any additional information associated to the purchase.
  // Reserved keys: order_id, order_value, value, currency, country,
  // shipping_price, subtotal, total_discounts, line_items, product.
  // Any values passed in the additionalInfo that use a reserved key will be ignored.
  additionalInfo: {
    additionalKey1: 'additionalValue1',
    additionalKey2: 'additionalValue2',
    additionalKey3: 'additionalValue3',
  },
});
```

## Conversion tracking

### Get feed id for VideoFeed and StoryBlock during component initialization

You could use onVideoFeedGetFeedId callback to get feed id for VideoFeed and StoryBlock during component initialization. The related reference links are:

1. [onVideoFeedGetFeedId callback for VideoFeed](https://eng.firework.com/react-native-firework-sdk/v2/interfaces/IVideoFeedProps.html#onVideoFeedGetFeedId)
2. [onVideoFeedGetFeedId callback for StoryBlock](https://eng.firework.com/react-native-firework-sdk/v2/interfaces/IStoryBlockProps.html#onStoryBlockGetFeedId)

```tsx
<VideoFeed 
  style={{ height: 200 }} 
  source="discover"
  onVideoFeedGetFeedId={(feedId) => {
    // The host app could store some custom info based on the feed id,
    // such as component name
  }}
/>

<StoryBlock 
  style={{ height: 200 }} 
  source="discover"
  onStoryBlockGetFeedId={(feedId) => {
    // The host app could store some custom info based on the feed id,
    // such as component name
  }}
/>
```

### Get feed id from event callbacks

Currently, the host app could get feed id from some event callbacks. For example:

<pre class="language-tsx"><code class="lang-tsx">FireworkSDK.getInstance().shopping.onShoppingCTA = async (event: ShoppingCTAEvent) => {
  const feedId = event.video.feedId;
  if (feedId) {
    // Get custom info based on the feed id
  }
}

FireworkSDK.getInstance().shopping.onCustomClickCartIcon = async (event) => {
  const feedId = event.video.feedId;
  if (feedId) {
    // Get custom info based on the feed id
  }
};


FireworkSDK.getInstance().shopping.onUpdateProductDetails = async (event) => {
  const feedId = event.video.feedId;
  if (feedId) {
    // Get custom info based on the feed id
<strong>  }
</strong>};

FireworkSDK.getInstance().shopping.onCustomTapProductCard = async (event) => {
  const feedId = event.video.feedId;
  if (feedId) {
    // Get custom info based on the feed id
  }
};

FireworkSDK.getInstance().onCustomCTAClick = async (event) => {
  const feedId = event.video.feedId;
  if (feedId) {
    // Get custom info based on the feed id
  }
}
</code></pre>
