Learn about the Types, configuration, and API implementation of Product facets.
After completing this page, you should be able to:
- Define the purpose of facets in product search and explain how they provide aggregated data alongside primary search results.
- Differentiate between Distinct, Range, and Count facets by identifying their specific use cases and essential configuration parameters (such as
field
,scope
,level
, andranges
). - Apply knowledge of facets to construct a
ProductSearchRequest
JSON for specified facet calculations and interpret the aggregated results from theProductPagedSearchResponse
.
query
, but they give you extra metadata about the characteristics of those products.facets
array to your main ProductSearchRequest
body. Each element in this array defines one facet calculation for the API to perform.// Structure of a request with facets
{
"query": {
/* Your main search query here */
},
"sort": [
/* Optional sorting */
],
"limit": 10,
"offset": 0,
"facets": [
// Array to define desired facets
{
/* Facet Definition 1 */
},
{
/* Facet Definition 2 */
}
// ... more facets
]
}
facets
field of the ProductPagedSearchResponse
.There are three main types of facets: distinct, ranges and count facets.
Distinct facets
- Purpose: Distinct facets count how many products (or variants) have specific, distinct values for a given field. This is useful for things like colors, brands, sizes (if they are discrete values), or categories.
- How it works: You specify a
field
(such asvariants.attributes.color.key
orcategories.id
). The API groups the products by the unique values found in that field and counts how many fall into each group (bucket). - Key configuration:
name
: A mandatory unique name you give this facet (for example, "colorFacet") to identify it in the results.scope
: Set this parameter toall
if the facet must consider all indexed products, not only the products resulting from the search query, which is the default behavior.field
(mandatory): The searchable product field to facet on.filter
: Additional filtering expression to apply to the facet result before calculating the facet.level
: Specify whether to count products (products
) or product variants (variants
).fieldType
: Required iffield
is a custom attribute.limit
: Maximum number of distinct value buckets to return. This improves query performance and is helpful when your UI does not need to display a large number of values. For example, only showing 10 different colors instead of 50 or more.sort
: How to sort the buckets, bykey
orcount
,asc
ordesc
. For example, sort color by count ascending.includes
: Only return buckets for these specific keys. For example, you only want colors red, blue, and green.missing
: A key to use for products that do not have the specifiedfield
. For example, some products do not have a color value; you can put these in a separate bucket like "misc" or "other colors".
Let’s consider how these concepts might map to a UI:

Example request
categories
attribute for results that match products with "white" or "White" in their name in this example request:{
"query": {
"fullText": {
"field": "name",
"language": "en",
"value": "white",
"caseInsensitive": true
}
},
"facets": [
{
"distinct": {
"name": "categoriesFacet",
"field": "categories",
"limit": 15,
"missing": "No Category"
}
}
]
}
Example response
{
"total": 244,
"offset": 0,
"limit": 20,
"facets": [
{
"name": "categoriesFacet",
"buckets": [
{
"key": "52e575d7-16ce-4186-ae67-39bec921e9ca",
"count": 65
},
{
"key": "2d1c1b7c-6e92-43c5-aa64-c10678793da5",
"count": 59
},
{
"key": "c2da8bae-daea-40e1-9e94-26753414e8d5",
"count": 49
},
{
"key": "06733ee5-0323-41e8-871d-bf58d5b6d093",
"count": 34
}
]
}
],
"results": [...]
}
Let’s take a look at how a standard product localized attribute facet query and response looks. We must specify the facet by their key. Because of this, you should consider how you get your application to store these keys, to ensure that you can quickly build the request.
{
"query": {
"fullText": {
"field": "name",
"language": "en",
"value": "white",
"caseInsensitive": true
}
},
"facets": [
{
"distinct": {
"name": "size",
"field": "variants.attributes.size.key",
"fieldType": "enum",
"limit": 15,
"missing": "No value"
}
}
]
}
In the response we have the attribute value keys.
{
"total": 244,
"offset": 0,
"limit": 20,
"facets": [
{
"name": "sizes", // Matches the name in the request
"buckets": [ // The results: distinct values and their counts
{ "key": "L", "count": 150 },
{ "key": "M", "count": 125 },
{ "key": "S", "count": 90 },
{ "key": "XL", "count": 70 },
{ "key": "Not Specified", "count": 20 }
]
}
],
"results": [...]
}
Ranges facets
- Purpose: Ranges facets count how many products fall into predefined numeric or date ranges. Ideal for price brackets, screen sizes, ratings, or date ranges.
- How it works: You define the boundaries (
from
,to
) for each range (bucket). The API counts how many products have a value in the specifiedfield
that falls within each range. - Key configuration:
name
(mandatory): Your unique name for this facet result.scope
: Whether the facet must consider only the products resulting from the search (query
) or all indexed products (all
).field
(mandatory): The numeric or date field to facet on (for example,variants.prices.centAmount
).level
: Specify whether to count products (products
) or product variants (variants
).fieldType
: Required for custom product attributes.ranges
(mandatory): An array defining each bucket:key
: (Optional) A custom label for the bucket, for example,0-50
or51-100
. If omitted, a default like*-5000
or5000-10000
is generated by the API.from
: The lower bound (inclusive). Omit for "less than".to
: The upper bound (exclusive). Omit for "greater than or equal to".
Example request
Let's count products by price ranges (in cents).
{
"query": {},
"facets": [
{
"ranges": {
"name": "priceRanges",
"field": "variants.prices.centAmount", // Field must be numeric/date
"ranges": [
{ "key": "under-50", "to": 5000 }, // .. up to 4999 cents
{ "key": "50-to-100", "from": 5000, "to": 10000 }, // 5000 to 9999 cents
{ "key": "100-plus", "from": 10000 } // 10000 cents and above
]
}
}
]
}
Example response
{
// ... other response fields
"facets": [
{
"name": "priceRanges",
"buckets": [
{ "key": "under-50", "count": 85 },
{ "key": "50-to-100", "count": 112 },
{ "key": "100-plus", "count": 43 }
]
}
]
"results": [...]
}

Count facets
- Purpose: The count facet counts the number of products (or product variants).
- How it works: Returns a single value representing the count.
- Key configuration:
name
: Your unique name for this facet result.scope
: Whether the facet must consider only the products resulting from the search (query
) or all indexed products (all
).filter
: Additional filtering expression to apply to the facet result before calculating the facet.level
: Specify whether to count products (products
) or product variants (variants
).
You can use the count facet to get the total number of variants or products and display it in the UI as shown below.
total
.
Example request
Let's get the total count of all products and all variants:
{
"query": {},
"facets": [
{
"count": {
"name": "totalProductCount",
"scope": "all" // Count ALL products, ignoring the main query
}
},
{
"count": {
"name": "totalVariantCount",
"level": "variants", // Count variants instead of products
"scope": "all" // Count ALL variants, ignoring the main query
}
}
]
}
Example response
{
"facets": {
"results": [
{
"name": "all-products",
"value": 200
},
{
"name": "all-variants",
"value": 1000
}
]
},
"results": [...]
}