Skip to content

    Pre-launch API. The concepts described here are settled, but the API shape is not: request and response fields, parameters and defaults can still change. Build against it, and talk to your Luigi's Box contact before you put an integration into production.

    Recommendations

    View source

    A recommender takes anchors — the products the current context is about — and returns items related to them. A surface for pages with nothing to anchor on answers with the most popular products.

    POST /discovery/v1/recommender serves every placement: the product page strip, the cart cross-sell, the homepage carousel, the abandoned-basket email.

    Terminal window
    curl -X POST 'https://api.eu1.luigisbox.ai/discovery/v1/recommender?channel_id=lbn_4hj9tv&surface_id=lbs_recommender_similar' \
    -H 'Authorization: Bearer <token>' \
    -H 'X-Lbx-Visitor-Id: 8f14e45f-ea0f-4b5c-9a1d-2b3c4d5e6f70' \
    -H 'Content-Type: application/json' \
    -d '{
    "type": "product",
    "touchpoint": "pdp",
    "anchor_ids": ["product/sku-1001"],
    "size": 8
    }'
    Query parameterRequiredNotes
    channel_idYesServing destination
    surface_idYesMust be a recommender surface
    Body fieldRequiredDefaultNotes
    typeYes—Usually product
    touchpointNononeWhere the recommendations appear. Any of the touchpoints — a recommender serves every one
    anchor_idsNononeUp to 50 object identities the recommendation is based on
    exclude_idsNononeUp to 50 object identities to keep out of the slate
    sizeNo101–100
    filtersNononeFilter tree
    return_fieldsNosurface defaultUp to 100 fields — see Selecting fields
    user_id / personalizeNoanonymous / truePersonalization

    Anchors are full typed identities, exactly as they appear in @id, in one array:

    { "anchor_ids": ["product/sku-1001", "product/sku-2087"] }

    A bare value with no type — "sku-1001" — is rejected with a 422, and so is an anchor whose type is not the one the surface is configured to take.

    There is no sort and no cursor: a recommender returns one fixed-size slate.

    {
    "hits": [
    { "@id": "product/sku-2087", "@type": "product", "@title": "Blue Linen Shirt", "price": 44.9 }
    ]
    }

    Recommendations are a fixed-size slate, not a browsable result set, so the response carries no cursor and no count: there is no page two of a carousel, there are no facets over one, and the slate is hits — its length is the count. There is no request_key either: the slate is not cached, so neither /facets nor /variants can address it.

    Which model runs, what it considers related, and how it treats the anchors are all the surface’s configuration — not request fields. A surface is called from every page that shows the same recommendations, and a place that needs its own tuning or business rules has a surface of its own:

    RecommenderAnchors you sendCalled fromSurface, by example
    Similar itemsThe product being viewedProduct pagelbs_recommender_similar
    Bought togetherThe product being viewedProduct pagelbs_recommender_xsell_pdp
    Bought togetherEvery product in the cartCartlbs_recommender_xsell_basket
    Bought togetherThe product just addedThe add-to-cart popuplbs_recommender_xsell_basket_popup
    Popular productsNoneHomepage, landing pages, category or brand stripslbs_recommender_popular

    The three bought-together surfaces read the same model. They are separate so that each place carries its own tuning and its own campaigns, which target surfaces, not touchpoints.

    A recommendation never returns its anchors. By default it also leaves out the other variants of each anchor (the same product in another colour or size), so a shopper on a product page is not shown the product they already look at. A surface can turn this off.

    Each request names its touchpoint, which is recorded with it, so calls from different pages can be told apart. filters narrow one request without a surface of its own: three similar-items strips over three categories are one surface called three times. Retuning a surface retunes it everywhere it is called.

    A recommender for pages with nothing to anchor on, such as the homepage and landing pages, is a surface of its own: lbs_recommender_popular answers with the most popular products. Send no anchor_ids, and narrow it with filters where a strip shows one category or brand. Products with no recorded popularity are left out, so a new catalog’s slate can be shorter than size, or empty.

    Terminal window
    curl -X POST 'https://api.eu1.luigisbox.ai/discovery/v1/recommender?channel_id=lbn_4hj9tv&surface_id=lbs_recommender_popular' \
    -H 'Authorization: Bearer <token>' \
    -H 'X-Lbx-Visitor-Id: 8f14e45f-ea0f-4b5c-9a1d-2b3c4d5e6f70' \
    -H 'Content-Type: application/json' \
    -d '{ "type": "product", "touchpoint": "homepage", "size": 12 }'

    A surface can limit how many recommendations share a brand, category, or another attribute. Several limits apply together. Products without a value for an attribute do not consume that attribute’s limit. A product with several category values counts once toward each category’s limit.

    With strict limits, a response can contain fewer products than the requested size. A surface can instead allow expansion: it selects products within the limits first, then fills empty slots with skipped eligible products in rank order. Expansion can exceed the group limits. Filters and variant grouping still apply. Active pins within the requested slate count toward the limits first and keep their positions after variant grouping, moving up only if the slate ends before their slot. Pins alone can exceed the limits. Pins outside the requested slate and fully decayed soft pins are selected in rank order like other products.

    filters applies to recommendations as on the other endpoints. Two common uses:

    // Never recommend what cannot be bought
    { "availability": { "eq": 1 } }
    // Never recommend across a boundary that would confuse the shopper
    { "gender": { "in": ["women", "unisex"] } }

    On a bought-together surface, filters drop the model’s recommendations that do not match, and matching popular products fill the rest, so under a narrow filter the slate is mostly popular products.

    Excluding objects the shopper has already seen

    Section titled “Excluding objects the shopper has already seen”

    exclude_ids names objects the slate must not contain — what is already in the cart, or what another widget higher up the page is showing. Pass identities in the same form as anchor_ids, up to 50.

    {
    "type": "product",
    "touchpoint": "basket",
    "anchor_ids": ["product/9c8f2a"],
    "exclude_ids": ["product/3d41b7", "product/7e05c2"],
    "size": 10
    }

    The objects are removed as the surface retrieves, not trimmed from the finished slate, so excluding costs you no slots: the surface still serves size recommendations as long as it has that many others to serve. The anchors themselves are always excluded and need not be repeated here.

    Send the field only when you have something to exclude; an empty array is the same as omitting it.

    exclude_ids is not the same as an @id filter

    Section titled “exclude_ids is not the same as an @id filter”

    A filter can name the same objects:

    { "filters": { "@id": { "not_in": ["product/3d41b7"] } } }

    The two differ in what may override them. exclude_ids binds every object in the slate. A filter is one of the caller’s own selections, and a pin from a business-rules campaign is allowed to place a product the caller’s filters excluded — so a campaign pinning product/3d41b7 puts it back in the slate, and exclude_ids is what keeps it out.

    Reach for exclude_ids when an object must not appear whatever a campaign says, and for filters when you are narrowing the pool a recommendation is drawn from.

    It suppresses the objects you name, not their other variants: under variant collapsing a different colour of an excluded object can still represent its group. And it cannot create inventory — excluding a large share of a small catalog leaves the slate short for the ordinary reason, that there is nothing else to serve.

    The slate is recorded when the request is served, including which surface answered and which anchors you sent. Report what the shopper does with it — clicks, cart additions, purchases. See Sending events.