Finding your Top Products¶
Where productInsight answers "what do I know about this specific product?", the topProducts query answers the inverse question: "which of my products best match this criterion?". Given a performance dimension (best sold on Tuesdays, highest lifetime value, best candidates for a 10% discount), it returns a ranked list of your products.
Typical uses:
- Campaign targeting: "give me the 10 best products to promote this Tuesday"
- Discount optimization: "which products should get the 10% voucher?"
- Time-based promotions: "what sells on Saturday mornings?"
- Feeding ranked product lists into email campaigns, repricing engines or ad platforms
The API is available on the same URL as the rest of the Product Intelligence API, with the same authentication:
https://core.helloretail.com/pi/graphql
Products are ranked by how they perform on the requested dimension. Products with too little purchase history are excluded, so the results are backed by meaningful amounts of data.
The query¶
topProducts(
websiteUuid: String!
dimension: RankDimension!
weekday: Int
hourFrom: Int
hourTo: Int
discountPercentage: Int
filters: [MetricFilter]
limit: Int = 10
): [RankedProduct]
You can only request products for websites that you have access to.
Dimensions¶
The dimension argument selects what to rank by. Some dimensions need one or more extra arguments:
DAY_OF_WEEK: Products most often bought on a specific day of the week. Requiresweekday(Monday is 1, Sunday is 7).TIME_OF_DAY: Products most often bought within an hour window. RequireshourFromandhourTo(0-23, both inclusive; "around 5pm" could behourFrom: 16, hourTo: 18).DAY_AND_TIME_OF_DAY: Products most often bought on a specific day within an hour window. Requiresweekday,hourFromandhourTo.DISCOUNT: Products most likely to be purchased at a given discount level. RequiresdiscountPercentage(0-100).PRODUCT_LIFETIME_VALUE: Products whose buyers generate the most expected future revenue.RETENTION_RATE: Products whose buyers are most likely to come back and buy again.RECURRENCE_RATE: Products most likely to be repurchased.
Passing a dimension without its required arguments (or with arguments it does not accept) returns a validation error telling you which arguments are missing.
Filters¶
Results can optionally be narrowed with threshold conditions on the products' scalar metrics. Filters combine with AND:
filters: [
{metric: RETENTION_RATE, operator: GT, value: 0.4},
{metric: PRICE, operator: GTE, value: 50}
]
metric: One ofPRODUCT_LIFETIME_VALUE,RETENTION_RATE,RECURRENCE_RATEorPRICE.operator: One ofGT,GTE,LT,LTE.value: The threshold.
Note that PRICE filters on the typical price at which the product sells, which can differ from its current catalog price. Products without data for a filtered metric are excluded.
Limit¶
limit controls how many products are returned: default 10, maximum 100.
Example¶
query {
topProducts(
websiteUuid: "a7ce8931-6473-4627-9127-ceafa74ae0a8",
dimension: DISCOUNT,
discountPercentage: 10,
filters: [{metric: RETENTION_RATE, operator: GT, value: 0.4}],
limit: 3) {
url
title
productNumber
price
score
dimensionValue
retentionRate
}
}
Tip: Try copying the above query to the graphql tester, change the websiteUuid to one of your own websites, and execute the query.
This returns a result like:
{
"data": {
"topProducts": [
{
"url": "https://example.com/products/baggy-denim-jeans-5",
"title": "Baggy Denim Jeans",
"productNumber": "BDJ-005",
"price": 79.95,
"score": 0.8571,
"dimensionValue": 0.3921,
"retentionRate": 0.5914
},
{
"url": "https://example.com/products/slim-fit-chinos-2",
"title": "Slim Fit Chinos",
"productNumber": "SFC-002",
"price": 69.95,
"score": 0.6234,
"dimensionValue": 0.3105,
"retentionRate": 0.5321
},
{
"url": "https://example.com/products/wool-sweater-9",
"title": "Wool Sweater",
"productNumber": "WS-009",
"price": 119.00,
"score": 0.5102,
"dimensionValue": 0.2274,
"retentionRate": 0.4406
}
]
}
}
The returned products¶
Products are returned best first, ordered by their score: a 0-1 indication of how well the product matches the requested dimension. Higher is better.
Each result offers:
url: The product's URL, identifying it in your catalog.title: The product's display name.productNumber: The product's number in your catalog.price: The product's price.imgUrl: The product's image URL.score: How well the product matches the requested dimension, as a 0-1 score.dimensionValue: The product's value on the requested dimension. ForDAY_OF_WEEK, for example, this is the share of purchases that happen on that day.
In addition, every metric available on productInsight (productLifetimeValue, retentionRate, discountData, purchaseDayOfWeekData and the rest) can be selected directly on each result.
If no products match, because the filters exclude everything or your products lack data on the requested dimension, the query returns an empty list, not an error.
Example request using javascript¶
const query = `query {
topProducts(
websiteUuid: "{website id}",
dimension: DAY_OF_WEEK,
weekday: 2,
limit: 10) {
url
title
score
}
}`;
const response = await fetch("https://core.helloretail.com/pi/graphql?apiKey=XXX", {
"headers": {
"Content-Type": "application/json"
},
"body": JSON.stringify({query}),
"method": "POST"
});
console.log(await response.json());