Facets and filters
Read the facets a page answers with, send the shopper's choices as filters, and count a facet when the shopper opens it.
A facet is a filter shoppers choose from, with the count each value would find. Every answer that lists products brings its page's facets. Here is the color facet of the sofa page wohnen/sofas (wohnen: living):
curl -s 'http://127.0.0.1:7800/v1/search?on=category_page&category=wohnen/sofas' \
| jq -c '.sections[] | select(.type == "product") | .facets[] | select(.field == "color")
| {field, kind, label}, (.values[] | {value, label, count})'{"field":"color","kind":"swatch","label":"Farbe"}
{"value":"anthracite","label":"Anthrazit","count":2}
{"value":"beige","label":"Beige","count":2}
{"value":"grey","label":"Grau","count":2}
{"value":"green","label":"Grün","count":2}Labels come in the request's locale: Farbe is color, Grau grey. Each value carries the code that chooses it and how many products it would find. A range, such as the width, brings min and max instead of values.
Choose values
Send the shopper's choices as filters in a POST, one key per field. Values of one field are alternatives, and fields narrow each other:
curl -s http://127.0.0.1:7800/v1/search -H 'Content-Type: application/json' \
-d '{"on": "category_page", "category": "wohnen/sofas",
"filters": {"color": ["grey", "green"], "width": {"gte": 160, "lte": 220}, "on_sale": true}}' \
| jq -c '.sections[] | select(.type == "product") | .hits[] | {entity, variant}'{"entity":"product:SOFA-ASKA-2","variant":"SOFA-ASKA-2-SALBEI"}One sofa is grey or green, 160 to 220 cm wide and on sale. Its tile shows the variant that meets all three: the Aska in sage (Salbei), which counts as green and is on sale.
Each kind of facet is chosen its own way:
| Facet kind | Chosen as | Example |
|---|---|---|
list, swatch | Value or group codes | "color": ["grey", "green"] |
buckets | A bucket's code, written as its bounds | "delivery_days": ["-15"] |
range | gte, lte or both | "width": { "gte": 160, "lte": 220 } |
toggle | true | "on_sale": true |
hierarchical | A category with everything below it | "category": { "within": "wohnen/sofas" } |
filters is a selector in these forms only. It takes any field some page of the release counts, so on_sale works on the sofa page too; any other field is a 400. The answer's filters labels each filter for its chip.
Reference: filters · Selector · filters in the answer
A chosen value stays
Each facet is counted under every filter but its own, so choosing a value never makes its siblings vanish:
curl -s http://127.0.0.1:7800/v1/search -H 'Content-Type: application/json' \
-d '{"on": "category_page", "category": "wohnen/sofas", "filters": {"color": "grey", "on_sale": true}}' \
| jq -c '.sections[] | select(.type == "product")
| .total, (.facets[] | select(.field == "color") | .values[] | del(.label, .swatch))'0
{"value":"green","count":1}
{"value":"grey","count":0,"selected":true}No grey sofa is on sale, so the page lists nothing. Green still counts one sofa, since the color facet ignores its own choice. Grey stays at 0, selected, so the shopper can take it back. Other empty values are left out, and so is an empty facet nobody chose.
Upper bounds
Where a product's variants differ, some counts can only be upper bounds. Choose two sizes and two colors of bed linen, and one variant may meet the size while another meets the color. Such a facet carries upper_bound: true, as does a section's total where a free range over such a field meets another choice, and the trace says why.
Reference: upper_bound
The price histogram
A price shown as a histogram brings the bars behind its slider, as histogram bins:
curl -s 'http://127.0.0.1:7800/v1/search?on=category_page&category=wohnen/sofas' \
| jq -c '.sections[] | select(.type == "product") | .facets[] | select(.field == "price")
| {min, max}, (.histogram[] | select(.count > 0))'{"min":649.0,"max":1899.0}
{"gte":620,"lt":680,"count":1}
{"gte":680,"lt":750,"count":1}
{"gte":750,"lt":820,"count":1}
{"gte":1200,"lt":1300,"count":1}
{"gte":1800,"lt":2000,"count":1}The bins are a fixed ladder of 24 steps to the decade, the same under every filter, and empty ones come too, so the bars keep their places. Four sofas fill five bins: a tile counts in every bin one of its prices falls in, and the Aska costs 649 € in sage, on sale, and 749 € in grey.
Reference: histogram
Facets counted later
A page counts its first 30 facets and those a filter chooses; the others come deferred, without values. A list or swatch carries 50 values, the chosen and the most frequent, and more says how many others it has.
To fill a facet when the shopper opens it, name it in facets. With count_only, the answer leaves out the hits and the other facets:
curl -s http://127.0.0.1:7800/v1/search -H 'Content-Type: application/json' \
-d '{"on": "category_page", "category": "wohnen/sofas", "filters": {"color": "grey"},
"facets": ["brand"], "count_only": true}' \
| jq -c '.sections[] | {total, hits, facets}'{"total":2,"hits":[],"facets":[{"field":"brand","kind":"list","label":"Marke","values":[{"value":"Halvard","label":"Halvard","count":2}],"search":true}]}Both grey sofas are Halvard's. The home store's pages show ten facets at most, so none waits; the React components ask this way for every facet a shopper opens.
Reference: facets · count_only · deferred · counted_facets
Which facets a page shows
The merchant lays out each page's facets in categories.json: default for every page, nodes for the categories that differ.
{
"default": {
"facets": ["category", { "field": "price", "display": "histogram" }, "style", "on_sale", "availability"]
},
"nodes": [
{ "category": "wohnen/sofas", "facets": ["width", "color", "upholstery", "seat_height", "price"] },
{ "category": "leuchten", "facets": ["room", "light_source", "material", "color", "price"] }
]
}A category page shows the facets of the nearest node up the tree that lists its own, else default: the floor lamps (leuchten/stehleuchten) show those of leuchten (lamps). A search page shows default, or the facets of the category its query names, so "sofa" shows the sofa page's. Pages and their filters shows how a merchant lays them out.
Reference: categories.json nodes · default
Next
- Category pages: browse a category with its facets and banners.
- Sorting: the orders a page offers and the one it starts in.
- URLs and redirects: keep the shopper's choices in the page's URL.