Product catalog

Learn how the new Product Attributes and Product Search capabilities fundamentally improve the management and discoverability of your Product data.

Ask about this Page
Copy for LLM
View as Markdown

After completing this page, you should be able to:

  • Describe the purpose and benefits of the new Product Attributes feature.

  • Explain how attribute filtering in the Product Projections API improves performance.

  • Demonstrate the use of fuzzy search, statistical facets, and discounted price filters in the Product Search API.

  • Identify the benefits of using the onlyMatching parameter set to true in GraphQL Product Projection Search.
  • Summarize the functionality and benefits of the Smart Data Modeler.

Product Projections

In modern commerce, every millisecond counts, and sometimes, the data you don't load is just as important as the data you do.

Before the introduction of attribute filtering, when you fetched a Product Projection, the response included all associated attributes for the Master Variant and all other Variants. While comprehensive, this often led to overfetching and unnecessarily large payload sizes, especially for complex products with hundreds of attributes.
We're excited to introduce the new filter[attributes] query parameter. This allows you to surgically specify exactly which Product Attributes (on the Product, Master Variant, or other Variants) you want to be included in (or excluded from) the API response.
The new filter[attributes] parameter is available across all core Product Projection endpoints, including queries, fetching by ID, fetching by key, and store-scoped requests.

Using it is straightforward, supporting both inclusion (whitelist) and exclusion (blacklist) modes:

Including specific Attributes (Whitelist)

To request only a specific set of attributes, simply provide a list of the attribute names. Any attribute not listed will be omitted from the response.

Syntax: filter[attributes]=attributeName1,attributeName2
For example, let's try to get a current Product Projection of a specific product (Rustic Country Queen Bed), but we only want to see the information about the color and finish for each variant:
Requestbash
curl --get \
"https://api.{region}.commercetools.com/{projectKey}/product-projections/key=rustic-country-queen-bed?filter[attributes]=search-color&filter[attributes]=search-finish" \
--header "Authorization: Bearer {bearerToken}" \
| jq
Resultjson
{
  "id": "70ab1f54-277e-4504-87f3-cdae3d5be73d",
  "version": 3,
  "productType": {
    "typeId": "product-type",
    "id": "415bec3b-e1de-4bbd-8c62-e537937ec817"
  },
  "name": {
    "en-US": "Rustic Country Queen Bed",
    "en-GB": "Rustic Country Queen Bed",
    "de-DE": "Rustikales Queensize-Bett im Landhausstil"
  },
...
    "attributes": [
      {
        "name": "search-finish",
        "value": {
          "key": "brown",
          "label": {
            "en-US": "Brown",
            "en-GB": "Brown",
            "de-DE": "Braun"
          }
        }
      },
      {
        "name": "search-color",
        "value": {
          "key": "yellow",
          "label": {
            "en-US": "Yellow",
            "en-GB": "Yellow",
            "de-DE": "Gelb"
          }
        }
      }
    ],
...
}

Excluding Specific Attributes (Blacklist)

To fetch all attributes except a few, use the minus sign (-) prefix before the attribute name.

Syntax: filter[attributes]=-attributeName1

If we want to get all attributes except search-color:

Requestbash
curl --get \
"https://api.{region}.commercetools.com/{projectKey}/product-projections/key=rustic-country-queen-bed?filter%5Battributes%5D=-search-color" \
--header "Authorization: Bearer {bearerToken}" \
| jq
Resultjson
{
...
    "attributes": [
      {
        "name": "search-finish",
        "value": {
          "key": "brown",
          "label": {
            "en-US": "Brown",
            "en-GB": "Brown",
            "de-DE": "Braun"
          }
        }
      },
      {
        "name": "finish-code",
        "value": "#8b4513"
      },
      {
        "name": "productspec",
        "value": {
          "en-US": "- Leather upholstery\n- Standard Queen size\n- Assembly on site",
          "en-GB": "- Leather upholstery\n- Standard Queen size\n- Assembly on site",
          "de-DE": "- Leather upholstery\n- Standard Queen size\n- Assembly on site"
        }
      },
      {
        "name": "finish-label",
        "value": {
          "en-GB": "Saddle Brown",
          "de-DE": "Sattel braun",
          "en-US": "Saddle Brown"
        }
      },
      {
        "name": "color-label",
        "value": {
          "en-GB": "Tan",
          "de-DE": "Bräunen",
          "en-US": "Tan"
        }
      },
      {
        "name": "color-code",
        "value": "#D2B48C"
      }
    ],
...
}
This new Attribute Filtering functionality is a prime example of how commercetools is continuously focused on developer experience and performance. By reducing unnecessary data payloads, you gain immediate, measurable improvements in application speed and efficiency. Make sure to integrate the filter[attributes] parameter into your next project or optimization sprint to unlock these benefits!

Statistical facets

But what if we would like to get some statistical information about some numeric properties of our products? For example about their EUR price for German customers? This is now possible thanks to a new addition to the Product Search API, statistical facets—a new type of facet that provides statistical aggregations (min, max, average, sum, count) for number and date fields in search results. This offers insights into product data without client-side calculation using multiple queries.

Let's use it to expand our previous request:

Requestgraphql
query FuzzySearchWithGermanPriceStats {
  productsSearch(
    query: {fuzzy: {field: "name", value: "tarditional", level: 2, language: "en-GB"}}
    facets: {stats: {name: "priceStatistics", field: "variants.prices.centAmount", filter: {and:[{exact: {field: "variants.prices.currencyCode", value: "EUR"}}, {exact: {field: "variants.prices.country", value: "DE"}}]}}}
  ) {
    results {
      product {
        key
        masterData {
          current {
            allVariants {
              prices {
                country
                value {
                  centAmount
                  currencyCode
                }
              }
            }
          }
        }
      }
    }
    facets {
      ... on ProductSearchFacetResultStats {
        name
        count
        sum
        min
        max
        mean
      }
    }
  }
}
Resultjson
{
  "data": {
    "productsSearch": {
      "results": [
        ...
      ],
      "facets": [
        {
          "name": "priceStatistics",
          "count": 3,
          "sum": 629700,
          "min": 29900,
          "max": 359900,
          "mean": 209900
        }
      ]
    }
  }
}

We now have not only the count of prices that meet our requirements but also valuable statistical information about them.

Filter by discounted prices

What if you only want to retrieve discounted "traditional" products? This is now achievable thanks to the newly introduced feature that allows you to query Products based on whether any of their Product Variants are currently discounted.
Requestgraphql
query FuzzySearchForDiscountedProducts {
  productsSearch(
    query: {and: [{fuzzy: {field: "name", language: "en-GB", level: 2, value: "tarditional"}}, {exact: {field: "variants.prices.discounted", value: true}}]}
  ) {
    offset
    limit
    results {
      id
      product {
        key
        masterData {
          current {
            allVariants {
              prices {
                discounted {
                  value {
                    centAmount
                    currencyCode
                  }
                }
                value {
                  centAmount
                  currencyCode
                }
              }
            }
          }
        }
      }
    }
  }
}
Resultjson
{
  "data": {
    "productsSearch": {
      "offset": 0,
      "limit": 10,
      "results": [
        {
          "id": "58084c1e-ccde-4c6d-9fd7-afc2ecd05673",
          "product": {
            "key": "traditional-armchair",
            "masterData": {
              "current": {
                "allVariants": [
                  {
                    "prices": [
                      {
                        "discounted": {
                          "value": {
                            "centAmount": 25415,
                            "currencyCode": "EUR"
                          }
                        },
                        "value": {
                          "centAmount": 29900,
                          "currencyCode": "EUR"
                        }
                      },
                      {
                        "discounted": {
                          "value": {
                            "centAmount": 25415,
                            "currencyCode": "GBP"
                          }
                        },
                        "value": {
                          "centAmount": 29900,
                          "currencyCode": "GBP"
                        }
                      },
                      {
                        "discounted": {
                          "value": {
                            "centAmount": 25415,
                            "currencyCode": "USD"
                          }
                        },
                        "value": {
                          "centAmount": 29900,
                          "currencyCode": "USD"
                        }
                      }
                    ]
                  }
                ]
              }
            }
          }
        }
      ]
    }
  }
}

Search for Product Variants in Stores

A significant enhancement to Product Search is the new capability to locate Product Variants that are available in specific Stores, regardless of how many active selections that Store has, or within specific Store Selections. Previously, this was only feasible if the entire Product belonged to the selection. Let's give it a try:

Requestgraphql
query FindVariantsBelongingToStore {
  productsSearch(
    query: {exact: {value: "a748b5f7-54b3-48f4-b744-fafb4b5d9f2c", field: "variants.stores"}}
    markMatchingVariants: true
  ) {
    results {
      product {
        key
        masterData {
          current {
            allVariants(onlyMatching: true) {
              sku
            }
          }
        }
      }
    }
  }
}
Resultjson
{
  "data": {
    "productsSearch": {
      "results": [
        {
          "product": {
            "key": "modern-three-seater-sofa",
            "masterData": {
              "current": {
                "allVariants": [
                  {
                    "sku": "MTSS-01"
                  }
                ]
              }
            }
          }
        },
        {
          "product": {
            "key": "maya-pillow-cover",
            "masterData": {
              "current": {
                "allVariants": [
                  {
                    "sku": "MPC-02"
                  }
                ]
              }
            }
          }
        }
      ]
    }
  }
}

The significant enhancements to Product Search in 2025—including fuzzy search, statistical facets, discounted price filters, and granular variant selection—collectively deliver a powerful, flexible, and high-performance search experience. By leveraging these new capabilities, Functional Architects can design storefronts that are more resilient to user error, provide deeper analytical insights on pricing, and offer precise control over store-specific product visibility, ultimately leading to improved conversion rates and a superior customer experience.

Test your knowledge