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.
Prerequisites
| Prerequisite | Purpose |
|---|---|
| Read the Technical Reference | 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
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.
Example — a shopper adds a product, increments twice, then removes it:
cart {units: 1}→cart {units: 2}→cart {units: 3}→cart {units: 0}
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.
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
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
GET https://integration.retailer.citrusad.com/v1/events/ad/interaction
?adId=shotgun_0001
×tamp=2026-05-20T10:15:00Z
&sessionId=12345gsyuhf-6678ghsj
&productCode=prod-00001-01
&catalogId=catlg-custom-DAA001
&interactionType=productImpressionProduct Click
GET https://integration.retailer.citrusad.com/v1/events/ad/interaction
?adId=shotgun_0001
×tamp=2026-05-20T10:15:30Z
&sessionId=12345gsyuhf-6678ghsj
&productCode=prod-00001-01
&catalogId=catlg-custom-DAA001
&interactionType=productClickAdd to Cart from Ad
GET https://integration.retailer.citrusad.com/v1/events/ad/interaction
?adId=shotgun_0001
×tamp=2026-05-20T10:16:00Z
&customerId=cust-abc-123
&productCode=prod-00001-01
&catalogId=catlg-custom-DAA001
&interactionType=cart
&units=2
&conversionValue=29.99What 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 troubleshooting section.

