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.
A recommender renders products from a recommender
surface. Each one has its own folder,
integration/recommender <name>/, and an integration can have any number of them. Two
kinds:
- Inline — a strip placed relative to an element of your page, on the pages it matches.
- Popup — a dialog opened after the shopper adds a product to the cart.
Inline
Section titled “Inline”// integration/recommender similar/_config.tsexport default { surface: 'lbs_recommender_similar', size: 8, fields: ['@title', 'url', 'image_url', 'price'], urlMatch: '^/p/', anchor: '.product-detail', position: 'after', reserve: 320,};// integration/recommender similar/_init.tsimport type { RecommenderConfigType } from '@/types';
export default (c: RecommenderConfigType) => { // The product on this page, as the recommendation's anchor. c.items = () => { const id = document.querySelector('[data-product-id]')?.getAttribute('data-product-id'); return id ? [`product/${id}`] : []; };};Popup after “add to cart”
Section titled “Popup after “add to cart””// integration/recommender cart/_config.tsexport default { surface: 'lbs_recommender_xsell_basket_popup', size: 4, fields: ['@title', 'url', 'image_url', 'price'], confirm: '.cart-notice.is-visible',};// integration/recommender cart/_init.tsimport type { RecommenderConfigType } from '@/types';
export default (c: RecommenderConfigType) => { c.intent = (target) => { const id = target.closest('.add-to-cart')?.getAttribute('data-product-id'); return id ? `product/${id}` : null; };};The popup opens when a click that intent recognises is followed, within windowMs, by an
element matching confirm — your site’s own “added to cart” notice. It does not open when
the add fails.
| Key | Default | |
|---|---|---|
surface | — | Required. A recommender surface; it decides the model |
size | — | Required. The number of products |
type | _global.itemType | The object type recommended |
fields | — | Fields the tiles need |
excludeItems | false | Also exclude the anchor products from the results |
urlMatch | — | Inline: a regular expression on the URL’s path |
anchor | — | Inline: CSS selector of the element the strip is placed relative to, or candidates, most specific first |
position | — | Inline: prepend, append, before or after |
settleMs | — | Inline: wait until the anchor stops changing for this long |
reserve | — | Inline: height in pixels reserved while loading, so the page does not jump |
rootClass | — | Inline: classes of yours put on the strip’s element |
confirm | — | Popup: CSS selector of your “added to cart” notice |
windowMs | 10000 | Popup: the longest time from the click to the notice |
Set in _init.ts:
| Hook | |
|---|---|
items() | The anchors: products the recommendation is about, as typed IDs (product/sku-1001). [] means no strip on this page. |
active(url) | Whether the strip belongs on this URL, for URLs a regular expression cannot describe |
intent(target) | Popup, required: given a click target, the typed ID of the product being added, or null when it is not an add-to-cart control |
An inline strip loads when it comes within about two screens of the viewport, after the page has loaded. A recommender that returns nothing, or fails, takes no space.
Templates and text
Section titled “Templates and text”Override recommender-box-default, recommender-result-default and recommender-popup —
see Templates. The heading is the translation recommender.title; set it
per recommender in its folder’s _translations.ts.
See also
Section titled “See also”- Recommendations — the request a recommender sends
Was this page helpful?
Thanks.