Skip to main content

How Ranking Works

This guide explains how Catalog Search orders results, so you can predict why one product ranks above another and choose the right setting to change it.

How Results Are Ordered​

Filters decide which products can appear. These include search profile filters, exclusions, search rule filters, and the search request's filter_by. Hidden products are removed. Filters never change the order, only what appears in the results.

The remaining products are sorted by these criteria, in order. Each criterion only breaks ties on the criteria before it:

  1. Request sort. The sort_by field on the search request, for example a price sort chosen by a shopper or a popularity field based sort set by your storefront. See Sorting Search Results.
  2. Boost score. Merchandising boosts, when they apply.
  3. Relevance score. How well the product matches the query. Browse requests (q=*) have no relevance score.

Only the first three criteria are used, and each request sort_by field counts as one. For example, a keyword search on a profile with boosts:

Request sort_byResults are ordered by
NoneBoost score. Products with the same boost score are ordered by relevance score
price.amount:ascPrice. Products with the same price are ordered by boost score, then relevance score
price.amount:asc,created_at:descPrice, then creation date. Remaining ties are ordered by boost score. Relevance score is not used
Three fieldsThe three sort_by fields only. Boosts and relevance score are not used

Without boosts, relevance moves up to take the boost score's place. Without request sort_by and boosts, relevance score drives ranking.

Finally, pinned products are inserted at their positions.

Boost Scores​

Profile boosts and the boosts of matching search rules produce one boost score. Each product gets the highest weight among all the boost conditions it matches, from either source, or 0 if it matches none. Weights do not add up.

{
"boosts": [
{ "condition": "extensions.products(Details).is_featured:=true", "weight": 100 },
{ "condition": "extensions.products(Details).on_sale:=true", "weight": 50 },
{ "condition": "extensions.products(Details).stock_status:=out_of_stock", "weight": -100 }
]
}

With these boosts, five example products score as follows:

ProductConditions it matches (weight)Boost score
Featured, on saleis_featured (100), on_sale (50)100
On saleon_sale (50)50
On sale, out of stockon_sale (50), stock_status (-100)50
In stock, not featured, not on saleNone0
Out of stockstock_status (-100)-100

A product matching a boost and a bury is boosted, because the higher weight wins. To bury out-of-stock sale items, exclude them from the boost condition: on_sale:=true && stock_status:!=out_of_stock.

The same applies across sources. A search rule bury does not demote a product that matches a higher profile boost, and a profile weight of 100 outranks a rule weight of 50. When several search rules match, their boosts are merged before this step.

Relevance Score​

The relevance score is built from signals in a fixed priority order. A lower signal only breaks ties on the signals above it, however large its difference. For example, with max_score or max_weight, a product matching both words of cordless drill always ranks above one matching only drill, even if that one is an exact match in a heavier field. Under max_weight, the exception is a match only in weight 0 fields (see below).

With the default text_match_type of max_score, the order is:

PrioritySignalRanks higher whenSetting
1Query words matchedMore query words are found across all query fields, including typo-corrected and partially typed words—
2Words in the fieldMore query words, including typo-corrected and partially typed words, appear within 10 words of each other. Ties go to the field containing more query words overall—
3Typos and partial wordsFewer corrections were needed. A typo costs more than completing a partially typed wordtypo_tolerance, prefix
4ProximityFewer other words sit between the matched words—
5Exact matchThe field contains only the query wordsprioritize_exact_match
6Word positionThe matched word is nearer the start of the field. A word that appears more than once is judged by its last occurrenceprioritize_token_position
7Synonym matchThe product matched directly, not through a synonymdemote_synonym_match
8Field weightThe match is in a heavier fieldfields[].weight
9Fields matchedThe query matches in more fields—

Signals 2–7 form a field score, computed for each query field. Different query words can match in different fields. Word order is not a signal: shoe red and red shoe score the same for either query.

Typo correction, compound words, and word dropping also decide which products are found at all. By default each runs only when a stricter search finds nothing. So if one product matches shoez as typed, products named shoes are not returned. See Handling Typos.

Text Match Types​

text_match_type on a search profile changes where field weight sits. The default suits most catalogs.

text_match_typeEffect
max_score (default)The best field score is used. Weight only breaks ties between equally good matches. Suits general product search
max_weightThe highest-weighted matched field is used, and weight moves above signal 2. A match in a heavier field wins even when a lighter field matches better. Use when field importance matters more than match quality
sum_scoreSignals 1–8 are replaced by the sum of each matched field's score multiplied by its weight, rewarding matches in several fields. Query words matched is not ranked, so a product matching one query word in several fields can rank above a product matching every query word

Example. A profile queries name (weight 10) and description (weight 5). A search for drill finds product A named Drill Bit Set and product B whose description is exactly drill. B has the better field score because it is an exact match.

  • max_score: B ranks first.
  • max_weight: A ranks first.

Under max_weight and sum_score, a product matching only in weight 0 fields gets the lowest relevance score and ranks below every product that matches a weighted field. Once any field has a weight, fields without one count as weight 0. Give every field that should affect ranking a weight above 0.

Ranking Settings​

ranking_settings on a search profile controls signals 5 and 6:

{
"ranking_settings": {
"prioritize_exact_match": true,
"prioritize_token_position": true
}
}

Both are optional. On update, the object is replaced as a whole. Send "ranking_settings": null to restore the defaults. Ranking settings do not apply to autocomplete.

prioritize_exact_match​

Default true. A field is an exact match when it contains only the query words, in any order, ignoring case. For cordless drill, Cordless Drill ranks above Cordless Drill Kit. With false, the two tie on this signal.

A single-word query is exact only when matched as typed, without typo correction or partial word completion. Turn this off only when an exact field match carries no more intent than a partial one.

prioritize_token_position​

Default false. When true, a match nearer the start of a field ranks higher. For bosch, Bosch Cordless Drill ranks above Drill Bit Set for Bosch.

Turn it on when field values lead with the most significant words, such as names that start with the brand. Leave it off for descriptive text.

Inspecting Relevance​

Each keyword-search hit includes text_match_info with the signals behind its score, such as tokens_matched, best_field_weight, and typo_prefix_score. Pinned products, and hits with no relevance score, do not include it. Use it to debug ranking. Under sum_score, only score and fields_matched are meaningful. The score is only comparable within one search and is not a match percentage, so do not show it to shoppers or filter on it.

Pinned and Hidden Products​

Search rules can pin and hide products outside the sort stack:

  • Pinned products are placed at one-based positions across the whole result set. They do not need to match the query, but must match the active filters.
  • Hidden products are removed. A product that is both pinned and hidden is hidden.
Ask External AI