> For the complete documentation index, see [llms.txt](https://developers.citrusad.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://developers.citrusad.com/integration/reference/integrate-banner-x-shoppable-banner-interaction-reporting.md).

# Integrate Banner X Shoppable Banner Interaction Reporting

{% hint style="info" %}
Epsilon Retail Media's documentation is now centralized with our knowledgebase!

For up to date guides, please view [this page](https://help.citrusad.com/retail-media-interface/integration/data-api/api-overview/ad-interaction-events-reporting/integrate-banner-x-shoppable-banner-interaction-reporting) in the new Integration APIs space of our documentation.
{% endhint %}

A Shoppable Banner is a Banner X ad with multiple companion-product hotspots in one placement. Once these events flow, the campaign report breaks banner performance down to each companion product — impressions, clicks, and CTR (plus cart actions where integrated) — instead of a single banner-level total.

This guide covers only the Shoppable Banner interaction types. For the endpoint, authentication, core fields (`adId`, `timestamp`, tracking id), beacon mechanics, dedup, and testing, see the [Ad Interaction Events Reporting Technical Reference](/integration/reference/ad-interaction-events-reporting.md).

## Prerequisites

| Prerequisite                                                                              | Purpose                                                                                |
| ----------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- |
| Read the [Technical Reference](/integration/reference/ad-interaction-events-reporting.md) | Confirms endpoint, authentication, core fields, and deduplication requirements.        |
| Companion products configured on the Banner X creative                                    | Ensures product-level interactions can be attributed to the creative.                  |
| Served ads return a realised `adId`                                                       | Links each event to the delivered ad instance.                                         |
| `productCode` and `catalogId` available per companion product                             | Identifies the product and catalog used in reporting.                                  |
| Viewability rule agreed for product tiles                                                 | Defines when a product tile counts as seen for `productImpression`.                    |
| Consistent tracking id per ad session                                                     | Supports attribution and deduplication using `sessionId`, `customerId`, or `dtmToken`. |

## Interaction Types for Shoppable Banner Reporting

These are `adInteraction` events (no `moduleId`). Send the core fields plus the key fields below. `productImpression` and `productClick` are the two events that unlock the Products tab — fire both.

| `interactionType`   | Key fields                                                      | When to fire                                                  | Reporting purpose                                                           |
| ------------------- | --------------------------------------------------------------- | ------------------------------------------------------------- | --------------------------------------------------------------------------- |
| `productImpression` | `productCode`, `catalogId`                                      | A product tile/SKU becomes visible per your viewability rules | Per-product impressions — fills the impression column (and zero-click rows) |
| `productClick`      | `productCode`, `catalogId`                                      | Shopper clicks a product tile/SKU                             | Per-product clicks — drives clicks and CTR                                  |
| `creativeClick`     | `creativeId`                                                    | Click on a non-product creative element                       | Engagement with non-product creative                                        |
| `cart`              | `productCode`, `catalogId`, `units`, optional `conversionValue` | Cart change from the ad context                               | Add-to-cart intent / product value                                          |

## Viewability Rules for `productImpression`

| Rule                                             | Guidance                                                                                                                |
| ------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------- |
| Define when a tile counts as seen                | Agree a viewability rule, such as percentage visible plus time on screen, and apply it consistently across web and app. |
| Fire impressions once per viewability occurrence | Debounce scroll jitter and re-renders so a single sighting is not counted many times.                                   |

## Cart: Send Absolute Current Units

Fire `cart` on every cart interaction — initial add, each `+`, each `−`, and removal (back to `0`) — with `units` set to the absolute current unit count, not a delta. Re-sending the current total keeps counts correct under dedup. Add `conversionValue` when you have it.

{% hint style="info" %}
**Example** — a shopper adds a product, increments twice, then removes it:\*\* `cart {units: 1}` → `cart {units: 2}` → `cart {units: 3}` → `cart {units: 0}`
{% endhint %}

## Step-by-Step Implementation

### Step 1 — Capture Ad Context

Read the realised `adId` from the served ad, and `productCode`/`catalogId` for each companion tile. Establish one tracking id for the session and reuse it on impressions and clicks.

### Step 2 — Fire Product Impressions

When a tile meets your viewability rule, fire `productImpression` once for that product.

```javascript
navigator.sendBeacon(
  "https://integration.{retailer}.citrusad.com/v1/events/ad/interaction?" +
  new URLSearchParams({
    adId, interactionType: "productImpression", sessionId,
    timestamp: new Date().toISOString(), productCode, catalogId
  })
);
```

### Step 3 — Fire a Product Click

```javascript
navigator.sendBeacon(
  "https://integration.{retailer}.citrusad.com/v1/events/ad/interaction?" +
  new URLSearchParams({
    adId, interactionType: "productClick", sessionId,
    timestamp: new Date().toISOString(), productCode, catalogId
  })
);
```

### Step 4 — Fire Cart Changes

On add/update, fire `cart` with the absolute current `units` for that product (and `conversionValue` if you have it) — see the cart rule above.

## Sample Requests

Full GET URLs (line-wrapped for readability — send as a single encoded query string).

### Product Impression

```http
GET https://integration.retailer.citrusad.com/v1/events/ad/interaction
  ?adId=shotgun_0001
  &timestamp=2026-05-20T10:15:00Z
  &sessionId=12345gsyuhf-6678ghsj
  &productCode=prod-00001-01
  &catalogId=catlg-custom-DAA001
  &interactionType=productImpression
```

### Product Click

```http
GET https://integration.retailer.citrusad.com/v1/events/ad/interaction
  ?adId=shotgun_0001
  &timestamp=2026-05-20T10:15:30Z
  &sessionId=12345gsyuhf-6678ghsj
  &productCode=prod-00001-01
  &catalogId=catlg-custom-DAA001
  &interactionType=productClick
```

### Add to Cart from Ad

```http
GET https://integration.retailer.citrusad.com/v1/events/ad/interaction
  ?adId=shotgun_0001
  &timestamp=2026-05-20T10:16:00Z
  &customerId=cust-abc-123
  &productCode=prod-00001-01
  &catalogId=catlg-custom-DAA001
  &interactionType=cart
  &units=2
  &conversionValue=29.99
```

## What Good Looks Like

| Check                           | Detail                                                                                                                 |
| ------------------------------- | ---------------------------------------------------------------------------------------------------------------------- |
| Events return HTTP 200          | `productImpression` and `productClick` return HTTP 200 in PRE/QA.                                                      |
| Products tab is fully populated | Every configured companion product appears, including zero-engagement rows (impressions populate the zero-click rows). |
| Dedup is working                | Counts hold steady when you re-fire the same impression/click.                                                         |

## Troubleshooting (Shoppable Banner Specifics)

| Symptom                                      | Fix                                                                                                                                                                |
| -------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Required product events aren't arriving      | Confirm the banner is Banner X with companion products at the creative stage, and that `productImpression` and `productClick` fire with `productCode`/`catalogId`. |
| Impressions firing on every scroll/re-render | Fire one `productImpression` per product per viewability occurrence; debounce.                                                                                     |
| Products tab shows wrong or missing products | Likely a `productCode`/`catalogId` mismatch with the catalog — reconcile the IDs you send against the catalog feed.                                                |
| Cart units look wrong                        | You're sending deltas — send the absolute current `units`.                                                                                                         |

For general endpoint troubleshooting, see the [Ad Interaction Events Reporting Technical Reference](/integration/reference/ad-interaction-events-reporting.md) troubleshooting section.
