Product catalog

Review the key enhancements in Product Modeling, including Product-level Attributes, optimized Product Projection fetching, and the new capabilities of the Product Search API.

Ask about this Page
Copy for LLM
View as Markdown

After completing this page, you should be able to:

  • Describe how to use Product-level Attributes to reduce data redundancy and improve update efficiency.

  • Apply the filter[attributes] query parameter to Product Projections to control the size of the API response payload.
  • Explain the key features that reached General Availability in the Product Search API, including Distinct, Ranges, Count, and Statistical Facets.

  • Utilize Fuzzy Search and Discounted Price Filtering within the Product Search API to enhance customer search experience and support specific promotions.

  • Use the GraphQL API to perform consolidated Product Search requests that include fuzzy matching and statistical facets.

  • Explain the purpose and benefit of the allVariants(onlyMatching:true) argument in the GraphQL Product Projection Search.
  • Implement server-side filtering using onlyMatching:true to return only the Product Variants that match the original search query.

Product modeling

In 2025, commercetools introduced architectural changes designed to streamline how product data is structured and retrieved. The focus shifted from "per-variant" data management to a more centralized "Product-level" approach, significantly reducing data redundancy and API payload sizes.

These updates are critical for developers looking to optimize storefront performance, especially for large catalogs with high variant counts.

Key enhancements

  • Product-level Attributes: historically, Attributes like brand, manufacturer, or material had to be replicated across every variant using the SameForAll constraint. You can now define Product Attributes directly at the Product level. This centralization ensures that common data is stored only once, leading to faster updates and leaner API responses.
  • Attribute filtering for Product Projections: a new filter[attributes] query parameter allows you to explicitly include or exclude specific Attributes in the API response. This is a game-changer for mobile performance, where reducing the JSON payload size is vital for quick page loads.
  • Updated Query Predicate format: to enhance indexing efficiency, Query Predicates for Attributes now require the Attribute name. This change allows the platform to route queries more effectively, preventing performance degradation as your Attribute count grows.
Example:
Let’s use the Attribute filtering feature to fetch a current Product Projection, but it should only include two specific Attributes we need (search-color and color-code):
Fetch current Product Projection that only includes two specific Attributes
import { ctpClientHTTPAPI, projectKey } from "./BuildClient";
import { createApiBuilderFromCtpClient } from "@commercetools/platform-sdk";

const apiRoot = createApiBuilderFromCtpClient(ctpClientHTTPAPI).withProjectKey({
  projectKey,
});

async function getFilteredAttributes() {
  await apiRoot
    .productProjections()
    .withKey({ key: "comfort-coffee-mug" })
    .get({
      queryArgs: {
        // Include only 'search-color' and 'color-code'
        "filter[attributes]": ["search-color", "color-code"],
      },
    })
    .execute()
    .then((response) => {
      console.log(
        "Filtered attributes: \n" +
          JSON.stringify(response.body.masterVariant.attributes, null, 2)
      );
    });
}

await getFilteredAttributes();

Filtered attributes:

Resultjson
[ {
  "name" : "search-color",
  "value" : {
    "key" : "white",
    "label" : {
      "de-DE" : "Weiß",
      "en-US" : "White",
      "en-GB" : "White"
    }
  }
}, {
  "name" : "color-code",
  "value" : "#FFFFFF"
} ]

As you can see by our result, when trying to display all Attributes of the master variant, only the ones included in our filter are available. This not only improves readability but also can help in reducing the payload size of the response we get from the HTTP API.

Test your knowledge