Integrate recommendations: developer reference
For custom integrations beyond the auto-generated snippet, use the JavaScript SDK or REST API to request recommendations, or Jinja to embed them in email campaigns and weblayers. This reference covers request parameters, runtime catalog filter operators, and event tracking.
For the snippet and channel deployment links, see Deploy recommendations.
Request recommendations
Request recommendations using:
- The
getRecommendation()method from the JavaScript SDK library. - The REST API directly.
Parameters
| Parameter | Type | Description | Example |
|---|---|---|---|
recommendationId (required) | String | ID of the recommendation. Generated when you save it. | 5a7c4dfefb6009323d4c7311 |
fillWithRandom / fill_with_random (Jinja) | Boolean | If true, fills any shortfall with random catalog items that match the filter conditions | true |
size | Integer (default 10) | Number of items to return. Maximum suggested value is 100. | 50 |
items | Object | Item ID used to generate context-based results. Note: the item field in the Preview tab is for testing only—specify item_id in code. | {'item_123': 1} |
catalogFilter / catalog_filter (Jinja) | Array of objects | Adds runtime constraints on top of the template's static catalog filter. | See Catalog filter operators. |
categoryNames (required for Popular in category) | Array (max 10) | Currently viewed category or categories. | ['shoes', 'high heels'] |
Jinja limitationWhen calling recommendations in Jinja—in emails, blocks, weblayers, managed endpoints, and other assets—
recommendationIdmust be a constant string. You can't use variables or parameters in its place. This limitation doesn't apply to the JavaScript SDK or REST API.
For the full specification, see the personalization guide.
Integrate via Jinja
Use Jinja to call recommendations in email campaigns, weblayers, and other campaign channels. Access item properties with {{ item.<attribute> }}.
Simple integration
This example iterates over recommendation results and renders each item as a list element with a title link.
<ul id="recommendations">
{% for item in recommendations('5a7c4dfefb6009323d4c7311') %}
<li>
<a href="{{ item.url }}">{{ item.title }}</a>
</li>
{% endfor %}
</ul>
Advanced integration with parameters
This example returns 50 items, passes a reference item, and applies a runtime category filter:
<ul id="recommendations">
{% for item in recommendations('5a7c4dfefb6009323d4c7311',
fill_with_random = true,
size = 50,
items = {"item_123": 1},
category_names = ["shoes", "men"],
catalog_filter = [{
"property": "category_2",
"constraint": {
"type": "string",
"operator": "contains",
"operands": [{
"type": "constant",
"value": "shoes"
}]
}
}]
) %}
<li>
<a href="{{ item.url }}">{{ item.title }}</a>
</li>
{% endfor %}
</ul>
If the engine can't return enough items, fill_with_random = true fills the gap with random catalog items that match the filter conditions.
Use different recommendations in one campaign
By default, recommendations() call with the same ID and parameters returns identical results to the same customer across a campaign. To return different results at each call, set cached=False:
{% for item in recommendations('5a7c4dfefb6009323d4c7311', cached=False) %}
Catalog filter operators
Runtime catalog_filter values support the following operators. For static catalog filtering configured in the Design tab, see Configure template: Optional merchandising fields.
For more detail, see Personalization in Jinja.
Important
catalog_filterparameter isn't supported for the Filter based template.
String
Operators: is set, is not set, has value, has no value, equals, does not equal, in, not in, contains, does not contain, starts with, ends with, regex.
catalog_filter = [{
"property": "category_2",
"constraint": {
"type": "string",
"operator": "in",
"operands": [
{'type': 'constant', 'value': 'ABC'},
{'type': 'constant', 'value': 'DEF'}
]
}
}]
Number
Operators: equal to, in between, less than, greater than, is set, is not set, has value, has no value.
catalog_filter = [{
"property": "price",
"constraint": {
"type": "number",
"operator": "in between",
"operands": [
{"type": "constant", "value": "1"},
{"type": "constant", "value": "200"}
]
}
}]
Boolean
Operators: is.
catalog_filter = [{
"property": "in_stock",
"constraint": {
"type": "boolean",
"operator": "is",
"value": "true"
}
}]
List
Use list-type operators with catalog fields that contain arrays of values—for example, tags, genres, or regions.
Operators: contains matching (matches at least one value), contains all (matches all specified values).
Prerequisites:
- Catalogs using the schema-based catalog infrastructure (Data hub item collection on unified setups).
- List attributes configured as searchable fields in catalog settings.
- Product data with properly formatted list attributes (arrays of strings or numbers).
catalog_filter = [{
"property": "tags",
"constraint": {
"type": "list",
"operator": "contains all",
"operands": [
{"type": "constant", "value": "sale"},
{"type": "constant", "value": "featured"}
]
}
}]
For more examples, see List-attribute filtering use cases.
Track performance
Implement event tracking to measure recommendation performance after deployment.
Events to track
| Event | When to fire | action value |
|---|---|---|
| Click | A customer clicks a recommended item | click |
| Show | Recommended items load successfully | show |
| Timeout | Loading exceeds 1,000 ms | timeout |
NoteClick tracking requires custom implementation for email campaigns. Add tracking code to capture those events explicitly.
Sample tracking code
This example combines A/B testing with show, click, and timeout tracking:
var PLACEMENT = "homepage";
exponea.getAbTest("rcm_" + PLACEMENT, {
"Variant A": 50,
"Control Group": 50
}, function (variant) {
if (variant == "Variant A") {
var RCM_STATUS = 0;
var onRecommendationsLoaded = function (data) {
if (RCM_STATUS !== "TIMED_OUT") {
RCM_STATUS = "LOADED";
exponea.track("recommendation", {
action: "show",
variant: variant,
item_ids: itemIds,
});
// render items and add click listeners
exponea.track("recommendation", {
action: "click",
variant: variant,
item_id: itemId,
});
}
};
exponea.getRecommendation({
recommendationId: "RECOMMENDATION ID HERE",// replace with your recommendation ID from the Web deployment tab
callback: onRecommendationsLoaded,
});
setTimeout(function () {
if (RCM_STATUS !== "LOADED") {
RCM_STATUS = "TIMED_OUT";
exponea.track("recommendation", {
action: "timeout",
variant: variant,
});
}
}, 1000);
} else if (variant == "Control Group") {
exponea.track("recommendation", { action: "show", variant: variant });
// add click listeners to fallback items
exponea.track("recommendation", { action: "click", variant: variant, item_id: itemId });
}
});Implementation notes
Handle empty, partial, and timed-out responses
Recommendation requests aren't guaranteed to return the full number of items you request. If fillWithRandom is false, the engine may return fewer items than size—or none at all—when it can't find enough matching recommendations.
Handle the following outcomes:
- Full response: Render the returned items normally.
- Partial response: Render the available items even if fewer than size are returned.
- Empty response: Hide the placement or show fallback content.
- Timeout: Stop waiting and fall back gracefully.
Handle timeouts
If your placement has a strict loading budget, add a client-side timeout and show fallback content when the request doesn't complete in time.

