# 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:

  1. Event Logging: They record that a specific action occurred (e.g., "User X viewed Product Y").

  2. 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 the product_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 or custom_data for 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.

  1. product_id (String/Number): The unique identifier from your database (e.g., SKU or ID).
  2. 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:

  1. Network Tab: Open the developer tools and filter for requests containing /api/product_event/.
    • Status: 200 OK indicates the event was successfully sent.
    • Payload: Verify the JSON payload contains your product_id and event_type.
  2. 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_id matches 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).