Product discovery

Composable Commerce's Product Projections Search endpoint is specifically designed for enhancing product discovery experiences like:

In this guide, we provide some hands-on examples demonstrating how to leverage the capabilities of the Product Projection Search API for these functionalities.
Be aware that due to our event-driven architecture, the changes to Products made with the Import API or the Products API could take up to 15 minutes to be reflected in the Product Projection Search API.

Prerequisites

Before proceeding to the following examples, make sure you have:

  1. Activated the Product Projection Search endpoint.

  2. Set relevant Product Attributes as searchable.

Activate Product Projection Search endpoint

You can activate the Product Projection Search endpoint either using the Change Product Search Indexing Enabled update action or in the Merchant Center from the Storefront search tab in Settings > Project settings.

Set relevant Product Attributes as searchable

To search Products by a particular Attribute, you need to set their AttributeDefinition as searchable. You can do it either by using the Change AttributeDefinition IsSearchable update action or utilizing the Merchant Center by navigating to Settings > Product types and attributes.

Product discovery is one of the topics to which you should pay most attention when designing your product data model.
When migrating to commercetools from your current system, you might tend to replicate your existing product data model. However, this often needs to be revised since it impacts your storefront performance, including product discovery. Be mindful that commercetools is the core commerce system in your composable landscape. Your product data model in commercetools should reflect what is necessary for your customers to find and purchase your products, with enough information to send downstream to process and fulfill orders.

We recommend carefully evaluating which Attributes you want to set as searchable. When making your decisions, be aware that:

  • Fields that are indexed are quicker to search but may consume more storage resources.
  • Making some Attributes as searchable and making others available only for retrieval can impact search capabilities and performance.

Before making an Attribute searchable, ask yourself if your storefront actually exposes the Attribute and if you need to filter, facet, or query the Attribute.
The name , description , slug , and searchKeywords of a Product and the related Product Variants' sku fields are searchable by default. To make custom Attributes searchable, you must set them as searchable.

Filtering by category

Filtering by category and by category subtrees lets you filter Products based on the Categories and child Categories they are assigned to.

The following diagram depicts an example of the relationship between Products and Categories.

Untitled

Given this Products and Categories relationship, the following filters are available:

  • Filter Products belonging to Categories within the Tops Category tree.
    For example, the query filter.query=categories.id:subtree("{tops-category-id}") will return both the wool-knit-sweater and the graphic-t-shirt Products.

  • Filter Products belonging to the T-Shirts Category.
    For example, the query filter.query=categories.id:"{t-shirt-category-id}") will return only the graphic-t-shirt Product.
    This query looks for Products belonging to a particular Category. If the T-Shirts Category had child Categories, such as Crew Neck and V-Neck, the Products belonging to those child Categories would not be returned.

  • Filter Products belonging both to T-Shirts and Sale Categories.
    For example, the query filter.query=categories.id:"{t-shirt-category-id}"&filter.query=categories.id:"{sale-category-id}" will return only the graphic-t-shirt Product.
    Note that the filter.query is passed twice in this example. Passing multiple filter parameters combines the filters as an AND operator.

  • Filter Products belonging either to the Sweaters or Sale Categories.
    For example, the query filter.query=categories.id:"{sweater-category-id}","{sale-category-id}" will return both the wool-knit-sweater and the graphic-t-shirt Products.
    Note that both Category IDs are passed to a single filter.query parameter. Passing multiple values to a single filter parameter works as an OR operator.

Filtering by price

Price range matching

Range queries let you filter Products based on price ranges. Such a filter is widely used in commerce websites allowing customers to find products within their budget.

For example, the query filter.query=variants.scopedPrice.centAmount:range(0 to 10000) will return all Products with at least one Product Variant that has a price between 0 and 100 (10000 cents).

Setting an upper or lower limit

You can use the greater than (>) or the less than (<) operators to filter Products above or below a certain price.

For example, the query filter.query=variants.scopedPrice.centAmount:>1000 will return all Product Variants with a price higher than 10 (1000 cents).
While the query filter.query=variants.scopedPrice.centAmount:<2000 will return all Product Variants with a price lower than 20 (2000 cents).

TermFacets

TermFacets optimizes the shopping experience for your customers by allowing them to filter products based on shared characteristics, such as size or color.

TermFacets categorize and count Product Variants based on specific Attribute values.
For example, to display the number of products for each size and color in your product catalog, you can use the query facet=variants.attributes.size&facet=variants.attributes.color that will return the following TermFacetResult.

Example of TermFacetResultjson
....
"facets": {
"variants.attributes.size.key": {
...
"total": 25239,
"other": 0,
"terms": [
{
"term": "xxxl",
"count": 3224
},
{
"term": "xs",
"count": 2504
},
{
"term": "xxs",
"count": 1861
}
]
},
"variants.attributes.color.key": {
...
"terms": [
{
"term": "blue",
"count": 5624
},
{
"term": "black",
"count": 3183
},
{
"term": "grey",
"count": 3004
}
]
}
}

On your storefront, you would render the facet similar to the following image.

An example of term facets by size and color on a website UI

RangeFacets

RangeFacets improve the experience on your commerce website by allowing customers to filter products based on predefined value ranges, such as price.

For example, to display how many products you have in three price ranges, you can use the query variants.price.centAmount:range(0 to 5000),(5000 to 15000),(15000 to *).
On your storefront, you would render the facet similar to the following image.

An example of ranges facet by price range on a website UI

FilteredFacets

FilteredFacets enhance the shopping experience by allowing your customers to narrow down search results based on specific characteristics of products, such as color, size, brand, or price. Unlike general facets that display all the available categories or attributes, FilteredFacets show only those that are relevant to the current search or selection.

For example, the query variants.attributes.size:"xxxl" will return only Product Variants that have the size Attribute set to xxxl.
On your storefront, you would render the facet similar to the following image.

An example of filtered facet by selected size on a website UI