Facets

Facets turn catalog fields into storefront filter controls. A facet has a customer-facing name, a product or product-variant association, a field to aggregate, and optional rules for which values to expose and how to order them.

Configure facets with the Admin API. Request evaluated facets alongside a Storefront products or productVariants connection. Each Storefront facet includes its display name, typed field, filterable queryField, and the values available in the current result context.

Facets and search use one shared contract: render the returned values, then combine queryField and the selected value into the connection’s query argument. Do not derive dynamic attribute or metafield paths in storefront code.

How facets move through the APIs

StepAPIResponsibility
ConfigureAdminChoose the facet name, association, field, visible values, and ordering.
EvaluateStorefrontApply the current search and commerce context, then return matching facet values.
RenderYour storefrontDisplay the returned facet name and values.
FilterStorefrontSend selected values back through the connection’s query argument.

Facet definitions are project configuration. The Storefront response is runtime data and can change with the search expression, catalog contents, publication state, store, price context, and customer context.

Configure a facet with the Admin API

Create one definition for each filter group the storefront should present. The example below exposes discovered product vendors under the customer-facing name “Brand.”

AUTOMATIC selects values found in the catalog. You can exclude unwanted values and provide a preferred order for active values.

Inspect both facet and errors in the mutation payload. Invalid field combinations return a typed FacetFieldInvalidError with a reason.

See facetCreate, FacetCreateInput, and FacetFieldInput for the full contract.

Associations

  • PRODUCT facets are returned by the Storefront products connection.
  • PRODUCT_VARIANT facets are returned by the Storefront productVariants connection.

Choose the association that matches the result grid being filtered. A variant facet can use product-level vendor, tag, or metafield information where supported, while still aggregating variant results.

Field kinds

KindWhat it representsStorefront queryField shape
VENDORProduct vendor or brand.vendor or product.vendor
TAGProduct tags.tag or product.tags
ATTRIBUTEValues of a configured product attribute.attributes.<normalized-name>
METAFIELDValues of an existing public metafield definition.metafields.<namespace>.<key> or a product-owned variant path
AVAILABILITYWhether the result is available for sale.available_for_sale
PRICEThe contextual minimum and maximum price.price

An ATTRIBUTE facet requires attributeId. A METAFIELD facet requires namespace and key; its owner defaults from the facet association. Product facets can only use product metafields. Namespace, key, and owner are invalid for other facet kinds.

Price and availability facets do not accept value-selection or ordering configuration.

Choose which values appear

Facets with discrete values—vendor, tag, attribute, and metafield—support two selection modes:

ModeUse it whenConfiguration rules
AUTOMATICNew catalog values should appear without updating the facet.Do not set values. Use excludedValues to hide values.
MANUALOnly an explicit allowlist should appear.Set values. Do not set excludedValues.

Use valueOrder to place important active values first. In automatic mode, ordered values cannot also be excluded. In manual mode, every ordered value must be present in values. Values not named in valueOrder keep a stable position after the configured values.

When valueSelectionMode is omitted, a facet with no explicit values behaves as automatic; a facet with values behaves as manual. Set the mode explicitly in integrations so intent remains clear.

Render and apply Storefront facets

The Storefront response is designed to drive the filter UI directly:

  • name is the configured label, such as “Brand.”
  • field identifies the facet kind for type-specific rendering.
  • queryField is the exact field name accepted by the search language.
  • values contains each available value and its matching result count.

Build a clause from queryField and the chosen value, then combine clauses using the Search query language. For example, a returned queryField of attributes.color and a selected value of Blue produces attributes.color:Blue.

Quote values that contain whitespace or search-language punctuation, for example vendor:"Acme Lighting". Pass the final expression as a GraphQL variable rather than interpolating it into the operation text.

Code in text

Keep selected filters in application state as { queryField, value } pairs. This avoids hard-coding normalized attribute paths and keeps the UI aligned if an Admin user changes facet configuration.

Price facets are ranges

A price facet is different from a discrete value facet. It returns values named min and max; their count field carries the contextual minimum and maximum amount in integer minor currency units. For EUR, a returned value of 5000 represents EUR 50.00.

Use those bounds to render a range control. Send the selected range back as price:>=<minimum> and price:<=<maximum>, with the same Storefront price currency, channel, country, and customer context used to request the facets.

price:>=5000 AND price:<=15000

For ordinary facet values, count is the number of matching results. Treat the PRICE field as the explicit signal to interpret min and max as amounts instead.

Integration checklist

  1. Configure the facet once through Admin and handle typed mutation errors.
  2. Request facets with the same Storefront connection, search expression, and commerce context as the product grid.
  3. Render the returned name and values; use field for specialized controls such as price ranges.
  4. Preserve the returned queryField and use it when constructing filters.
  5. Reset cursor pagination whenever the filter expression changes.
  6. Re-request both products and facets after a selection so counts and available values stay current.