Event API

The Events API accepts structured JSON events describing the interaction of the users with the website or mobile app. The events received via the Events API feed into the feedback loop, allow the system to learn and contribute to the performance of many of the models used in the background.

Note that sending events directly via the low-level API is an advanced use-case and you should consider using the JavaScript collector for websites. Using the Events API directly is mostly useful when:

The API can receive following types of events:

  • impression (“pv”) - which can hold information about a pageview (if the site has a URL available) or a catalog object shown to the user
  • click - which is used to capture interaction with the site, mainly with products lists
  • event - an event, which is analogous to impression, but triggered without an actual page reload - mainly if you need to report a new list, which appeared asynchronously.

All events are expected to be HTTP POST-ed to https://api.luigisbox.com.

Impression event

The impression event is a basic event which tracks a visit on a page (when a user visits a page that has URL). This event can be also used to track an object impression done by the user -- when the user displays a "detail" of any object that you have indexed in Luigi's Box catalog.

All impression events that track object are automatically paired to the catalog data using the "url" attribute, which must contain the object identity. The attribute is called url historically (you can read a story about the "why" here), but it holds the object identity.

You should send Impression event in these scenarios:

  • user visits any page on your website that has a URL (homepage, basket, ...)
  • user visits a detail of an object that is present in our catalog
    • Products
    • Category listing pages
    • Brand listing pages
    • Article (blog posts)

POST https://api.luigisbox.com/

{
  "type": "pv",
  "id": 6985277691922445000, // Globally unique identifier of the event
  "url": "2372711",   // In case of catalog object, use object identity, even though the field is called "url"
  "tracker_id": "1234-56678",
  "client_id": 6969470340316755000,
  // The rest of the attributes is optional, feel free to leave them out
  "title": "White sneakers GLX 23",
  "customer_id": 4739473924329473000,
  "local_timestamp": 1626386701,
  "app_version": "fe136c8",
  "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X x.y; rv:42.0) Gecko/20100101 Firefox/42.0",
  "referer": "",
  "context": {
    "warehouse": "Berlin"
  },
  "consent_granted": true,
  "from_list_id": "1abc2de3-f456-7890-1g23-hijk45l6789m"
}

The impression event defines the basic event structure that you'll be using for all other event types:

attribute explanation
typeREQUIRED Use pv for impression.
idREQUIRED Globally unique ID of the event
urlREQUIRED Object identity of the object as indexed in the Luigi's Box catalog
tracker_idREQUIRED The site's tracker_id, you can find it in the Luigi's Box application in "General settings" > "Integration settings" screen.
client_idREQUIRED A generated unique numeric identifier of the user.
customer_idoptional Your system identifier of the logged in user. Make sure that it is unique for each registered user.
local_timestampoptional Local timestamp in seconds. The event will be automatically timestamped by Luigi's Box servers and you don't have to send one explicitely. Make sure that the timestamp is in seconds and not in milliseconds. Sending an incorrect timestamp (in the future or too far in the past will cause the event to get droppped).
app_versionoptional Version string of your integration. Can be also used to explicitly differentiate platform (iOS, Android). You can use this field for segmentation in Luigi's Box analytics later.
user_agentoptional User agent string (read more).
titleoptional Title of the page. Only used for presentation in Luigi's Box analytics, has no impact on the feedback loop.
refereroptional Referer URL.
contextoptional Context of the session / user (e.g. used warehouse within session). Should hold the key-value pairs consistent with what is pushed into the catalog data. See context in analytics and the Multi-warehouse solution for a use-case.
consent_grantedoptional Set true, if a user has granted consent for personalization.
from_list_idoptional Identifier of the list from which the user was redirected to your site (e.g. identifier of the newsletter recommendation list). Only applicable for use-cases where you are generating recommendations into email newletters.
Pay special attention to local_timestamp and make sure that it is in seconds. A very common mistake that we see is that the timestamp is in milliseconds. If you send the timestamp in milliseconds, we will decode it to a date far in the future and drop the event as invalid.

Client ID vs. Customer ID

The client_id attribute is what identifies every user and maintains a continuity in the event stream of a single user. customer_id is an ID of the logged in customer that will not be available until the user signs in to you app/website. To reiterate:

  • Always send the client_id.
  • When the user signs in keeps sending both client_id and customer_id.
  • When the user signs out, keep sending just the client_id.

The client_id must always be the same for the same user even in the most complex scenario when the user starts as anonymous guest, signs in and then signs out. If you switch to a different client_id mid-session, the original session will be closed and a new session will start for the new user.

Search event

Report searches and search results as a search event which describes the search inputs (query and filters) and search results.

Note that the search API calls you make do not track data into analytics implicitely and you have to report searches explicitely. There are many reasons for this, mainly:
  • The analytics should track what the user has seen. Sometimes, you may want to filter out some products that the search API returned or display a slight variations of the results that the API returned.
  • The information presented to the user may be different than what the API returned, this is most frequently the case with B2B pricing where you load and display different prices for different customers.
  • Some information is only available on the frontend, such as you user ID or cookie consent information.

POST https://api.luigisbox.com/

{
 "id": 6667520098487994000,
 "tracker_id": "1234-5678",
 "client_id": 6667519810961010000,
 "type": "event",
 "lists": {
   "Search Results": {
     "items": [
       {
         "title": "White shirt v-neck",
         "type": "item", // The catalog type
         "url": "39818", // Object identity
         "position": 1,
         "price": 19
       },
       {
         "title": "White button-up shirt",
         "type": "item", // The catalog type
         "url": "288828", // Object identity
         "position": 2,
         "price": null
       },
       {
         "title": "White shirt, short-sleeves",
         "type": "item", // The catalog type
         "url": "928127", // Object identity
         "position": 3,
         "price": 351.36
       }
     ],
     "query": {
       "string": "white shirt",
       "filters": {
          "brand": "Loona fashion",
          "sort by": "price_amount:asc",
        }
     }
   }
 },
 "app_version": "fe136c8",
 "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X x.y; rv:42.0) Gecko/20100101 Firefox/42.0"
}

Search event contains a "Search Results" list (this exact name is important, do not change it) which contains list of search results and query definition including search query and search filters applied for that search.

Search results

The search results (inside the "items" attribute) contain the following attributes:

attribute explanation
titleREQUIRED Title of the item. Only used in Luigi's Box analytics for presentation purposes, has no impact on the feedback loop.
typeREQUIRED Type of the search result, consistent with the type that object is indexed with in the Luigi's Box catalog.
urlREQUIRED Identity of the object, consistent with how the object is indexed in the Luigi's Box catalog.
positionREQUIRED Position of the item in a list. Does not neccessarily have to start at 1, e.g. when sending an event for 2nd page of the search results, the position will be offset by the number of results on the previous page.
priceoptional Price of the item, used for presentation purposes in Luigi's Box analytics to calculate cart values.

If you are using pagination, then you must send a pv event for every subsequent pagination view. Positions of the items should be relative to the first page, e.g., if a use clicks on page 2 and you have 20 items per page, the first item position should be 21. If you are using infinite-scroll style pagination, make sure that you are only sending the list items that were appended to the infinite list and NOT all items from the beginning.

Query

The "query" part of the list consists of "string" and "filters". The query "string" is required and represents a query that the user typed in the searchbox, the "filters" part is optional and represents the filters that the user selected to narrow down the search. Read more about the concept of filters, including an example.

Filters can hold not only information about real filters, but also about other factors that influence search results and their ordering ("sort by" option) or even internal information with effect on search results (algorithm version etc.). You can segment sessions based on presence of filters later on in Luigi's Box Analytics application.

Autocomplete event

See the description of Search event above for more details. The Autocomplete has mostly the same structure and semantics. The notable differences from the Search event are:

  • The list name in the JSON data is "Autocomplete". It is important that you use exactly this name without modifications.
  • Autocomplete usually does not have any filtering, it is safe to skip the "filters" part inside "query".
  • Defer sending the Autocomplete event until the user stopped typing (we recommend a 500ms cutoff time). Even if you don't implement the defer, the Events API will automatically detect and ignore autocomplete queries which are prefix of a following query in the user's stream of events. The ignored list will not contribute to the feedback loop, it will however count towards your units usage.

POST https://api.luigisbox.com/

{
 "id": 6667520098487994000,
 "tracker_id": "1234-5678",
 "client_id": 6667519810961010000,
 "type": "event",
 "lists": {
   "Autocomplete": {
     "items": [
       {
         "title": "Shirts",
         "type": "category", // The catalog type
         "url": "c398818", // Object identity
         "position": 1
       },
       {
         "title": "White shirt v-neck",
         "type": "item", // The catalog type
         "url": "39818", // Object identity
         "position": 2,
         "price": 19
       },
       {
         "title": "White button-up shirt",
         "type": "item", // The catalog type
         "url": "288828", // Object identity
         "position": 3,
         "price": null
       },
       {
         "title": "White shirt, short-sleeves",
         "type": "item", // The catalog type
         "url": "928127", // Object identity
         "position": 4,
         "price": 351.36
       }
     ],
     "query": {
       "string": "white shirt"
     }
   }
 },
 "app_version": "iOS",
 "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X x.y; rv:42.0) Gecko/20100101 Firefox/42.0"
}

Recommendation event

Report recommended products as a recommendation event which describes the recommendation inputs (query and filters) and recommended objects.

Note that the recommender API calls you make do not track data into analytics implicitely and you have to report recommendations explicitely. There are many reasons for this, mainly:
  • The analytics should track what the user has seen. Sometimes, you may want to filter out some products that the recommender API returned or display a slight variations of the recommendations that the API returned.
  • The information presented to the user may be different than what the API returned, this is most frequently the case with B2B pricing where you load and display different prices for different customers.
  • Some information is only available on the frontend, such as you user ID or cookie consent information.

POST https://api.luigisbox.com/

{
 "id": 6667520098487994000,
 "type": "event",
 "tracker_id": "1234-5678",
 "client_id": 6667519810961010000,
 "lists": {
   "Recommendation": {
     "items": [
       {
         "title": "Off-white long-sleeve shirt",
         "type": "item",
         "url": "283838", // Object identity
         "position": 1,
         "price": 89
       },
       {
         "title": "Khaki slacks",
         "type": "item",
         "url": "881818", // Object identity
         "position": 2,
         "price": 45.50
       },
       {
         "title": "Knitted sweater",
         "type": "item",
         "url": "993939", // Object identity
         "position": 3,
         "price": 351.36
       }
     ],
     "query": {
       "filters": {
          "ItemIds": ["39818"],
          "RecommendationId": "1abc2de3-f456-7890-1g23-hijk45l6789m",
          "Recommender": "homepage_personalized",
          "RecommenderClientId": "homepage_personalized",
          "Type": "complementary_combined_assoc"
        }
     }
   }
 },
 "app_version": "iOS",
 "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X x.y; rv:42.0) Gecko/20100101 Firefox/42.0"
}

Each recommendation list event must contain query filters with the following key-value pairs. Values for the keys can be found in the recommendation request or recommendation request result.

key explanation
RecommenderClientIdREQUIRED Unique identifier of the recommender (recommender_client_identifier from recommendation result). Its value should define type of recommender user along with its position on the site (e.g., product_detail_bottom_alternatives). See Placement and model reuse for more details.
RecommendationIdREQUIRED Unique identifier of a set of recommended items (recommendation_id from recommendation result). Required for new integrations of Luigi's Box Recommender. We strongly recommend to update existing integrations as well.
ItemIdsoptional List of input items of a recommendation request (item_ids from recommendation request).
Recommenderoptional Name of the recommender (recommender from recommendation result).
Typeoptional Type of the recommender (recommendation_type from recommendation result).

RecommenderClientId

RecommenderClientId usually consists of three parts:

  • location of the recommender (e.g., item_detail, basket, basket_popup, homepage, news),
  • recommendation type (same as recommendation_type, e.g. personalized, optional),
  • A/B test variant (original/luigis, when not requesting Luigis' Box Recommender, always use original).

These three parts must always be lowercased and joined by a symbol _. Please, avoid using any other characters than a-z and _.

Several examples of Recommender Client Identifiers:

  • in item's detail:item_detail_complement_original, item_detail_original, item_detail_personalized_original,
  • basket: basket_popup_original, basket_original,
  • homepage: homepage_personalized_original, homepage_last_seen_original, homepage_trends_original,
  • other: category_original, news_original, discounted_original.

Click Event

Report a click event for any click interaction with search results, autocomplete results or recommendations.

POST https://api.luigisbox.com/

{
 "id": 6667521051615376000,
 "type": "click",
 "tracker_id": "1234-5678",
 "client_id": 6667519810961010000,
 "action": {
   "type": "click",
   "resource_identifier": "983838"
 },
 "app_version": "Mobile",
 "user_agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 13_5_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.1.1 Mobile/15E148 Safari/604.1"
}

Click event contains an action attribute:

attribute explanation
typeREQUIRED Must contain value click.
resource_identifierrequired Identity of the clicked item which points to a clicked item from the search results / recommendation. If the type of the clicked item is query, resource_identifier should contain its title. Otherwise, it should contain item identity exactly as it is reported in other lists (Autocomplete, Search Results, Recommendation).

Conversion event

Conversion event represents a user's explicit interest into an item displayed in a list (search, autocomplete or recommender). This will typically be "add to cart", "add to wishlist", "add to favorite".

POST https://api.luigisbox.com/

{
 "id": 6667522057510804000,
 "type": "click",
 "tracker_id": "1234-5678",
 "client_id": 6667519810961010000,
 "action": {
   "type": "buy",
   "resource_identifier": "https://www.eshop.com/another-product"
 },
 "app_version": "Mobile",
 "user_agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 13_5_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.1.1 Mobile/15E148 Safari/604.1"
}

Anything different from action.type "click" is considered a conversion (e.g., "buy", "add-to-favorites", "add-to-comparison"). Make sure to provide the resource_identifier (see "Click event" section above).

Send the conversion event from the following places:

  • The page/mobile app screen where the search/recommendation list is shown, e.g. a search results page, or a title page with a recommender box.
  • The product detail page/mobile app screen.

The identity in the resource_identifier field will be used to scan the event stream backwards and attribute the conversion to a prior list and service interaction.

Transaction event

To report a purchases use a transaction event, which contains all the items with their quantities and applied discounts.

POST https://api.luigisbox.com/

{
 "id": 6667520098487994000,
 "type": "transaction",
 "tracker_id": "1234-5678",
 "client_id": 6667519810961010000,
 "items": [
    {
      "title": "White shirt, round neck, short sleeves",
      "url": "9339993",
      "count": 1,
      "total_price": 19,
      "was_discounted": false,
      "was_volume_discounted": false
    },
    {
      "title": "Brown overcoat",
      "url": "299299",
      "count": 2,
      "total_price": 268.50,
      "was_discounted": true,
      "was_volume_discounted": false
    }
  ]
}

Each transaction must contain a list of items that were purchased. Each item is a hash with the following key-value pairs:

key explanation
titleoptional Title of the product.
urlREQUIRED Identity of the purchased product
countREQUIRED Quantity of the purchased product.
total_priceREQUIRED Price of the product after taking into account quantity, discounts, and volume discounts (e.g. product with price 10 was added to basket 3 times, thus total_price is 30).
was_discountedREQUIRED Determines, whether the product was discounted (true or false).
was_volume_discountedREQUIRED Determines, whether the product was discounted based on the quantity within purchase (true or false).

Scenarios

This section provides a rough guidelines for the events in different environments.

Web application

Note that these are just rough guidelines and the events may vary depending on your use case, the Luigi's Box services you use and the content that you index.

When Event
Product detail page shown Send Impression event for the product identity.
Category listing page shown Send Impression event for the category identity.
Brand listing page shown Send Impression event for the brand identity.
Search results shown Send Search event describing the search.
Autocomplete results shown Send Autocomplete event describing the autocomplete.
Search or autocomplete result clicked Send Click event with a resource_identifier set to the identity of the clicked object.
Recommendation shown Send Recommendation event describing the recommendations.
Recommendation clicked Send Click event with a resource_identifier set to the identity of the clicked object.
Product added to cart Send Converstion event with a resource_identifier set to the identity of the clicked object. Make sure to send this from every place where the product can be added to basket.
Transaction completed / products purchased Send Transaction event describing the purchase.

Mobile application

Note that these are just rough guidelines and the events may vary depending on your use case, the Luigi's Box services you use and the content that you index.

When Event
Product detail screen shown Send Impression event for the product identity.
Category listing screen shown Send Impression event for the category identity.
Brand listing screen shown Send Impression event for the brand identity.
Search results shown Send Search event describing the search.
Autocomplete results shown Send Autocomplete event describing the autocomplete.
Search or autocomplete result clicked Send Click event with a resource_identifier set to the identity of the clicked object.
Recommendation shown Send Recommendation event describing the recommendations.
Recommendation clicked Send Click event with a resource_identifier set to the identity of the clicked object.
Product added to cart Send Converstion event with a resource_identifier set to the identity of the clicked object. Make sure to send this from every place where the product can be added to basket.
Transaction completed / products purchased Send Transaction event describing the purchase.

Support

Troubles? Cannot get it to work? Contact us at support@luigisbox.com, we are glad to help!