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:

Parameters

ParameterTypeDescriptionExample
recommendationId (required)StringID of the recommendation. Generated when you save it.5a7c4dfefb6009323d4c7311
fillWithRandom / fill_with_random (Jinja)BooleanIf true, fills any shortfall with random catalog items that match the filter conditionstrue
sizeInteger (default 10)Number of items to return. Maximum suggested value is 100.50
itemsObjectItem 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 objectsAdds 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 limitation

When calling recommendations in Jinja—in emails, blocks, weblayers, managed endpoints, and other assets—recommendationId must 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_filter parameter 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

EventWhen to fireaction value
ClickA customer clicks a recommended itemclick
ShowRecommended items load successfullyshow
TimeoutLoading exceeds 1,000 mstimeout
📘

Note

Click 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.

© Bloomreach, Inc. All rights reserved.