Product Listings
This article explains the Product Listing model in Hygraph. A Product Listing lets you configure a filtered set of products from an Algolia query, rather than from a commercetools category tree.
Use a Category when the set of products is “everything in this category”. Use a Product Listing when the set is a rule: vegan products, clearance, a brand plus a tag, a handful of SKUs, and so on.
The same listing can be a page of its own, and can also feed a Products Block, a mega-menu block, or cart recommendations.
How to configure
To view, edit or create a Product Listing, in Hygraph navigate via the left menu pane to Content, and in the secondary left menu pane under DEFAULT VIEWS select Product Listing.
A list of all existing Product Listings, from all tenants, in the selected Environment, will be displayed. Filter by tenant first so you do not edit another shop’s listing. Selecting a listing opens the edit page. To create a new one, use the button on the top right of the screen.
Reuse outside the listing page
The listing’s presets, filter query, and sort are reused when you select it as the product source:
- Products Block on a Page — Sections, Components and Elements
- Menu Product Listing Component — Menu
- Cart Recommendations — Settings
Those placements show a slice of the same Algolia result (for example the first products in a slider). The listing page is still what “view all” should open.
Publishing
Save and publish the listing, including locales that should go live. See Save, Publish & Schedule.
- Changing title, SEO, hero, or the filter/sort fields: publish the listing. First-time URLs can still need a build; later updates often use Page revalidation.
- Products newly matching because they were tagged, given a property, or put on discount: the Algolia index must contain that data. Request a build if the query is right but the product is missing.
Builds: Slack #help-commercetools-hygraph. Say if you need staging; otherwise production is assumed.
Fields in Hygraph on the "Product Listing" model
You do not pick the product grid by ticking products (that is what a Products Block Custom products selection is for). The listing asks Algolia for products that match Filter Presets and Filter Query. Sort By is the default order of those results; it does not decide which products match.
Presets and the filter query are combined with AND. Several presets are also combined with AND. Shoppers can still narrow the page with the filters sidebar; they cannot switch off the listing’s own presets and query.
If both presets and the filter query are empty, Algolia returns the catalogue (minus products marked exclude-from-search). Always set at least one of them.
| You want | Use |
|---|---|
| A common bucket such as clearance, vegan, or in-stock well-rated products | Filter Presets |
| A category, brand, tag, property, or a mix that has no preset | Filter Query |
| A preset and an extra constraint (for example Popular products in one category) | Both. They stack with AND |
| Newest / cheapest / A–Z first, without dropping products | Sort By only |
Popular as a preset is not the same as Sort By → Rating. The preset keeps products with rating ≥ 4 that are in stock. Sort By only orders whatever already matched.
Tenant and Storefront
Set Tenant and Storefront. This listing only appears on the webshops you select. If you leave a storefront unselected, it will not show there.
Title
Title (title) — localized. This is the page heading (and the name shown when the listing is reused elsewhere, for example as a cart-recommendation title fallback).
SEO
Fill SEO as on other webpage models. The URL Identifier becomes the slug; URL Path is generated from it. Details: SEO.
A Products Block that uses this listing can link “view all products” to that URL. Publish the listing with a URL before you rely on that link.
Filter Presets
Filter Presets (filterPresets) is a multi-select. Each value becomes an Algolia filter at request time:
| Preset | What Algolia keeps |
|---|---|
| New | Products whose “new until” date is still in the future (newToDateTimestamp) |
| TopRated | Products with averageRating exactly 5 |
| Clearance | Discounted products (discounted:true) |
| Popular | averageRating >= 4 and in stock |
| HasSubscription | Products that offer a subscription |
| Vegan | Products with the Vegan product property |
Leave presets empty when the filter query already describes the full rule. Do not pick Vegan and write properties:Vegan in the query; that is the same filter twice.
Filter Query
Filter Query (filterQuery) is a single Algolia filters string. The shop sends it as-is (combined with any presets). Syntax and operators are Algolia’s, not Hygraph’s.
Read these before writing a query:
- Filtering overview
- filters parameter (AND, OR, NOT, quotes, grouping)
- Filter by attributes (strings, numbers, booleans)
- Combining AND, OR, and NOT
How to go about it
- Decide the rule in plain language (“in-stock vegan products in Superfoods”).
- Prefer a Filter Preset for any part of that rule that already exists (here: Vegan).
- Put the rest in Filter Query, using stable identifiers (
categories.categoryKey,productKey,tags.identifier) rather than localized titles. - Combine parts with
AND/OR/NOTand parentheses, as in the Algolia docs. - Publish the listing and open the page. If the grid is empty or too broad, the query is usually quoting, an identifier, or an AND that is too strict — not a missing build.
A workable pattern:
attribute:value
attribute:"Value with spaces"
numericAttribute >= 4
(attribute:a OR attribute:b) AND other:true
NOT attribute:value
Quotes are required when the value contains spaces. Booleans and simple tokens can be unquoted (inStock:true, properties:Vegan).
Attributes you can filter on
These are the ones content usually needs. Values must match what is stored in Algolia for that shop and locale.
| Attribute | Typical use |
|---|---|
productKey |
One product, or a fixed list with OR |
categories.categoryKey |
Products in a commercetools category (stable key, not the title) |
brand.title |
Brand name as indexed for that locale |
tags.identifier |
A Tag identifier |
properties |
A Product Property enum value, for example Vegan, GlutenFree |
inStock |
true / false |
discounted |
true / false |
hasSubscription |
true / false |
averageRating |
Numeric, for example >= 4 |
Prefer tags.identifier over filterset text (filtersets.diet:"Vegan"). Filterset values are the localized tag label, so they break as soon as the label differs per language.
categories.title and brand.title are also locale-specific. categories.categoryKey and productKey stay the same across locales.
Examples
A single category (use the category key from commercetools / Hygraph, not the URL):
categories.categoryKey:"superfoods"
A brand. Quote the title; it must match the brand title in Algolia for that locale:
brand.title:"Purasana"
A tag, using the Tag Identifier:
tags.identifier:"energy-01"
A product property (same values as on the product):
properties:GlutenFree
Only in-stock products in a category:
categories.categoryKey:"beauty" AND inStock:true
Either of two tags:
tags.identifier:"vegan" OR tags.identifier:"vegetarian"
A small hand-picked set of products:
productKey:"magnesium-synergy" OR productKey:"vitamin-d3" OR productKey:"omega-3"
Category, excluding discounted items:
categories.categoryKey:"superfoods" AND NOT discounted:true
Preset Popular plus this query keeps well-rated in-stock products that also match the query. Example: Popular products in Superfoods — select Popular, and set the query to:
categories.categoryKey:"superfoods"
Preset Clearance plus a brand:
brand.title:"Purasana"
Things that go wrong
- AND vs OR.
properties:Vegan AND properties:GlutenFreeis both.ORis either. Group OR-lists in parentheses when you also AND something else:(productKey:"a" OR productKey:"b") AND inStock:true. Algolia only allowsORbetween filters of the same kind (text with text, number with number).brand.title:"Purasana" OR averageRating >= 4is invalid. - Wrong identifier.
categories.title:"Superfoods"fails if the indexed title is translated. Usecategories.categoryKey. - Tag label instead of identifier. The identifier lives on the Tag model, not the text shoppers see.
- Spaces without quotes.
brand.title:Vitamin Expressis invalid; usebrand.title:"Vitamin Express". - Sort By used as a filter. Newest / price / name never removes products; only presets and the query do.
- Empty query and empty presets. The page lists the whole catalogue.
You cannot test the string inside Hygraph. After publish, check the listing URL. For a query that still looks right but returns nothing, confirm the attribute and value in Algolia (or ask engineering); a typo in the attribute name is enough for zero hits.
Sort By
Sort By (sortBy) is the default ranking for this listing and for Products Blocks that reuse it. Shoppers can still change sort on the listing page with the sort dropdown.
| Value | Effect |
|---|---|
| Relevance | Algolia’s default ranking (leave this when you do not care) |
| PriceAsc / PriceDesc | Price |
| NameAsc / NameDesc | Product name A–Z / Z–A |
| CreatedAtDesc | Newest first |
| CreatedAtAsc | Oldest first |
| RatingDesc | Best rated |
| DiscountDesc | Highest discount first |
Sort replicas are an Algolia index per order. That is why sort is a separate field from the filter query: filters choose the set, sort chooses the replica used to display it.
Typical pairings:
- Clearance preset + DiscountDesc — discounted products, biggest discount first.
- New preset + CreatedAtDesc — still-new products, newest first.
- A category filter query + PriceAsc — that category, cheapest first.
Hidden Facets
Hidden Facets (hiddenFacets) hides filter groups from the listing sidebar. The shop already hides categories.title on Product Listing pages.
Add a facet name to hide it, for example brand.title, properties, or filtersets.diet (the Filterset Identifier, with the filtersets. prefix). Filtersets on a Product Listing are those that have matching tagged products, unless you hide them here. See Filtersets.
Maximum results to display
Maximum results to display (maxResultsToDisplay) — optional cap on how many products the page shows. Leave empty for the full result set.
Hide default product list and filters
Hide default product list and filters (hideDefaultListingContent) — hides the product grid, filters, and related listing chrome. Only hero, top content, and bottom content blocks remain. Use this when the page is content-led and should not look like a PLP.
Disable Personalization
Disable Personalization (disablePersonalization) — turns off Algolia personalization on this page. See Algolia personalization.
Disable Reranking
Disable Reranking (disableReranking) — turns off Algolia Dynamic Re-Ranking on this page. See Algolia re-ranking.
Hero
Hero (hero) — optional top section. If the hero title is empty, the listing Title is used.
Hero for mobile
Hero for mobile (heroForMobile) — optional. If set, it replaces the hero on small screens.
Top Content
Top Content (topContent) — rich text under the title, above the product grid. Keep it short; it pushes products down, especially on mobile.
Bottom content blocks
Bottom content blocks (bottomContentComponents) — stacked blocks under the products (FAQ, text, and the same kinds of blocks used on Categories). See Sections, Components and Elements.
Recommended Products
Recommended Products mark those products with a recommended highlight on this listing only. They do not add extra products to the grid; the product still has to match the presets and filter query.
Bestseller Products
Bestseller Products mark those products with a bestseller highlight on this listing only. They do not add extra products to the grid; the product still has to match the presets and filter query.
Product Listing Labels
Product Listing Labels (productListingLabels) — tags shown as labels on tiles of products that belong to this listing. See Tags, Product Badges and Labels. Label changes on tiles need a build.