Deliver recommendations (Google)
Deliver recommendations (Google)
This is for:
DeveloperIn this article, we’ll take an in-depth look at how you can use our Recommendations API to present your customers with one or more products or content pieces that may be of interest based on one of Google’s recommendations strategies.
Making a request
Called via a POST request:
POST https://recs.qubit.com/vc/recommend/2.1/<tracking_id>?strategy=<strategy_name>&n=<no_of_recs_to_return>&locale=<language-currency>&contextId=<contextId>
Prerequisites
Product catalog
To serve Google’s recommendations, we need to see 100 products across your product catalog generated from QP events or a product feed.
QP events
We need to see:
-
100 distinct product views (derived from
ecProduct
, whereeventType=detail
) -
For the strategies google_product_conversion and google_personal_conversion, 10,000
ecBasketItemAction
events, whereaction=add
for 100 distinct products -
For the strategy google_basket_revenue,
ecBasketItemTransaction
event for 100 distinct product Ids,product.productId
-
For the strategy google_product_similar, no events are required
Note
Reach out to your CSM if you have questions about the prerequisites for using any of Google’s recommendations strategies. |
Unique values
Before using the Recommendations API, you will require the following unique values:
Name | Description |
---|---|
|
Qubit tracking Id for the property the request is made from. This will be provided by Qubit’s Customer Success team |
|
Must match the |
A quick note on context_id
Google’s Recommendations AI strategies require a user Id (Qubit’s contextId
).
This should match the context.id
defined by Jolt, as shown in the following example id: '8lt0vannbw8-0jfc8hl8v-xj2r3pc'
:
context: {
viewTs: 1522310723801,
sessionViewNumber: 2,
entranceViewNumber: 2,
lifetimeValue: {
value: 0
},
sample: '77542',
timezoneOffset: -60,
viewNumber: 2,
sessionTs: 1522310705008,
entranceTs: 1522310705008,
conversionCycleNumber: 1,
id: '8lt0vannbw8-0jfc8hl8v-xj2r3pc',
sessionNumber: 1,
entranceNumber: 1,
conversionNumber: 0
}
Understanding the endpoint
Sample request
curl -X POST \
'https://recs.qubit.com/vc/recommend/2.1/demo_uk_prod?strategy=google_product_conversion&n=10&locale=en-gb-GBP&contextId=8lt0vannbw8-0jfc8hl8v-xj2r3pc&experienceId=203511' \
-H 'content-type: application/json' \
-d '{"h": ["all"]}'
Where:
-
demo_uk_prod
is the Qubit tracking Id for the property the request is made from. Your CSM at Qubit will provide this -
strategy
is one of Google’s Recommendations AI strategies and is mandatory. See Strategies for more information -
locale
is the locale you want to use. If not specified, defaults to the most common language/currency combination seen in your product catalog -
contextId
is thecontext.id
defined by Jolt -
experienceId
is the Id of a recommendations experience containing promotion or blacklisting rules you want to pass into your request -
h
is an optional parameter to define the history or seed to generate recommendations for. Can accept an array of product Ids/SKUs. See The recommendation seed for details and examples
Recommendations are typically generated using product Id. If you wish to use SKU instead, you’ll need to inform Qubit during the onboarding process. |
Note
Recommendations are generated using the products from across your entire product catalog and all provided locales.
For example, if you’re using the google_product_conversion |
Sample response
The Recommendations API will always generate a response with HTTP status 200 for any responses it has control over.
Leading-practice
Always check the status field to ensure that the response has been successful. |
The response body will be a JSON object containing the following fields.
Name | Description | Required |
---|---|---|
status |
HTTP status code of the response |
Yes |
result |
In case of errors, this will be a string. In other cases it will be another JSON object containing the data requested |
Yes |
segment |
Name of the server-side segment calculated for this visitor |
No |
annotations.segment |
JSON object containing additional data that pertains to the segment |
No |
annotations.strategy |
JSON object containing additional data that pertains to the strategy |
No |
Sample successful response
HTTP/1.1 200 OK
Content-Type: application/json;charset=utf-8
{
items: [
{
id: '5637911031',
weight: 0.07154133712308453,
details: {
category: 'Craft Essentials',
unit_sale_price: 1.5,
subcategory: 'Craft Paint',
url: 'http://www.crafters.co.uk/deco-art-crafters-acrylic-white-2oz/563791-1031',
sku_code: '5637911031',
unit_price: 1.5,
name: 'Deco art Crafters Acrylic White 2oz',
currency: 'GBP',
image_url: 'http://www.crafters.co.uk/supplyimages/563791_1031_1_170.jpg',
stock: 3,
id: '563791',
description: 'Deco art Crafters Acrylic White 2oz'
}
}
]
}
Sample unsuccessful responses
Invalid strategy or tracking Id
If either the strategy or tracking Id is invalid, we will return a response with status code 200, but with 0 results:
HTTP/1.1 200 OK
Content-Type: application/json;charset=utf-8
{
items: []
}
Missing tracking Id
If you make an error passing in the tracking Id for your property, we will return a response with status code 404:
HTTP/1.1 404 OK
Content-Type: application/json;charset=utf-8
{
"status": 404,
"message": "Requested URL /vc/recommend/2.1/ not found"
}
Missing strategy
If you omit a strategy from your request, we will return a response with status code 400:
{
"status": 400,
"message": "Invalid value for parameter 'strategy': required <class 'str'>"
}
A summary of Google’s strategies
The following table summarizes each of the Google strategies available to our customers. We’ve also included the name of the strategy as it displays in the Experience Hub.
Strategy Name | Description | Optimized for | Seed required | Name in Hub |
---|---|---|---|---|
google_product_conversion |
This strategy encourages visitors to buy more products by surfacing other products of interest, 'Others you may like', based on the product currently being viewed and the visitor’s own browsing and purchase history |
Conversion Rate |
Yes |
Convert based on a product and your history |
google_product_clickthrough |
This strategy encourages visitors to engage with more of your products by surfacing other products of interest, 'Others you may like', based on the product currently being viewed and the visitor’s own browsing and purchase history |
Clickthrough Rate |
Yes |
Engage based on a product and your history |
google_product_similar |
This strategy shows similar products to the one a visitor is viewing |
None |
Yes |
Similar products |
google_personal_conversion |
This strategy encourages visitors to buy more products by surfacing other products of interest, 'Recommended for you', based on the visitor’s own browsing and purchase history |
Conversion Rate |
No |
Convert based on your history |
google_personal_clickthrough |
This strategy encourages visitors to engage with more of your products by surfacing other products of interest, 'Recommended for you', based on the visitor’s own browsing and purchase history |
Clickthrough Rate |
No |
Engage based on your history |
google_basket_revenue |
This strategy encourages visitors to increase the value of the products in their basket by surfacing products 'Frequently bought together' with the products in the basket |
Revenue Per Order |
Yes |
Increase your basket value |
Example requests
In this section, we will look at how you can use Google’s strategies to deliver recommendations.
Strategy google_product_conversion
Encourage visitors to convert by recommending products that may be of interest, based on the Id of the seeded product IA61R3
and the visitor’s browsing and purchase history, obtained contextId
:
-
strategy=google_product_conversion
-
1A61R3
curl --request POST \
--url 'https://recs.qubit.com/vc/recommend/2.1/example_trackingId?strategy=google_product_conversion&locale=en-us&contextId=4rw8m5o5oc8-0k7aan7c0-ap149zk'
--header 'content-type: application/json' \
--data '{"h":["1A61R3"]}'
Strategy google_product_clickthrough
Encourage visitors to clickthrough by recommending products that may be of interest, based on the Id of the seeded product IA61R3
and the visitor’s browsing and purchase history, obtained from contextId
:
-
strategy=google_product_clickthrough
-
1A61R3
curl --request POST \
--url 'https://recs.qubit.com/vc/recommend/2.1/example_trackingId?strategy=google_product_clickthrough&locale=en-us&contextId=4rw8m5o5oc8-0k7aan7c0-ap149zk'
--header 'content-type: application/json' \
--data '{"h":["1A61R3"]}'
Strategy google_product_similar
Show similar products to the one a visitor is viewing, based on the Id of the seeded product IA61R3
.
-
strategy=google_product_similar
-
1A61R3
curl --request POST \
--url 'https://recs.qubit.com/vc/recommend/2.1/example_trackingId?strategy=google_product_similar&locale=en-us&contextId=4rw8m5o5oc8-0k7aan7c0-ap149zk'
--header 'content-type: application/json' \
--data '{"h":["1A61R3"]}'
Strategy google_personal_conversion
Encourage visitors to convert by recommending products that may be of interest, based on the visitor’s browsing and purchase history, obtained from contextId
:
-
strategy=google_personal_conversion
curl --request POST \
--url 'https://recs.qubit.com/vc/recommend/2.1/example_trackingId?strategy=google_personal_conversion&locale=en-us&contextId=4rw8m5o5oc8-0k7aan7c0-ap149zk'
Strategy google_personal_clickthrough
Encourage visitors to clickthrough by recommending products that may be of interest, based on the visitor’s browsing and purchase history, obtained from contextId
):
-
strategy=google_personal_clickthrough
curl --request POST \
--url 'https://recs.qubit.com/vc/recommend/2.1/example_trackingId?strategy=google_personal_clickthrough&locale=en-us&contextId=4rw8m5o5oc8-0k7aan7c0-ap149zk'
Strategy google_basket_revenue
Encourage visitors to add more items to their basket by recommending products that may be of interest, based on the Id of the seeded product IA61R3
and the visitor’s browsing and purchase history, obtained contextId
:
-
strategy=google_basket_revenue
-
1A61R3
curl --request POST \
--url 'https://recs.qubit.com/vc/recommend/2.1/example_trackingId?strategy=google_basket_revenue&locale=en-us&contextId=4rw8m5o5oc8-0k7aan7c0-ap149zk'
--header 'content-type: application/json' \
--data '{"h":["1A61R3"]}'
The recommendation seed
The seed parameter defines the products and product categories to generate recommendations for. If there is sufficient data about the provided seed, for example, products viewed or bought together with a product, we will return recommendations.
By adding or omitting a seed, you can use each strategy in the manner best suited to where you are adding the recommendations carousel.
Leading-practice
Although there are places where a single product Id should be used as the seed, for example, on product detail pages, where possible, we recommend using an array of product Ids as the seed to guarantee a richer, aggregated set of recommendations. This is especially true for a home page or a search page that hasn’t returned results from a product search. |
The recommendation seed will always be a product Id—or, if specified during onboarding, an SKU. |
Example seed
{
"h": ["W000277351"]
}
Where:
-
h
is an optional parameter to define the history or seed to generate recommendations for
A seed is considered contextual if the value is a product Id or an array of Ids:
{
"h": ["W000277351","W000277352","W000277353"]
}
And generic if the value is all
:
{
"h": ["all"]
}
Contextual seed
A contextual seed is obtained by passing specific product Ids to generate recommendations.
On product detail pages, you might generate recommendation for the product being viewed by passing its product Id:
curl -X POST \
'https://recs.qubit.com/vc/recommend/2.1/example_property?strategy=google_basket_revenue&locale=en-us&contextId=4rw8m5o5oc8-0k7aan7c0-ap149zk' \
-H 'content-type: application/json' \
-d '{"h": ["W000277351"]}'
On basket pages, you might generate recommendations for all of the products present in the shopper’s basket by passing an array of product Ids:
curl -X POST \
'https://recs.qubit.com/vc/recommend/2.1/example_property?strategy=google_basket_revenue&locale=en-us&contextId=4rw8m5o5oc8-0k7aan7c0-ap149zk' \
-H 'content-type: application/json' \
-d '{"h": ["W000277351","W000277352","W000277353"]}'
Leading-practice
By sending multiple product Ids, the endpoint will aggregate the results and return the top sorted recommendations. |
Generic seed
On the other hand, a generic seed is obtained by seeding the recommendation with all
.
For example, on a home page, it may make more sense to recommend trending products from across your product inventory:
curl -X POST \
'https://recs.qubit.com/vc/recommend/2.1/example_property?strategy=google_basket_revenue&locale=en-us&contextId=4rw8m5o5oc8-0k7aan7c0-ap149zk' \
-H 'content-type: application/json' \
-d '{"h": ["all"]}'
Per-request filters
Qubit offers the possibility to refine recommendations through the application of rules. These can be defined globally for your property or for one or more experiences in the Recommendations page.
For certain use cases, for example, where you wish to heavily promote a product by applying a higher weight (factor) than can be defined when adding rules in the platform, it might be appropriate to use rules on a per-request basis.
We refer to these rules as per-request filters
because they are restricted to the API request containing the filter and are then discarded.
Some important considerations
When calling the Recommendations API, per-request filters are added to any global rules defined in the platform and any experience-specific rules (if passed in your request). Observe the following points closely:
-
Per-request filters are restricted to the request containing them
-
Filters are added to global rules and any experience-specific rules (but only if you pass the experienceId in your request) but do not override them
-
The application of filters in requests containing multiple seeds is impractical. For this reason, filters are only applied to the first seed within the request
For information about adding global rules for blacklisting and promoting products in the Coveo Experimentation Hub, see Available Rules.
Let’s look at a simple per-request filter that includes blacklist and promotion elements. We have not passed an experienceId in the request, so the rules will only be added to globally-defined rules:
curl -X POST \
'http://localhost:6662/vc/recommend/2.1/example_property?strategy=google_basket_revenue&locale=en-us&contextId=4rw8m5o5oc8-0k7aan7c0-ap149zk' \
-H 'Content-Type: application/json' \
-d '{
"h":["all"],
"rules":[
{
"name":"Blacklist low price",
"condition":{ "<=":[ 0, { "var":"rec.unit_price" }, 30 ] },
"factor":0
},
{
"name":"Promote Shirts-Tops",
"condition":{ "in":[ "Shirts-Tops", { "var":"rec.categories" } ] },
"factor":200
}
]
}'
Where:
-
name
is the filter name, used for information purposes only -
condition
is the logic used to filter products - written in JsonLogic -
factor
determines whether the filtered products are blacklisted"factor":0
, or promoted (for example,"factor":1
,"factor":2
, etc) if condition evaluates as true
Looking at the previous example, the first rule blacklists products with a unit price less than or equal to 30. The second rule promotes products in the Shirts-Tops product category by a factor of 200. It’s worth remembering that a promotion rule added in the platform will apply a factor of 2.
To assist you in building filters, the JsonLogic site includes a playground for testing condition logic. To use the site, copy the entire condition value into Rule field:
{
"seed": <seed product details>,
"rec": <recommended product details>
}
For a list of supported operations, see Operations.
A quick look at weights and factors
Take note of the following points:
-
Weight determines the position in the recommendations carousel. The higher the weight, the higher the position
-
Where applied, factors impact the weight applied to a product from a particular strategy
weight x factor
:-
factor=0 (blacklisting) -> last position in carousel and filtered from it
-
factor=1 -> no effect
-
== factor=>1 (promotion) -> higher position in the carousel
-
Using regex
You can also use regex to define filters using the match operator.
If you want to use multiple regexes, then use match_some
instead of match
:
Example - match:
{
"name": "Blacklist product ids starting with RX_",
"factor": 0,
"condition": {
"match": [{"var": "rec.id"}, "^RX_.*$"]
}
}
Example - match_some:
{
"name": "Blacklist product ids containing test or starting with RX_",
"factor": 0,
"condition": {
"match_some": [{"var": "rec.id"}, ["^RX_.*$", ".*test.*"]]
}
}
Examples
Refer to the following examples that show how you can use per-filters.
Promotion
Promote products by a factor of 2 belonging to a specific brand in the product categories shoes and pants:
{
"name": "Brand promotion",
"condition": { "and": [
{"or": [
{ "in": [ "Shoes": { "var": "rec.categories" }]},
{"in": ["pants": { "var": "rec.categories" }]}
]},
{ "==": [ { "var": "rec.brand" }, "adidas" ] }
]},
"factor": 2
}
Same field filter
Only recommend products that are the same size as the returned seed product:
{
"name": "same size recommendations",
"condition": { "!=": [ { "var": "seed.size" }, { "var": "rec.size" } ] },
"factor": 0
}
Different field filter
Don’t recommend products that are the same size as the returned seed product:
{
"name": "different size recommendations",
"condition": { "==": [ { "var": "seed.size" }, { "var": "rec.size" } ] },
"factor": 0
}
Low stock
Don’t recommend products with less than ten items in stock:
{
"name": "low stock products filter ",
"condition": { "<": [ { "var": "rec.stock" }, 10 ] },
"factor": 0
}
Price range filter
Don’t recommend products with a price between 11 and 99 USD:
{
"name": "filter products with 10 < price < 100 USD",
"condition": {"and": [
{ "<": [ 10, { "var": "rec.price" }, 100 ] },
{ "==": [ { "var": "rec.currency" }, "USD" ] }
]},
"factor": 0
}
High price filter
Don’t recommend products that have a price higher than the returned product seed:
{
"name": "higher price recommendations",
"condition": { ">": [ { "var": "rec.price" }, { "var": "seed.price" } ] },
"factor": 0
}
Cross sale (blacklisting style)
Only recommend products from the category blow dryers
when viewing combs
:
{
"name": "only sell blow dryer with a comb",
"condition": { "and": [
{ "in": [ "combs", { "var": "rec.categories" }]}
{ "!": {"in": [ "blow dryer", { "var": "seed.categories" }]}}
]},
"factor": 0
}
Cross sale (promotion style)
Recommend blow dryers when viewing combs by a factor of 2:
{
"name": "promote blow dryers when viewing combs",
"condition": {"and": [
{"in": ["combs", { "var": "rec.categories" }]}
{"in": ["blow dryer", { "var": "seed.categories"}]}
]},
"factor": 2
}
Real-life example
In this real-life example, we demonstrate the possibilities when using per-request filters to customize the recommendation seed fully:
{
"rules": [
{
"name": "low stock config",
"condition": { "<": [ { "var": "rec.stock" }, 10 ] },
"factor": 0
},
{
"name": "low price config",
"condition": { "and": [
{ "<": [ { "var": "rec.price" }, 30 ] },
{ "==": [ { "var": "rec.currency" }, "GBP" ] }
]},
"factor": 0
},
{
"name": "blacklist config",
"condition": { "or": [
{ "in": [ "Adult", { "var": "rec.categories" }] },
{"match_some": [{"var":"rec.description"},["^Sample*", "*Tester.$"]]},
{ "==": [ { "var": "rec.is_clearance" }, true ] },
{ "in": [
{ "var": "rec.sku_id" },
[ "23757604", "23757639", ... ]
]}
]},
"factor": 0
},
{
"name": "promote products",
"condition": { "==": [ { "var": "rec.id" }, "24004952" ] },
"factor": 2
}
]
}
Debugging rules
You can output the rules object in the response by appending a query parameter debug=True
to the API request.
You can view this object to determine which rules, if any, are being used to filter a recommendation:
https://recs.qubit.com/vc/recommend/2.1/example_trackingId?strategy=google_basket_revenue&locale=en-us&contextId=4rw8m5o5oc8-0k7aan7c0-ap149zk&debug=True
In the following example, we see that a recommendation was filtered using a rule called Blacklist - out of stock
:
Calling the API in an experience
Basic
You can retrieve recommendations by passing through the Experience API (options)
.
Recommendations will be returned based on the defaults listed in the Configuration section below.
const recommendations = require('@qubit/recommendations')(options)
recommendations.get().then((recs) => {
console.log(recs)
})
Standard
If you are making only one type of recommendation request, where the strategy and number of products you wish to use will be the same, you can define this upfront by providing your own configuration.
You can override any key shown in Configuration section below.
const productId = options.state.get('productId')
const recommendations = require('@qubit/recommendations')(options, {
strategy: 'google_basket_revenue',
limit: 20,
seed: productId
})
recommendations.get().then((recs) => {
console.log(recs)
})
Advanced
Sometimes, we’re required to implement more a customized recommendations call. To do this, we specify our configuration at the time of making the request. This approach is useful if you need to make more than one request on a pageview.
Configuration passed to get overrides any configuration you pass when initializing the module, such as in the Standard example above.
Any keys you leave out will fallback to the configuration passed when initialized or to the defaults described in Configuration if no initial configuration was used.
const recommendations = require('@qubit/recommendations')(options)
recommendations.get({
strategy: 'google_basket_revenue',
limit: 30,
seed: [{ category: 'jeans' }, 'W000277351', { category: 'blazers' }],
rules: [{
condition: {
'!==': [{
var: 'rec.custom_field'
}, {
var: 'seed.custom_field'
}]
},
factor: 0
}]
}).then((recs) => {
console.log(recs)
})
Example
We will return id, weight, and strategy for every recommendation, so if you’re looping through the API response to render recommendations, this data will be immediately available to make the call.
Here’s an example of how you might choose to emit shown and clicked events:
const recommendations = require('@qubit/recommendations')(options)
recommendations.get().then((recs) => {
const $recs = recs.map((product, i) => {
const { details } = product
recommendations.shown(product)
return $(`
<div class="t001-rec">
<a href="${details.url}">
<img class="t001-img" src="${details.image_url}" />
<div class="t001-name">${details.name}</div>
<div class="t001-price">${details.unit_sale_price}</div>
</a>
</div>
`).click(() => {
recommendations.clicked(_.assign({ position: i + 1 }, product))
})
})
$(`.product-details`).append($recs)
}).catch(err => {
console.log(err)
})
Note
If you include this package in a Qubit experience, the get call should take place in triggers.js, so you can verify a response before activating. |
Configuration
You can override as little or as much of the configuration shown in the examples above.
strategy
-
type - String
-
default - none
-
options -
google_product_conversion
,google_product_clickthrough
,google_product_similar
,google_personal_conversion
,google_personal_clickthrough
,google_basket_revenue
locale
-
type - String
-
default - most common language/currency combination seen in your product catalog
limit
-
type - Number
-
default -
10
A number specifying the number of recommendations you wish to return.
If no recommendations are generated from the seed, the promise will be rejected. See timeout for details of how to handle errors.
seed
-
type - String or array
-
default -
all
As mentioned above, you can seed recommendations with product Ids/SKUs.
Product Ids/SKUs can be passed as a string. Place in an array to combine:
[{"W000277351","W000277352","W000277353"}]
timeout
-
type - Number
-
default -
0
The default of 0 milliseconds means no timeout will occur. Should you wish to cancel the loading of recommendations after a set period, pass the timeout key and attach a catch block to perform an alternate operation:
const recommendations = require('@qubit/recommendations')(options, {
timeout: 3000, // 3 sec
})
recommendations.get().then((recs) => {
console.log(recs)
}).catch((e) => {
// perform alternate action
})
trackingId
-
type - String
-
default -
options.meta.trackingId
Should you wish to request recommendations for a different property, perhaps to build on a staging environment, but would like to request production recommendations, this can be set here.
visitorId
-
type - String
-
default -
options.meta.visitorId
This package assumes usage within a Qubit experience.
If using elsewhere, you can specify how the Qubit Visitor Id should be found, typically via the _qubitTracker
cookie.
url
-
type - String
-
default -
https://recs.qubit.com/vc/recommend/2.1/
The Recommendations API endpoint.
Events
Metrics and reporting in Coveo Experimentation Hub
To enable the metrics and reporting features for a the Experimentation Hub Recommendations experience, implement the following events:
-
When a recommendation is shown/rendered onto the page:
recommendations.shown({
id: 'ABC123',
weight: '0.9',
strategy: 'pop'
})
-
When a recommendation is clicked:
recommendations.clicked({
id: 'ABC123',
weight: '0.9',
strategy: 'pop',
position: 1
})
Coveo Experience Hub
Refer to Product recommendations for details of which events need to be emitted to deliver product recommendations and Google’s product recommendations for details of events specifically for Google’s product recommendations.
We recommend also referring to our Events page to determine which events to emit.