# Product Projections Retrieve product data projected to the context of your Store, specific to the customer locale and country. The intended use of the Product Projections API is to provide product data for product detail pages (PDPs) and product listing pages (PLPs) in your storefront applications. Product Projections represent the state of a [Product](/urn?urn=ctp%3Aapi%3Atype%3AProduct) as visible to customers, taking into account the Product's publication status, the Store context, and various projection dimensions. When retrieving Product Projections, you can specify whether the data should be restricted to either its [current or staged](/api/product-catalog-overview.md#current--staged) data. To tailor the query response to your use case, you can further filter the data based on context such as: - given [Locales](/api/product-catalog-overview.md#locales), - specific [Prices](/api/product-catalog-overview.md#prices), - the Product's availability on [inventory supply channels](/api/product-catalog-overview.md#inventory-entries), or - its assignment to specific [Product Selections](/api/product-catalog-overview.md#product-selection-assignments). Use the [Query ProductProjections](/api/projects/productProjections.md#query-productprojections) endpoint of this API for queries on non-localized standard fields, such as `id` and `key`. For queries on [Attributes](/api/product-catalog-overview.md#attributes) and localized fields, use the [Product Search API](/api/projects/product-search.md) instead that is the preferred option for product discovery. It provides full-text search, filtering, faceting, and lower response times compared to the Query ProductProjections endpoint, see [performance tips](/api/performance-tips.md#query-and-retrieve-data). This API provides read-only access to Product Projections. For managing Products, use the [Products API](/api/projects/products.md) instead. When the Project has the [ProductCatalogModel](/api/projects/project.md#productcatalogmodel) set to `Modular`, `masterVariant` and `variants` in the [ProductProjection](/urn?urn=ctp%3Aapi%3Atype%3AProductProjection) object are empty. Use the [Variant Projections API](/api/projects/variant-projections.md) to retrieve variant data instead. Learn more about how to implement a product detail page (PDP) using Product Projections in our self-paced Build product detail pages module. ## Projection dimensions ### Current / staged Every [Product](/urn?urn=ctp%3Aapi%3Atype%3AProduct) resource contains two representations of its data, from the moment it is created: - `staged`: Represents the draft data. This is where all pending changes, such as edits to descriptions, prices, variants, are held before they are made public. - `current`: Represents the live version of the product data visible to customers in a storefront. The platform detects updates made to the `staged` representation. If there are differences compared to `current`, the `hasStagedChanges` flag in the [ProductCatalogData](/urn?urn=ctp%3Aapi%3Atype%3AProductCatalogData) is set to `true`. #### Publishing If your product data is ready for your customers, you can [publish](/api/projects/products.md#publish) the Product. During this process, the platform: - Copies the `staged` data to `current`. - Sets the `published` flag to `true` in the [ProductCatalogData](/urn?urn=ctp%3Aapi%3Atype%3AProductCatalogData). - Sets the `hasStagedChanges` flag to `false` in the [ProductCatalogData](/urn?urn=ctp%3Aapi%3Atype%3AProductCatalogData). Typical storefront applications retrieve product data by [querying](/api/projects/productProjections.md#query-productprojections) or [searching](/urn?urn=ctp%3Aapi%3Aendpoint%3A%2F%7BprojectKey%7D%2Fproducts%2Fsearch%3APOST) only the `current` representation of published Products. You can restrict access to only published Products by assigning the `view_published_products:{projectKey}` [scope](/api/scopes.md#product-projections) instead of `view_products:{projectKey}`. #### Unpublishing [Unpublishing](/api/projects/products.md#unpublish) a Product makes it inaccessible through the Product Projection endpoints by default and removes it from the [Product Search](/api/projects/product-search.md) index. Unpublishing only sets the `published` flag to `false` in the [ProductCatalogData](/urn?urn=ctp%3Aapi%3Atype%3AProductCatalogData); it does not alter the data stored in the `current` or `staged` representations. ### Locales To remove unneeded translations from Product Projections, [LocalizedStrings](/api/types.md#localizedstring) can be filtered based on locales. The locales that should be included in the Product Projection are determined in the following order: - Locales defined directly with the query parameter `localeProjection`. - Locales configured in the [Store](/urn?urn=ctp%3Aapi%3Atype%3AStore) that is specified with the query parameter `storeProjection`. Projecting on locales also affects [Line Items](/api/projects/carts.md#lineitem) of Carts bound to a Store. If no translation is found on a given field for the specified locales, the API checks the [Project](/urn?urn=ctp%3Aapi%3Atype%3AProject) languages in their configured order and uses the first localized value it finds. This ensures that required fields cannot remain empty in the Product Projection. ### Prices Price projection is a mechanism for filtering the prices included in a Product Projection. It ensures that the API response for a product contains only the prices relevant to a specific context, such as a particular country, customer group or distribution channel. This practice simplifies client-side logic by preventing API responses from being cluttered with a product's entire, often extensive, price list. #### Projection by Store To remove unneeded [Embedded Prices](/api/pricing-and-discounts-overview.md#embedded-prices) from Product Projections, they can be filtered based on the product distribution channels configured in the [Store](/urn?urn=ctp%3Aapi%3Atype%3AStore) that is specified with the query parameter `storeProjection`. If the Store has `distributionChannels` set, then the Product Projection will only include the Prices meeting one of the following criteria: - The Price has a distribution Channel that is included in the Store's `distributionChannels`. - The Price does not have a distribution Channel assigned. Likewise, if the Store has `countries` set, then the projection will only include the Prices that meet one of the following criteria: - The Price has a country that is included in the Store's `countries`. - The Price does not have any country assigned. This filtering logic applies to the `prices` array within the Product Projection. For price projection by Store to apply, the [Product](/urn?urn=ctp%3Aapi%3Atype%3AProduct) `priceMode` must be `Embedded`. [Standalone Prices](/api/projects/standalone-prices.md) are not computed using Store channels or countries. To retrieve a Standalone Price in Product Projections, apply [projection by price selection](/api/projects/productProjections.md#projection-by-price-selection). #### Projection by price selection [Price selection](/api/pricing-and-discounts-overview.md#price-selection) allows you to select one price for your Product that is the best matching price for the customer. This best match can be either an Embedded Price of the Product Variant or a Standalone Price associated with the Product Variant. The platform selects the best matching price based on the price selection parameters, such as `priceCurrency`, `priceCountry`, `priceCustomerGroup`, and `priceChannel`. When price selection is applied, the Product Variants that are returned will contain two fields with Prices: - The `prices` array contains Embedded Prices (optionally [projected by Store](/api/projects/productProjections.md#projection-by-store)); Standalone Prices are **never included**. - The optional `price` field contains the best matching price based on the provided price selection parameters. This can be either an Embedded Price or a Standalone Price. ### Inventory entries To remove unneeded [Product Variant Availabilities](/api/projects/products.md#productvariantavailability) from Product Projections, they can be filtered based on the Inventory supply Channels configured in the [Store](/urn?urn=ctp%3Aapi%3Atype%3AStore) that is specified with the query parameter `storeProjection`. If the Store has `supplyChannels` set, then only the following Inventory entries are included in the projected Product Variants availability: - Inventory entries with a supply Channel that is included in the Store's `supplyChannels` - Inventory entries without a supply Channel Projecting on Inventory entries also affects [Line Items](/api/projects/carts.md#lineitem) of Carts bound to a Store. ### Product Selection assignments To retrieve only those Product Projections that are assigned to a particular [Product Selection](/api/projects/product-selections.md), use the [Get ProductProjection in Store](/api/projects/productProjections.md#get-productprojection-in-store) endpoints. For Product Selections that only have particular [Product Variants](/api/projects/products.md#productvariant) assigned, these endpoints return only those Variants in the retrieved Product Projections. ### Attributes To reduce the response size and improve performance, use the `filter[attributes]` query parameter to specify [Product Attributes](/api/projects/products.md#attribute) that you want to include or exclude in the Product Projections response. - **Include Attributes**: specify the Attribute names to include them in the response. - **Exclude Attributes**: add a dash (`-`) before the Attribute names to exclude them from the response. You can include or exclude Product Attributes, Attributes in the Master Variant, and all other variants of the Product. Example queries: ```bash title="Include only specific Attributes" curl --get https://api.{region}.commercetools.com/{projectKey}/product-projections/{id}?filter[attributes]=color&filter[attributes]=size -i --header "Authorization: Bearer ${BEARER_TOKEN}" ``` This returns only the `color` and `size` Attributes in the Product Projections response. ```bash title="Exclude specific Attributes" curl --get https://api.{region}.commercetools.com/{projectKey}/product-projections/{id}?filter[attributes]=-description&filter[attributes]=-specifications -i --header "Authorization: Bearer ${BEARER_TOKEN}" ``` This returns all Attributes except `description` and `specifications` in the Product Projections response. ## Representations #### ProductProjection [type definition](/api/projects/productProjections.md?urn=ctp:api:type:ProductProjection). #### ProductProjectionPagedQueryResponse [type definition](/api/projects/productProjections.md?urn=ctp:api:type:ProductProjectionPagedQueryResponse). ## Get ProductProjection ### Get ProductProjection by ID [endpoint definition](/api/projects/productProjections.md?urn=ctp:api:endpoint:/\{projectKey}/product-projections/\{id}:GET). ### Get ProductProjection by Key [endpoint definition](/api/projects/productProjections.md?urn=ctp:api:endpoint:/\{projectKey}/product-projections/key=\{key}:GET). ## Get ProductProjection in Store ### Get ProductProjection in Store by ID [endpoint definition](/api/projects/productProjections.md?urn=ctp:api:endpoint:/\{projectKey}/in-store/key=\{storeKey}/product-projections/\{id}:GET). ### Get ProductProjection in Store by Key [endpoint definition](/api/projects/productProjections.md?urn=ctp:api:endpoint:/\{projectKey}/in-store/key=\{storeKey}/product-projections/key=\{key}:GET). ## Query ProductProjections You can [sort](/api/general-concepts.md#sorting) the results only on standard scalar fields that are not nested inside arrays, such as `masterVariant.sku`, `createdAt`, and `lastModifiedAt`, as well as localized fields like `name.en`. Sorting on [Prices](/urn?urn=ctp%3Aapi%3Atype%3APrice) or on [Attributes](/urn?urn=ctp%3Aapi%3Atype%3AAttribute) is not possible through the Query ProductProjections endpoint. To sort or filter on Attributes and for other product discovery use cases, use the [Product Search API](/api/projects/product-search.md) instead. When querying an [Attribute](/urn?urn=ctp%3Aapi%3Atype%3AAttribute), we recommend that you use the performance-optimized [Product Search](/api/projects/product-search.md) API whenever possible. For more information, see [inefficient patterns](/api/predicates/query.md#inefficient-patterns). When querying an Attribute, you must always include both the `attribute-name` and `attribute-value` details in the Query Predicate. Otherwise, a [400 Bad Request](/api/errors.md#400-bad-request) error will occur. [endpoint definition](/api/projects/productProjections.md?urn=ctp:api:endpoint:/\{projectKey}/product-projections:GET). ## Check if ProductProjection exists ### Check if ProductProjection exists by ID [endpoint definition](/api/projects/productProjections.md?urn=ctp:api:endpoint:/\{projectKey}/product-projections/\{id}:HEAD). ### Check if ProductProjection exists by Key [endpoint definition](/api/projects/productProjections.md?urn=ctp:api:endpoint:/\{projectKey}/product-projections/key=\{key}:HEAD). ### Check if ProductProjection exists by Query Predicate [endpoint definition](/api/projects/productProjections.md?urn=ctp:api:endpoint:/\{projectKey}/product-projections:HEAD). ## Check if ProductProjection exists in Store ### Check if ProductProjection exists in Store by ID [endpoint definition](/api/projects/productProjections.md?urn=ctp:api:endpoint:/\{projectKey}/in-store/key=\{storeKey}/product-projections/\{id}:HEAD). ### Check if ProductProjection exists in Store by Key [endpoint definition](/api/projects/productProjections.md?urn=ctp:api:endpoint:/\{projectKey}/in-store/key=\{storeKey}/product-projections/key=\{key}:HEAD). ## Related pages - [Area overview page with navigation](/api.md) - [Previous page: Products](/api/projects/products.md) - [Next page: Product Selections](/api/projects/product-selections.md)