Recommendation Widgets
Recommendation widgets
POST /indexes/{index_name}/recommendations/widgets/{widget_id}
Purpose
Serve a recommendation shelf that a merchandiser built and named in the Marqo console, such as a "New arrivals" carousel on the home page, a "Staff picks" grid on a landing page, or a personalised "For you" row. The storefront asks for the widget by its ID and Marqo returns the products the widget's source and merchandising rules produce. Merchandisers change what a widget shows from the console, without a theme or code change.
Background
The other recommendation endpoints are algorithms seeded by the request: similar and complementary take product IDs, For You takes a shopper. A widget is a configured object instead. Each widget has a label, an ID the storefront references it by, a source that fills it, and its own merchandising rules (pins, exclusions, boosts and buries, filters, and schedules) that apply only to that widget.
| Source | What fills the widget | Typical use |
|---|---|---|
| Search query | The results of a search query, merchandised with the widget's rules | "New arrivals", "Under $50", "Gifts for dad" |
| Collection | The products of a collection, merchandised with the widget's rules | "Best of bedding" on the home page |
| Hand-picked | Only what the merchandiser pins, in the order they chose, from anywhere in the catalog. Filters, boosts and buries shape anything after the pins | Editorial or campaign sets |
| For You | Personalised per shopper from their tracked events. Pinned products always appear; the remaining slots are filled per shopper at request time | Home page "For you" row |
When to use
- Home page and landing page shelves: Recommendations that are not tied to a product the shopper is viewing
- Campaign placements: Shelves a merchandiser retargets, reorders, or schedules without a deploy
- Personalised rows with guaranteed placements: A For You widget where certain products must always appear
- Any placement rendered from an ID: One theme block that renders whichever widget a merchandiser assigns to it
Example uses
| Use Case | Description | Source | Business Impact |
|---|---|---|---|
| Home page "New Arrivals" | Show recently added products, filtered to the last week and in stock | Search query | Keeps the home page fresh without theme edits |
| Seasonal campaign shelf | Hand-pick the campaign's hero products in a fixed order, scheduled for the campaign window | Hand-picked | Guarantees placement for promoted items |
| Collection spotlight | Feature a collection on the home page with a bestseller pinned first | Collection | Drives traffic into a priority category |
| Personalised "For You" row | Fill a row per shopper, with a new launch pinned to position 1 | For You | Combines personalisation with merchandising control |
| Landing page grid | Render a widget as a grid rather than a carousel; the API is layout-neutral | Any | One widget serves any layout |
Creating a widget (console)
- In the Marqo console open Merchandising → Recommendation Rules → Widgets and select the index.
- Click Create Widget and give it a Label, an ID, and a Source. A Search query widget also takes the query; a Collection widget takes the collection.
- Merchandise it as you would a search or collection: pin and exclude products, boost and bury, filter, and schedule rules.
- Publish. A widget is served once it has published rules. Until then the endpoint returns
404for its ID.
Published changes reach the API within five minutes: rules are exported to the edge on a five-minute schedule. The same applies when a widget is deleted, after which its ID returns 404.
The ID is what the storefront sends in the path. It is chosen by the merchandiser, is unique within the index, and is used exactly as authored (case-sensitive). IDs may contain letters, digits, _ and -, must start with a letter or digit, and are at most 64 characters long, so they are always URL-safe.
Widget rules are independent of the index's global rules. A widget never inherits the index's global filters or score modifiers; only the rules authored on the widget apply. For You widgets cannot be previewed in the console, since their unpinned slots are chosen per shopper at request time.
Example (cURL)
curl -X POST https://ecom.marqo-ep.ai/api/v1/indexes/${index_name}/recommendations/widgets/new-arrivals \
-H "x-marqo-index-id: ${MARQO_INDEX_ID}" \
-H "Content-Type: application/json" \
-d '{
"limit": 8,
"filter": "in_stock:true"
}'
For You example
A For You widget needs the shopper, exactly as the For You endpoint does. It requires the event tracking pixel to be installed on the store.
curl -X POST https://ecom.marqo-ep.ai/api/v1/indexes/${index_name}/recommendations/widgets/for-you-home \
-H "x-marqo-index-id: ${MARQO_INDEX_ID}" \
-H "Content-Type: application/json" \
-d '{
"userId": "abc123",
"limit": 12
}'
A shopper Marqo cannot personalise for yet (no tracked events) still gets the widget: its pinned products first, then the widget's rules applied across the catalog. The x-marqo-results-personalized response header says which happened.
A For You widget returns a single synthesised page, so totalHits equals the number of hits returned rather than a catalog-wide count.
Parameters
The widget is named by the path. The body carries only per-request options and uses strict validation: any unrecognised parameter returns a 400 error. Filters use the Marqo Filter DSL and apply in addition to the widget's own filter rules.
| Name | In | Type | Required | Description | Example |
|---|---|---|---|---|---|
| widget_id | path | string | yes | The widget's ID as set in the console. Used exactly as authored (case-sensitive). | new-arrivals |
| limit | body | integer | no | Max number of results to return. Defaults to the index's configured search limit (12 if none is set); 10 for a For You widget. | 8 |
| offset | body | integer | no | Offset for pagination. | 0 |
| filter | body | string | no | Server-side constraints (e.g., in_stock, price ranges, brand, category). See Marqo Filter DSL. | "in_stock:true" |
| attributesToRetrieve | body | array[string] | no | Attributes to return in the response for each document. If not specified, all attributes are returned. | ["title", "price", "image_url"] |
| userId | body | string | For You widgets | User identifier for personalisation. Required for a For You widget and ignored by the other sources, so a storefront block can always send it. | "abc123" |
| sessionId | body | string | no | Optional session identifier. For You widgets only. | "xyz789" |
| interactionTypes | body | array[string] | no | Types of interactions to consider (ClickEvent, AddToCartEvent, PurchaseEvent). Default: all types. For You widgets only. | ["ClickEvent", "AddToCartEvent"] |
Response (example)
The response has the same shape as a search response.
{
"hits": [
{
"_id": "sku_38702",
"title": "Linen Duvet Cover",
"price": 249.0,
"image_url": "https://cdn.example.com/sku_38702.jpg"
}
],
"limit": 8,
"offset": 0,
"totalHits": 143,
"processingTimeMs": 41
}
| Header | Description |
|---|---|
x-marqo-results-personalized | For You widgets only. true when the results were built from the shopper's own events; false when the widget fell back to its rules alone. |
Errors
| Status | Meaning |
|---|---|
| 400 | An unrecognised body parameter, or a For You widget called without userId |
| 400 | Personalized recommendations not configured: a For You widget on an index that has no event tracking pixel or has personalisation switched off |
| 404 | Widget '<id>' not found: no widget with that ID on the index, the widget has no published rules yet, or merchandising is not enabled on the index |
Treat a 404 as "render nothing". It is the expected response for a widget a merchandiser has created but not yet published, or has since deleted.