Extracting context for managed recommendations¶
When Hello Retail renders a managed Recommendation on your site, the recommendation algorithm often needs to know something about the page it is shown on: which product the visitor is looking at, its brand, where in the category tree the visitor is, or a custom value your filters depend on. Instead of requiring you to pass these values programmatically, a managed Recommendation can extract them directly from the page using a crawl config.
A crawl config is a small set of extraction rules written in a jQuery-inspired selector syntax. helloretail.js executes the rules in the visitor's browser, against the live DOM, right before the recommendation is requested. The extracted values are sent along with the request and become the recommendation's input context, every field is available to the algorithm as $input.<field>.
How it works¶
- helloretail.js finds the recommendation's placement on the page and prepares to load it.
- If the recommendation has a crawl config, each rule in it is evaluated against the page.
- The extracted values are sent to Hello Retail as the request context.
- The algorithm configured on the recommendation runs with that context:
url,urlsandproductNumbersidentify the products the recommendation is about (used by algorithms like related products and bought together), and every field can be referenced in filters and source conditions as$input.<field>.
If a recommendation has no crawl config, the context still contains the page URL, so if the URL matches a product URL in the product catalog, Product-based algorithms and filters still work. The crawl config is for everything beyond that.
The crawl config is edited on the recommendation itself in your Hello Retail Dashboard, under Recommendations → select a recommendation → Context for recommendation algorithm.
A first example¶
Say your product page marks up the brand and a color, and you want a "More from this brand" recommendation that also prefers the same color. This crawl config extracts both:
| Part | Meaning |
|---|---|
brand, extraData.color | The field name the value is stored under. Must be one of the known field names (see Field names); extraData.* accepts any custom name |
$("[itemprop=brand]") | A CSS selector, like jQuery's $(). Selects all matching elements on the page |
.text() | A processing method applied to the selection; here, the text content of the matched elements |
.data("color") | Reads the data-color attribute of the first matched element |
In the recommendation's algorithm you can then add a filter such as brand equals $input.brand, or a condition on $input.extraData.color, and the values extracted from the page are used every time the recommendation loads.
The syntax¶
A crawl config is one rule per line:
The source decides what data extracted from the page; the processing steps refine it.
Sources¶
title: $(".product-title")
currency: "EUR"
extraData.campaign: [$(".campaign-badge"), $(".sale-badge")]
extraData.pageUrl: url
| Source | Meaning |
|---|---|
$("css selector") | All elements matching the CSS selector. By default it is the result of querySelectorAll, the shop can be configured to use jQuery instead |
"text" | A fixed string literal |
[expr, expr, ...] | A list built from several expressions, each with its own source and processing steps |
Processing steps¶
Each step is applied to the result of the previous one, left to right:
| Step | Meaning |
|---|---|
.method() / .method(arg, ...) | Calls a method; either one of the Hello Retail methods below, or any method the current value has natively (string methods like .replace(), .split(), .trim(), .toLowerCase(); array methods like .join(), .slice()) |
.name | Reads a property, e.g. .length |
[index] | Picks one item from a list, e.g. [0] |
Method arguments can be numbers (2, -1, 0.5), strings ("text") or regular expressions (/pattern/flags, with the flags g, i, m and s).
If a rule fails, the selector matches nothing and a later step cannot run, or a method throws, the rule simply produces no value. A crawl config never breaks the page.
Hello Retail methods¶
These methods are provided by helloretail.js.
Reading values from elements¶
| Method | Returns |
|---|---|
.text() | The concatenated text content of all matched elements |
.attr("name") | The named attribute of the first matched element |
.data("name") | The data-name attribute of the first matched element. Multi-word attributes use camelCase: data-product-id is read with .data("productId") |
.html() | The inner HTML of the first matched element |
.val() | The value of the first matched form element |
.prop("name") | The named DOM property of the first matched element |
Narrowing a selection¶
| Method | Returns |
|---|---|
.first() / .last() | A selection containing only the first / last element |
.eq(n) | A selection containing only the element at index n |
.get(n) | The element at index n itself |
Conditions¶
| Method | Returns |
|---|---|
.exists() / .notExists() | true / false depending on whether the selection matched anything. Useful for boolean fields like inStock |
.matches(/pattern/) / .notMatches(/pattern/) | true / false depending on whether the value, as a string, matches the pattern. Also accepts a plain string argument |
Numbers¶
| Method | Returns |
|---|---|
.multiply(factor) | The value parsed as a number and multiplied by factor, e.g. .multiply(1.25) to add VAT |
.sum() | The sum of a list of numeric values |
Working with lists¶
| Method | Returns |
|---|---|
.fns("method", arg, ...) | Calls the named method on each item and collects the results, a map operation. E.g. .fns("attr", "href") turns a list of links into a list of URLs |
.insert(index, item, ...) | The list with the items inserted at index (-1 appends) |
.removeElements(index, count) | The list with count items removed from index |
.removeMatching("text") | The list without the items equal to the string (or matching, when given a /regex/) |
.asTags() | Wraps each item in its own single-item list: [a, b] becomes [[a], [b]]. Used with hierarchies to treat each crumb as its own top-level hierarchy |
How values are cleaned up¶
After the rules run, the extracted values are normalized before they are sent:
- A selection of elements that reaches the end of a rule is converted to the text content of each element (or a single string, when a method like
.text()or.attr()was already applied). urlandimgUrlare made absolute://,/pathand relative values get the page's protocol and domain prepended.priceand the other price fields are stripped of surrounding currency symbols and whitespace, so"DKK 1.299,00"style markup can be selected directly.hierarchiesmust end up as a list of hierarchies, where each hierarchy is a list of levels. Anything else is discarded, see the example below.
Extracting hierarchies¶
A breadcrumb usually holds one hierarchy with several levels, so wrap the selection in [...]:
This produces e.g. [["Clothing", "Women", "Dresses"]], one hierarchy without three levels. Without the brackets the result would be a flat list of strings and would be discarded. If each matched element is instead its own independent category, use .asTags():
which produces [["Sale"], ["News"]].
Field names¶
The left-hand side of a rule must be one of the known field names. The ones most relevant for Recommendations context:
| Field | Used for |
|---|---|
url, urls, productNumbers | Identify the products the recommendation is about. Algorithms like related products, bought together and others are looking at find products relative to these |
hierarchies | The category context, e.g. for filters like hierarchies matches $input.hierarchies |
title, brand, price, currency, inStock, ean, productNumber, imgUrl, description, keywords | Standard product fields, available to filters as $input.<field> |
extraData.<name>, extraDataList.<name>, extraDataNumber.<name> | Custom values, a single string, a list of strings, or a number. <name> is free-form, so this is the place for anything shop-specific |