Advanced Product Detail Page Integration

The product detail page of a retail website is where your products shine: customers discover all features of your products and decide, based on the available information, if they want to buy the product, continue their search, or simply abandon the session. The Froomle Personalization platform can help your products shine even brighter in a number of ways, two of which are discussed in this example. These are:

  • Similar products: Recommend products that are viewed by other users who also viewed this product. This will direct users to good candidates for products that do satisfy their needs if the current product failed.

  • Complementary products: Recommend products that are frequently bought together with the viewed product. This will create potential upsale opportunities where customers will buy more products in the same basket. Additionally these products can serve as inspiration, e.g. for outfits.

The example integration will cover both use cases simultaneously as you can request multiple lists per page in a single request to Froomle.

To set up a Froomle integration on a product detail page, there are three major steps:

Configuring the Froomle recommendations

Froomle provides the Configurations API to set up additional constraints on products to be recommended for a specific use case. For the product detail page there are a few obvious constraints you could configure:

Similar products

Only allow products of a specific brand

E.g. on the detail page of product X of brand Y you only want to recommend other products of brand Y.

Example configuration:

{
    "constraints": [{
        "query": {
            "key": "brand",
            "match": {
                "variable": {
                    "name": "brand"
                }
            }
        }
    }],
    "configuration_id": "specific_brand"
}

To correctly use this configuration, Froomle needs to know what brand a product belongs to. Therefore, a brand field needs to be included in your metadata dumps and the "brand" variable should be specified inside your recommendation request (see below).

Only allow items of a specific category

E.g. on the detail page of an item in category Z you only want to recommend other items of category Z.

Example configuration:

{
    "constraints": [{
        "query": {
            "key": "category",
            "match": {
                "variable": {
                    "name": "category"
                }
            }
        }
    }],
    "configuration_id": "specific_category"
}

To correctly use this configuration you will also have to provide Froomle with category information in your metadata dumps and specify the "category" variable inside your recommendation request (see below).

Complementary products

Only allow items up to a certain price

E.g. to boost the sale of accessories you only recommend items with a price lower than 20€.

Example configuration:

{
    "constraints": [{
        "query": {
            "key": "price",
            "range": {
                "max": 20,
                "min": 0
            }
        }
    }],
    "configuration_id": "max_price"
}

To correctly use this configuration you will also have to provide Froomle with price information in your metadata dumps.

Only allow items from specific categories

E.g. to boost the sale of accessories you only want to recommend items from the accessories category.

Example configuration:

{
    "constraints": [{
        "query": {
            "key": "category",
            "match": {
                "value": "accessories" (1)
            }
        }
    }],
    "configuration_id": "only_accessories"
}
1 Please be aware of the difference between this configuration and the previous configuration using match, this time we are not using a variable but the hardcoded value accessories

To correctly use this configuration you will also have to provide Froomle with category information in your metadata dumps.

Requesting recommendations

After setting up your configurations you are ready to start requesting recommendations from the Froomle Recommendations API. This Recommendations API lives at https://customer_token.froomle.com/api/environment/recommendations/requests. The Froomle support team will be in touch concerning your customer_token and environment.

Froomle can identify your users by either device_id or user_id. A device_id is anything that is tied to a specific device or browser, such as a cookie. A user_id is expected to be long-lived and used across devices, f.e. a login ID.

For the described use cases we would have to create the following recommendation requests:

Similar products

We will create a request that fetches 3 recommendations for both the specific_brand and specific_category configurations, our product detail page contains a product of brand "lego" and is found in the "toys" category.

{
    "page_type": "product_detail",
    "device_id": "BD3qoN3ko7URdparQX2vDT4",
    "user_id": "7081599607",
    "context_item": "917096",
    "lists": [
        {
            "list_name": "More from this brand",
            "configuration_id": "specific_brand",
            "list_size": 3,
            "brand": "lego"
        },
        {
            "list_name": "More in this category",
            "configuration_id": "specific_category",
            "list_size": 3,
            "category": "toys"
        }
    ]
}

One very important detail about this request is the context_item key. This represents the unique identifier of the product displayed on the product detail page and is used as context for generating the list of similar products.

After receiving the response we can merge both lists and display them in a single box of recommendations on our product detail page. Or alternatively, display two separate recommendation lists on our product detail page.

{
    "user_group": "froomle",
    "version": "Froomle_1",
    "device_id": "BD3qoN3ko7URdparQX2vDT4",
    "user_id": "7081599607",
    "request_id": "1285050",
    "lists": [
        {
            "list_name": "More from this brand",
            "configuration_id": "specific_brand",
            "list_size": 3,
            "limit": 3,
            "list_key": "biufwgbvilwabi274rbd",
            "items": [
                {
                    "item_id": "item_1",
                    "rank": 1
                },
                                {
                    "item_id": "item_2",
                    "rank": 2
                },
                                {
                    "item_id": "item_3",
                    "rank": 3
                }
            ]
        },
        {
            "list_name": "More in this category",
            "configuration_id": "specific_category",
            "list_size": 3,
            "limit": 3,
            "list_key": "nk5adbl45nlvd",
            "items": [
                {
                    "item_id": "item_4",
                    "rank": 1
                },
                                {
                    "item_id": "item_5",
                    "rank": 2
                },
                                {
                    "item_id": "item_6",
                    "rank": 3
                }
            ]
        }
    ]
}

Complementary products

We will create a request that fetches 3 recommendations for both the max_price and only_accessories configurations.

{
    "page_type": "product_detail",
    "channel": "website",
    "device_id": "BD3qoN3ko7URdparQX2vDT4",
    "user_id": "7081599607",
    "context_item": "917096",
    "lists": [
        {
            "list_name": "Complementary products",
            "configuration_id": "max_price",
            "list_size": 3
        },
        {
            "list_name": "Accessories",
            "configuration_id": "only_accessories",
            "list_size": 3
        }
    ]
}

One very important detail about this request is the context_item key. This represents the unique identifier of the product displayed on the product detail page and is used as context for generating the list of complementary products.

{
    "user_group": "froomle",
    "version": "Froomle_1",
    "device_id": "BD3qoN3ko7URdparQX2vDT4",
    "user_id": "7081599607",
    "request_id": "1285050",
    "lists": [
        {
            "list_name": "Complementary products",
            "configuration_id": "max_price",
            "list_size": 3,
            "limit": 3,
            "list_key": "biufwgbvilwabi274rbd",
            "items": [
                {
                    "item_id": "item_6",
                    "rank": 1
                },
                                {
                    "item_id": "item_5",
                    "rank": 2
                },
                                {
                    "item_id": "item_3",
                    "rank": 3
                }
            ]
        },
        {
            "list_name": "Accessories",
            "configuration_id": "only_accessories",
            "list_size": 3,
            "limit": 3,
            "list_key": "nk5adbl45nlvd",
            "items": [
                {
                    "item_id": "item_4",
                    "rank": 1
                },
                                {
                    "item_id": "item_1",
                    "rank": 2
                },
                                {
                    "item_id": "item_2",
                    "rank": 3
                }
            ]
        }
    ]
}

After receiving the response we can merge both lists and display them in a single box of recommendations on our product detail page. Or alternatively, display two separate recommendation lists on our product detail page.

Requesting cached recommendations

When a user leaves a product detail page and shortly after returns to the same product detail page, generating a new list of recommendations for the same product detail page can lead to a bad user experience. Recommendation responses are not guaranteed to be identical as our models are recomputed constantly and user event histories change as they view different products on your website. For product revisist that happen in a short window (e.g. 5 minutes) after the last recommendation request you should utilize our lists endpoint instead.

Integration events

Recommendations also introduce a set of extra integration events that you will have to communicate to Froomle. To link the original set of recommendations that is displayed with their events sent upon interaction, the recommendations API communicates a unique request_id in its response. You will see this is listed as a mandatory parameter for all the recommendation events.

Impression

Every time you display a box of recommendations it is important for us to know when each of the recommended items displayed in the box was visible to the user. Recommendations are often displayed "below the fold" meaning users have to scroll down on the product detail page before they can actually see them. A second example is a carousel that holds the recommendations, only a subset of the recommendations will be visible initially, when users "scroll" through the carousel other recommendations will be visible too. An impression event is used for each recommendation to communicate this information to Froomle.

Click on recommendation

Once a user interacts with a recommendation by clicking on a recommended item, you will have to communicate this interaction to Froomle by means of a click_on_recommendation event.

Combining use cases

As you might have noticed we request multiple lists inside the same recommendation request while we split up both of the described use cases in separate requests. In an actual integration where both use cases would be implemented on the same product detail page it wouldn’t make any sense to send two requests: it takes longer to get both responses compared to a single response and uses double the resources at Froomle. Sending a single request also has the added benefit that we at Froomle can make sure no items are recommended multiple times over the different lists.

We advise minimizing the request count for a single page to a single request to Froomle if your implementation supports this.

Combining both use cases could be achieved using the following request:

{
    "page_type": "product_detail",
    "channel": "website",
    "device_id": "BD3qoN3ko7URdparQX2vDT4",
    "user_id": "7081599607",
    "context_item": "917096",
    "lists": [
        {
            "list_name": "More from this brand",
            "configuration_id": "specific_brand",
            "list_size": 3,
            "brand": "lego"
        },
        {
            "list_name": "More in this category",
            "configuration_id": "specific_category",
            "list_size": 3,
            "category": "toys"
        },
        {
            "list_name": "Complementary products",
            "configuration_id": "max_price",
            "list_size": 3
        },
        {
            "list_name": "Accessories",
            "configuration_id": "only_accessories",
            "list_size": 3
        }
    ]
}