# Product Events
Product Events are a specialized class of user interactions designed specifically for E-commerce and Catalog-based applications. They allow you to track the lifecycle of a product—from a "View" to an "Add to Cart"—to power recommendation engines and abandoned cart automations.
# Introduction
Unlike standard events which are static logs of behavior, Product Events serve a dual purpose:
Event Logging: They record that a specific action occurred (e.g., "User X viewed Product Y").
Product Indexing: They update the global profile of the product in your User.com database.
# Method signature
To track these interactions, you use the standard userengage function with a reserved keyword.
userengage('product_event', productObject)
keyword(String): Must be strictly'product_event'.productObject(Object): A dictionary containing theproduct_id,event_type, and product attributes.
# Capabilities & scope
# The "Product Profile" logic (Critical)
It is vital to understand that Product Events overwrite product details.
- Behavior: Every time you send a
product_event, the system updates that product's global attributes (Name, Image URL, Category) with the latest values provided. - Consequence: You cannot store historical state in product attributes.
- Example: If a user adds a generic "T-Shirt" to the cart today for $20, and you change the name to "Vintage T-Shirt" and price to $30 tomorrow, the user's past event history will reflect the current name and price ($30), not the value at the time of the event.
Warning: Do not use Product Attributes to track fixed transaction data (like
transaction_value). Use Orders (Backend), Custom Event orcustom_datafor immutable records.
# Supported event types
The event_type field is strictly typed. You must use one of the following specific strings. Custom strings are not supported in this field.
| Event Type | Typical Use Case |
|---|---|
view | User loads a product detail page (PDP). |
add to cart | User adds an item to their basket. |
remove | User removes an item from their basket. |
purchase | (SDK Not Recommended) Essential for recommendations, but best sent via Backend (Orders) to ensure data integrity. |
liking | User "hearts" or likes an item. |
add to observation | User adds item to a wishlist/watchlist. |
click | User clicks a product card on a listing page. |
detail | Viewing specific technical details. |
promo click | Clicking a banner promoting the product. |
return, refund | Post-purchase logic. |
checkout, checkout option | Steps within the funnel. |
# Implementation
# Required fields
Every product event must include these two keys.
product_id(String/Number): The unique identifier from your database (e.g., SKU or ID).event_type(String): One of the specific strings listed above.
# Scenario 1: Single product view
Use this on your Product Detail Page (PDP).
Best Practice: We generally do not recommend passing full product details (like Name, Price, or Description) from the frontend. Since these values update the global Product Profile, inconsistent data from different users/browsers can overwrite your catalog with incorrect values. Ideally, you should only pass the product_id, and let your backend integration or XML Product Feed handle the product data synchronization.
However, if you do need to update a product's details on the fly, you can include attributes like name or image_url alongside the ID.
// Recommended: Pass only ID and Type
userengage('product_event', {
product_id: 'SKU-12345',
event_type: 'view'
});
# Scenario 2: Handling multiple items (The Cart Loop)
The SDK does not support passing an array of products in a single call. If a user performs an action on multiple items (e.g., "Checkout" or adding a bundle), you must iterate through them.
const cartItems = [
{ id: '101', price: 12.00 },
{ id: '205', price: 85.00 }
];
// CORRECT: Loop and fire individually
cartItems.forEach(item => {
userengage('product_event', {
product_id: item.id,
event_type: 'add to cart',
// Optional: Custom Data for context (see below)
custom_data: {
cart_session_id: 'sess_998877'
}
});
});
# Scenario 3: Using custom_data for context
Since product attributes can be overwritten, use the custom_data object to store permanent facts about the specific event.
- Use Case: Recording the specific price at that moment or a coupon code used.
userengage('product_event', {
product_id: 'SKU-999',
event_type: 'add to cart',
// Permanent Event Data (Stored only with this specific event)
custom_data: {
price_at_moment: 150.00, // Safe historical record
discount_applied: 'WINTER_SALE_20',
size_selected: 'XL',
variant_id: 'v_999_XL' // Distinct from parent product_id
}
});
# Verification
To verify your Product Events are firing correctly:
- Network Tab: Open the developer tools and filter for requests containing
/api/product_event/.- Status:
200 OKindicates the event was successfully sent. - Payload: Verify the JSON payload contains your
product_idandevent_type.
- Status:
- User Timeline: Go to the specific user's timeline in your app.
- Success: You should see a timeline entry: "Product event occurrence".
- Note: If the timeline shows the event but the product details (name, image) are missing, ensure the
product_idmatches a product already imported into your catalog. The recommended method for importing products is via the XML Product Feed (Settings > App Settings > Products > Product feeds).