Skip to main content

Similar Recommendations

Similar recommendations

POST /api/v1/indexes/{index_name}/recommendations/similar

Purpose

Surface similar alternatives to the item(s) a shopper is viewing to keep them engaged and reduce bounce rates. These recommendations excel at providing substitutions when size, color, price, or brand preferences differ, or when the original item is out of stock. They help maintain shopping momentum by offering viable alternatives without disrupting the user's intent.

Background

Similar recommendations use vector similarity and machine learning to identify products with comparable features, styles, or characteristics. The algorithm analyzes product attributes, visual similarities, and behavioral patterns to surface items that serve as effective substitutes, helping reduce pogo-sticking and cart abandonment when the primary item isn't quite right.

When to use

  • Product detail pages: Show similar alternatives to give customers more options and choices
  • Recommendation carousels: Surface items with comparable features, aesthetics, or price points, underneath collections, for example
  • Cross-merchandising: Present alternatives that might better match customer preferences

Example uses

Use CaseDescriptionInput ProductsBusiness Impact
PDP "Similar Items" SectionDisplay alternatives below or beside the main product on detail pagesCurrent product being viewedIncreases choice, extends browsing time
Homepage Recommendation CarouselsShow "You Might Also Like" or "Similar Styles" carouselsRecently viewed or featured productsEncourages exploration, improves discovery
Category Page Side RailsPresent similar alternatives alongside category listingsCategory anchor or filtered productsExpands choice, captures various preferences
Search Results EnhancementAdd similar product suggestions within search result pagesSearch result products as anchorsIncreases options, improves search experience
Email Marketing RecommendationsInclude "Similar to Your Recent Views" in email campaignsPreviously viewed or purchased itemsDrives return visits, extends engagement

Input products (documentIds)

The documentIds parameter uses Marqo's document ID field: the special _id each document has. Values from any other field will not work.

  • PDP Context: Use the current product being viewed to find direct alternatives
  • Stock Context: Use out-of-stock item IDs to find immediate substitutes
  • Preference Context: Include recently viewed or clicked items to understand style preferences
  • Best Practice: Use 1-3 most relevant products as input to maintain similarity focus and relevance

Example (cURL)

curl -X POST https://ecom.marqo-ep.ai/api/v1/indexes/${index_name}/recommendations/similar \
-H "x-marqo-index-id: ${MARQO_INDEX_ID}" \
-H "Content-Type: application/json" \
-d '{
"documentIds": ["sku_38702"],
"limit": 8
}'

Parameters

Filters use the Marqo Filter DSL. Results automatically exclude the input item(s). The endpoint uses strict validation: any unrecognised parameter returns a 400 error.

NameTypeRequiredDescriptionExample
documentIdsarray[string]yesAn array of 1-10 Marqo document IDs (the _id field) to base similarity on. Each value must exactly match the _id of an indexed document, the same _id returned in search and collection responses.["sku_38702"]
limitintegernoMax number of results to return. Defaults to 10.8
offsetintegernoOffset for pagination. Defaults to 0.0
filterstringnoServer-side constraints (e.g., in_stock, price ranges, brand, category). See Marqo Filter DSL."in_stock:true"
attributesToRetrievearray[string]noAttributes to return for each document. If omitted, the attribute list configured for the index is returned, the same default as search.["title", "price", "image_url"]
sortByobjectnoCustom result ordering, in the same shape as the search sortBy. Fields from the request take precedence over any sort configured for the index. When a sort applies, results are ordered by it rather than by similarity, and personalisation is not applied.{ "fields": [{ "fieldName": "price", "order": "asc" }] }
userIdstringnoShopper identifier. Personalises the shelf when personalisation is enabled for the index (see below)."abc123"
sessionIdstringnoShopper session identifier, used together with userId."xyz789"
profileIdstringnoA named search configuration profile for the request (e.g. different behaviour on PDP vs collection pages). If the profile does not exist, Marqo falls back to the default configuration."pdp_default"
merchandisingProfileIdstringnoThe merchandising profile whose rules (pins, exclusions, boosts, buries, filters) are applied to this shelf. This is separate from profileId, which selects search configuration. If no such profile matches, the shelf's published rules apply."summer_campaign"
note

This endpoint and /complete-the-look take the seed products as documentIds; the /complementary endpoint takes them as docIds.

limit and offset must be whole, non-negative numbers. The API does not check this itself: a fractional or negative value is passed to the search engine, which rejects the request with Similar recommendations failed: <reason>.

Merchandising and personalisation

Merchandising rules published for the Similar Recommendations context in the Marqo console apply to the shelf. Which rules resolve depends on how many seed products are sent, because the request is split into one search per seed, up to six searches.

SeedsRules applied
1The rules published for that product, including its pins.
2-6Each search is merchandised with the rules published for its own seed: filters, exclusions, boosts and buries. Pins are not placed, because no single seed owns the shelf.
7 or moreSeeds share searches, so only the index-wide rules apply.

merchandisingProfileId swaps in the rules of a merchandising profile instead. A profile's per-product rules are looked up only when exactly one seed is sent; with several seeds the profile's index-wide rules apply.

When userId is sent and personalisation is configured for the index, results are re-ranked toward the shopper's interaction history. Personalisation is skipped when a sortBy applies. See Personalization for how to enable it.

Response (example)

{
"hits": [
{
"_id": "sku_40118",
"_score": 0.8731,
"title": "Linen Duvet Cover - Sage",
"price": 249.0,
"image_url": "https://cdn.example.com/sku_40118.jpg"
}
],
"processingTimeMs": 38,
"limit": 8,
"offset": 0,
"personalized": true
}
FieldTypeDescription
hitsarray[object]The recommended documents, each with _id, _score and the retrieved attributes.
processingTimeMsintegerServer processing time in milliseconds.
limitintegerThe limit applied to the request.
offsetintegerThe offset applied to the request.
personalizedbooleanPresent only when userId was sent. true when the results were re-ranked toward the shopper's history.

There is no totalHits field: the shelf is built from a similarity search and has no catalog-wide count.

HeaderDescription
x-marqo-cache-hit-count, x-marqo-cache-miss-countHow many of the underlying searches were served from cache and how many were not.
x-marqo-results-personalizedPresent when userId was sent. true or false, matching the personalized field.

Fallback when the seed products are missing

When none of the documentIds exist in the index (for example, every seed product has been deleted), the endpoint does not return an error. It returns a regular search response for the whole index instead, with the other request parameters (such as filter and limit) applied. That response has the search response shape, including totalHits, facets and query, and carries the x-marqo-cache-hit header. Clients should handle both shapes, for example by rendering hits and ignoring fields they do not expect.

The fallback response carries x-marqo-cache-hit in place of the x-marqo-cache-hit-count and x-marqo-cache-miss-count headers, and its body has no personalized field even when userId was sent. The x-marqo-results-personalized header is still present in that case and reports the outcome.

Errors

Error responses have the body {"error": "<message>"}.

StatusMessage
400Parameter 'documentIds' is required and must be a non-empty array
400All documentIds must be non-empty strings
400Number of 'documentIds' must be less than or equal to 10
400Unrecognized param(s): '<name>' for any parameter not listed above
400A message from the request validator when a value fails its constraint, for example an empty merchandisingProfileId
400Similar recommendations failed: <reason> when the underlying search rejects the request (for example, an invalid filter, or a fractional limit)