Skip to main content

Event Triggering Guide

This guide explains when to trigger each event type and what data to retain from the Recommendations API for proper attribution tracking across the customer journey.

Overview

The event system tracks the complete customer journey from recommendation display through purchase. Each event builds upon the previous ones, creating a complete attribution chain that enables accurate analytics and reporting.

Event Flow Sequence

The customer journey can follow different paths depending on user interactions:

Common Flow Patterns:

Pattern 1: Product Detail View

Recommendations API → Slot Impressions → Click (on product) → View Products → Add to Cart → Checkout → Purchase

Pattern 2: Direct Add to Cart

Recommendations API → Slot Impressions → Click (on add to cart button) → Add to Cart → Checkout → Purchase

Pattern 3: Direct Purchase

Recommendations API → Slot Impressions → Click (on buy now button) → Purchase

Pattern 4: View Without Click

Recommendations API → Slot Impressions → View Products (direct navigation) → Add to Cart → Checkout → Purchase

1. Recommendations API Call

Reference: Recommendations API

When to trigger: When displaying product recommendations to a customer

Data to retain: Store all slot-level attribution data with customer ID for long-term persistence

important

The data structure below shows the final stored data after both recommendations are received AND user clicks. The fields come from different sources:

  1. From Recommendations API (stored when recommendations are received)
  2. From Click Event (added when user clicks)
  3. Storage Metadata (added by implementation)

Data Structure to Store:

// FINAL STORED DATA STRUCTURE (after recommendations + clicks)
{
customerId: "xxxxxxxxxxxxxxxxxxxxxxx",
productRecommendations: {
[productRefId]: {
// Sponsored slot data (with click data added later)
sponsored: {
// === FROM RECOMMENDATIONS API ===
routeId: "xxxxxxxxxxxxxxxxxxxxxxx",
widgetId: "xxxxxxxxxxxxxxxxxxxxxxx",
recommenderId: "xxxxxxxxxxxxxxxxxxxxxxx",
campaignId: "xxxxxxxxxxxxxxxxxxxxxxx",
tacticId: "xxxxxxxxxxxxxxxxxxxxxxx",
tacticLabel: "Featured Products",
placementId: "xxxxxxxxxxxxxxxxxxxxxxx",
bannerId: "xxxxxxxxxxxxxxxxxxxxxxx",
adSetId: "xxxxxxxxxxxxxxxxxxxxxxx",
adSetVersion: 1,
costPerClick: 0.5,
costPerAction: 1.0,
costPerMille: 0.25,
timeStamp: 638481477292391000,
hmacSalt: "xxxxxxxxxxxxxxxxxxxxxxx",
hmac: "xxxxxxxxxxxxxxxxxxxxxxx",
supplierId: "xxxxxxxxxxxxxxxxxxxxxxx",
retailBoostCollectionCampaignId: "xxxxxxxxxxxxxxxxxxxxxxx",

// === FROM CLICK EVENT (added when user clicks) ===
clickId: "xxxxxxxxxxxxxxxxxxxxxxx",
eventTime: "2024-03-01T14:00:00.000Z",
currentUrl: "https://www.example.com/products",
actionType: 1,
contextType: 1,
redirectUrl: "https://www.example.com/product/detail",
referralUrl: "https://www.example.com/category",
clickPosition: 3
},

// Organic slot data (with click data added later)
organic: {
// === FROM RECOMMENDATIONS API ===
routeId: "xxxxxxxxxxxxxxxxxxxxxxx",
widgetId: "xxxxxxxxxxxxxxxxxxxxxxx",
recommenderId: "xxxxxxxxxxxxxxxxxxxxxxx",
campaignId: "xxxxxxxxxxxxxxxxxxxxxxx",
tacticId: "xxxxxxxxxxxxxxxxxxxxxxx",
tacticLabel: "Featured Products"
// Note: No placementId, bannerId, adSetId or other Retail Media fields for organic slots

// === FROM CLICK EVENT (added when user clicks) ===
clickId: "xxxxxxxxxxxxxxxxxxxxxxx",
eventTime: "2024-03-05T14:00:00.000Z",
currentUrl: "https://www.example.com/products",
actionType: 1,
contextType: 1,
redirectUrl: "https://www.example.com/product/detail",
referralUrl: "https://www.example.com/category",
clickPosition: 3
},

// === STORAGE METADATA ===
recommendationTime: "2024-03-01T14:00:00.000Z",
lastUpdated: "2024-03-05T14:00:00.000Z"
}
}
}

Storage Requirements:

  • Persistent storage by customer ID (not session-dependent)
  • Product-level association - each product recommendation stored separately
  • Separate sponsored and organic click storage - maintain both click types
  • Sponsored-first usage - when both sponsored and organic attribution exist, prefer sponsored and fall back to organic if needed
  • Long-term retention - keep data for attribution window (e.g., 30-90 days)
  • Attribution limit cleanup - remove stored attribution data once it falls outside the attribution window
  • Post-purchase cleanup - delete the specific attribution data (organic or sponsored) used in a Purchase event
  • Independent click tracking - sponsored and organic clicks don't overwrite each other

2. Slot Impressions Event

Reference: Slot Impressions Event API

When to trigger: When a recommendation slot is displayed to a customer

Required data:

  • Customer ID and session ID
  • Current URL where slot is displayed
  • Current slot's attribution data (from the recommendations API response for this specific slot)
  • Product information for each product in the slot
important

Use the current slot's data, not stored data. Multiple slots across different pages can display the same product, so you need the attribution data specific to the slot being displayed.

Key fields (from current slot's Recommendations API response):

  • routeId, widgetId, recommenderId, campaignId, tacticId, tacticLabel, placementId, bannerId
  • Retail Media fields (for sponsored content): adSetId, adSetVersion, costPerClick, costPerAction, costPerMille, timeStamp, hmacSalt, hmac, supplierId
  • retailBoostCollectionCampaignId (for retailer boost)

3. Click Event

Reference: Click Event API

When to trigger: When a customer clicks on a recommended product or banner

Required data:

  • Customer ID and session ID
  • Generated clickId (client-side unique identifier)
  • Product refId that was clicked
  • Current slot's attribution data (from the recommendations API response for this specific slot)
  • Action type and context type
important

Use the current slot's data for the Click event, not stored data. The stored data is used later for Add to Cart, Checkout, and Purchase events.

Critical requirements:

  • clickId is mandatory and must be generated client-side as a GUID during the Click event
  • Store clickId in appropriate slot (sponsored or organic) for later events
  • Separate storage for sponsored and organic clicks
  • Both sponsored and organic clicks contribute to attribution (sponsored attribution vs. organic attribution)

Route and Widget ID Requirements:

  • General Rule: Both routeId and widgetId are REQUIRED for click events
  • Exception: Route and Widget IDs are NOT required when ALL conditions are met:
    • contextType = NativeButton (ContextTypes.NativeButton = 11)
    • AND actionType is one of:
      • ClickBuyNow (ActionTypes.ClickBuyNow = 10)
      • ClickExternalBuyNow (ActionTypes.ClickExternalBuyNow = 11)
      • AddProductToWishlist (ActionTypes.AddProductToWishlist = 9)

Always Required Fields:

  • clickId, actionType, contextType, currentUrl, customerId, sessionId

Valid click types for attribution:

  • Sponsored clicks: Must have adSetId populated (for sponsored attribution)
  • Organic clicks: Must have valid routeId and widgetId (for organic attribution)
  • Native button clicks: Not attributed (not from recommendation slots)

4. View Products Event

Reference: View Products Event API

When to trigger: When a customer views a product page

Required data:

  • Customer ID and session ID
  • Product refId being viewed
  • Current URL of the product page

Attribution data (if available):

  • routeId, widgetId, recommenderId, campaignId, tacticId
  • referralUrl (if applicable)
  • bannerId (if applicable)

Data Source:

  • Use current slot's data if the user navigated from a recommendation slot
  • Send without attribution if the view was not initiated from a slot
note

View Products events should be sent for ALL product views, regardless of attribution. This provides complete analytics on product view counts. Attribution data is included when available, but the event is still sent even without attribution.

5. Add to Cart Event

Reference: Add to Cart Event API

When to trigger: When a customer adds a product to their shopping cart

Required data:

  • Customer ID and session ID
  • Product information (refId, quantity, price)
  • Attribution data (source depends on context)

Data Source:

  • From slot: Use current slot's data for the Click event, then use that Click event's data for Add to Cart
  • From elsewhere (product page, etc.): Generate Click event with native button context, then use that Click event's data for Add to Cart
important

Critical requirements:

  • Always generate Click event first before Add to Cart (regardless of source)
  • From slot: Click event uses current slot's data (routeId, widgetId, etc.) and gets stored
  • From elsewhere: Click event uses native button context (contextType: NativeButton, actionType: AddProductToCart) but does NOT get stored
  • Add to Cart uses the Click event's data (including the generated clickId)
  • Store both sponsored and organic clicks (both contribute to attribution) - native button clicks are not stored

Event Flow Scenarios:

Slot-Based Interactions (from Recommendation Widgets)

Scenario A: Click → View Products → Add to Cart

  1. First: Trigger Click event when user clicks on product in slot (generate clickId)
  2. Use current slot's data for the Click event (routeId, widgetId, etc.)
  3. Store: clickId in sponsored/organic data slot
  4. Then: Trigger View Products event when user views product page (use current slot's data)
  5. Finally: Trigger Add to Cart event when user adds product to cart (use stored data)

Scenario B: Direct Add to Cart from Slot

  1. First: Trigger Click event when user clicks "Add to Cart" button in slot (generate clickId)
  2. Use current slot's data for the Click event (routeId, widgetId, etc.)
  3. Then: Trigger Add to Cart event using the Click event's data (including clickId)
  4. Store: Attribution data for potential future use

Native Button Interactions (not from Recommendation Widgets)

Scenario C: Add to Cart from Product Page

  1. First: Trigger Click event when user clicks "Add to Cart" button on product page (generate clickId)
  2. Use native button context for the Click event (contextType: NativeButton, actionType: AddProductToCart)
  3. Then: Trigger Add to Cart event using the Click event's data (including clickId)
  4. Note: No routeId/widgetId needed for native button clicks
  5. Important: This Click event is NOT stored (native button clicks are not from recommendations)

Scenario D: View Products without Click

  1. First: Trigger View Products event (direct navigation) - with or without attribution
  2. Then: Trigger Add to Cart event when user adds product to cart
  3. Note: No clickId available - Add to Cart will fail validation
  4. Important: For this scenario, you would look for stored attribution data from previous interactions with this product

6. Checkout Event

Reference: Checkout Event API

When to trigger: When a customer initiates checkout process

Required data:

  • Customer ID and session ID
  • Checkout details (prices, currency, delivery info)
  • Product array with attribution data
  • Optional clickId for attribution tracking

Attribution data per product:

  • Include stored recommendation data for each product
  • Prefer sponsored attribution; use organic data only when sponsored is unavailable
  • routeId, widgetId, recommenderId, campaignId, tacticId
  • Retail Media fields if applicable (from sponsored click)
  • Retailer Boost fields if applicable (from sponsored click)

7. Purchase Event

Reference: Purchase Event API

When to trigger: When a customer completes a purchase

Required data:

  • Customer ID and session ID
  • Order details (orderId, payment method, currency)
  • Product array with attribution data
  • Optional clickId for attribution tracking

Attribution data per product:

  • Include stored recommendation data for each product
  • Prefer sponsored attribution; use organic data only when sponsored is unavailable
  • All Retail Media fields (if applicable, from sponsored click)
  • All Retailer Boost fields (if applicable, from sponsored click)

After submitting the Purchase event, remove the stored attribution data that was used (organic or sponsored) for the purchased products to prevent reuse beyond the attribution window.

Implementation Best Practices

1. Data Storage Strategy

Frontend Storage Options:

  • Local Storage: Persistent across browser sessions
  • Cookies: Can be set with expiration dates

Storage Key Structure:

// Recommended key format
const storageKey = `pa_recommendation_${customerId}_${productRefId}`;

// Store recommendation data persistently
function storeRecommendationData(customerId, productRefId, data) {
// For frontend implementation
const key = `pa_recommendation_${customerId}_${productRefId}`;
localStorage.setItem(key, JSON.stringify({
...data,
lastUpdated: new Date().toISOString()
}));

// For backend implementation
// Store in database with customerId + productRefId as key
}

// Retrieve stored data for events
function getStoredRecommendationData(customerId, productRefId) {
// For frontend implementation
const key = `pa_recommendation_${customerId}_${productRefId}`;
const stored = localStorage.getItem(key);
return stored ? JSON.parse(stored) : null;

// For backend implementation
// Retrieve from database
}

2. Click ID Management

important

The clickId must be generated as a GUID format during the Click event. It is only stored for recommendation-based clicks (sponsored/organic) for later use in follow-up events. Native button clicks are not stored.

// Generate click ID when user clicks
function handleProductClick(productRefId, clickData) {
const clickId = generateGUID(); // Must be a GUID format

// Get existing stored data or create new
let storedData = getStoredRecommendationData(customerId, productRefId);
if (!storedData) {
storedData = {
refId: productRefId,
sponsored: null,
organic: null,
recommendationTime: new Date().toISOString()
};
}

// Determine if this is a sponsored or organic click
const isSponsored = clickData.adSetId && clickData.adSetId.length > 0;

// Store click data in appropriate slot (including the generated clickId)
// Only store recommendation-based clicks (sponsored/organic), not native button clicks
if (isSponsored) {
storedData.sponsored = {
clickId: clickId, // Store the generated clickId for later use
eventTime: new Date().toISOString(),
...clickData
};
} else if (clickData.routeId && clickData.widgetId) { // Only store organic clicks from recommendations
storedData.organic = {
clickId: clickId, // Store the generated clickId for later use
eventTime: new Date().toISOString(),
...clickData
};
}
// Native button clicks (contextType: NativeButton) are not stored

storedData.lastUpdated = new Date().toISOString();
storeRecommendationData(customerId, productRefId, storedData);

// Send click event
sendClickEvent({
clickId: clickId,
refId: productRefId,
...clickData
});

// Handle different click actions
if (clickData.actionType === 2) { // AddProductToCart
// Trigger Add to Cart event immediately
sendAddToCartEvent(productRefId, 1, clickData.price);
} else if (clickData.actionType === 10) { // ClickBuyNow
// Trigger Purchase event immediately
sendPurchaseEvent(productRefId, 1, clickData.price);
}
// For other action types (like OpenProductPage), let the user navigate naturally
}

3. Event Attribution

// Get the most recent valid click data for attribution
function getAttributionData(customerId, productRefId) {
const storedData = getStoredRecommendationData(customerId, productRefId);

if (!storedData) {
return null;
}

// Check if we have sponsored click data
if (storedData.sponsored && storedData.sponsored.clickId) {
return storedData.sponsored;
}

// Check if we have organic click data
if (storedData.organic && storedData.organic.clickId) {
return storedData.organic;
}

return null;
}

// Handle View Products event with optional attribution
function handleProductPageView(productRefId) {
const attributionData = getAttributionData(customerId, productRefId);

const eventData = {
refId: productRefId,
currentUrl: window.location.href,
eventTime: new Date().toISOString()
};

// Add attribution data if available (from Recommendations API)
if (attributionData) {
Object.assign(eventData, {
routeId: attributionData.routeId,
widgetId: attributionData.widgetId,
recommenderId: attributionData.recommenderId,
campaignId: attributionData.campaignId,
tacticId: attributionData.tacticId,
tacticLabel: attributionData.tacticLabel,
placementId: attributionData.placementId,
bannerId: attributionData.bannerId,
referralUrl: attributionData.referralUrl
});
}

// Always send View Products event, with or without attribution
sendViewProductsEvent(eventData);
}


// Use stored data for follow-up events
function sendAddToCartEvent(productRefId, quantity, price) {
const attributionData = getAttributionData(customerId, productRefId);

if (!attributionData || !attributionData.clickId) {
throw new Error('No click ID found - must have click event first');
}

const eventData = {
clickId: attributionData.clickId,
product: { refId: productRefId, quantity, price },
// Include all attribution fields (from Recommendations API)
routeId: attributionData.routeId,
widgetId: attributionData.widgetId,
recommenderId: attributionData.recommenderId,
campaignId: attributionData.campaignId,
tacticId: attributionData.tacticId,
tacticLabel: attributionData.tacticLabel,
placementId: attributionData.placementId,
bannerId: attributionData.bannerId
};

// Add Retail Media fields if this was a sponsored click
if (attributionData.adSetId) {
Object.assign(eventData, {
adSetId: attributionData.adSetId,
adSetVersion: attributionData.adSetVersion,
costPerClick: attributionData.costPerClick,
costPerAction: attributionData.costPerAction,
costPerMille: attributionData.costPerMille,
timeStamp: attributionData.timeStamp,
hmacSalt: attributionData.hmacSalt,
hmac: attributionData.hmac,
supplierId: attributionData.supplierId
});
}

// Add Retailer Boost fields if applicable
if (attributionData.retailBoostCollectionCampaignId) {
eventData.retailBoostCollectionCampaignId = attributionData.retailBoostCollectionCampaignId;
}

sendAddToCartEvent(eventData);
}

Common Pitfalls

1. Missing Click Events

  • Problem: Trying to send Add to Cart without Click event
  • Solution: Always generate click event first, store clickId (for both sponsored and organic recommendation clicks)

2. Session-Dependent Storage

  • Problem: Storing recommendation data only for current session
  • Solution: Use persistent storage by customer ID (localStorage or cookies)

3. Missing Attribution Fields

  • Problem: Not including all required attribution fields
  • Solution: Store and include all fields from recommendations API

4. Organic vs Sponsored Clicks

  • Problem: Not understanding that both organic and sponsored clicks contribute to attribution
  • Solution: Both organic and sponsored clicks contribute to attribution (different types of attribution)

5. Separate Sponsored and Organic Storage

  • Problem: Overwriting sponsored clicks with organic clicks or vice versa
  • Solution: Store sponsored and organic clicks in separate slots
  • Benefit: Preserves both click types for proper attribution

Summary

  • Store recommendation data persistently by customer ID using localStorage or cookies
  • Always generate Click events before Add to Cart events (two-step process)
  • Include all attribution fields in follow-up events (including all Retail Media fields)
  • Both sponsored and organic clicks contribute to attribution (different types)
  • Store sponsored and organic clicks separately - maintain both click types independently
  • Use appropriate click data for attribution based on click type
  • Send View Products events for ALL product views - with attribution when available, without attribution when not
  • Maintain data consistency across all events in the customer journey

This ensures accurate attribution tracking and enables proper analytics and reporting for your recommendation campaigns.

Data Source Summary

For each event, use the appropriate data source:

EventData SourceWhen
Slot ImpressionsCurrent slot's dataAlways use the current slot's Recommendations API response
Click EventCurrent slot's dataAlways use the current slot's Recommendations API response
View ProductsCurrent slot's data OR No attributionUse current slot if navigating from slot, no attribution if not from slot
Add to CartClick event dataAlways generate Click event first, then use Click event's data for Add to Cart
CheckoutStored dataAlways use stored attribution data
PurchaseStored dataAlways use stored attribution data