GraphQL (headless)¶
Headless storefronts (PWA Studio, Next.js, Vue Storefront, your own) get OpenFilter's layered navigation from Magento's products query: add the field openfilter_aggregations.
query ($filter: ProductAttributeFilterInput) {
products(filter: $filter, pageSize: 24) {
total_count
items { name sku }
openfilter_aggregations {
code filter_key label url_param display_mode multiselect logic tooltip position
options { value label url_value count selected depth from to swatch { type value } }
range { min max from to }
}
}
}
{ "filter": { "category_id": { "eq": "21" }, "color": { "in": ["49", "50"] }, "size": { "eq": "167" } } }
What you get¶
- The store view's filters (send the
Storeheader) in the merchant's order, only where they show (Where it shows, by thecategory_idorcategory_uidof the query), with the labels, tooltips and URL names of that store view. - Counts that help shoppers pick: each filter is counted without its own picks, so with Black and Blue picked, Green still shows how many products it would add. Filters set to Products must match all of the picked values (
logic: "and") count with their picks. Values without products are left out unless picked. - Picks:
selectedmarks the values of thefilterargument;valueis what to send back (filter_keynames the argument: the attribute code,price, orcategory_id). - Sliders (
display_modesliderorfrom_to):range.min/range.maxof the products found without the slider's own pick,range.from/range.tothe picked bounds. - Ranges (
display_moderanges): optionsfrom–to, [from, to), with counts. Send one asprice: { from: "10", to: "30" }. - Categories: the categories below the queried category (the store's root category without one), as many levels as the category tree is set to (
depth1 = a child), with Magento's counts. Pick one by querying itscategory_id. - Swatches:
swatch.typecolor(value#hex),image(value a URL) ortext.
Everything comes from the same search request as the products: with the single query strategy OpenFilter adds no request to Magento's own (measured in the integration tests).
Good to know¶
- Prices and ranges are in the units of Magento's
pricefilter (the price index), not converted to the display currency. - Magento's
aggregationsfield of the same query counts the same way (it is the same search). Queries withoutopenfilter_aggregationsare unchanged. - The built-in rating, in stock, on sale and new filters depend on the shopper's session on the storefront and are not part of GraphQL yet.
- The storefront picks several categories on one page (
?cat=21,25); Magento'scategory_idargument lists one category per query, so a headless page picks one category at a time. - GraphQL is optional: OpenFilter does not require Magento's GraphQL modules (
composer suggest), and a store without them is unaffected.
A complete page that uses only this field and plain JavaScript is in examples/headless.