--- title: Leveraging facets, sorting, and pagination (Shopify Hydrogen) slug: p25e0438 canonical_url: https://docs.coveo.com/en/p25e0438/ collection: coveo-for-commerce source_format: adoc --- # Leveraging facets, sorting, and pagination (Shopify Hydrogen) Facets, sorting, and pagination are essential components of any commerce interface. These features improve the user experience by helping users find what they need when browsing product lists. > **Note** > > In the following sections, you'll notice that Headless doesn't specify details about what should be returned by the Commerce API, such as which facets are available, the types of sorting criteria, and how many items are displayed per page. > Because of the [declarative nature of the Commerce API](https://docs.coveo.com/en/o6od0220/), this information is determined by the configuration associated with the Commerce API request. ## Define and access target controller hooks Common functionalities, such as pagination, facets, and sorting, rely on [target controller hooks](https://docs.coveo.com/en/p3ae0283#initializing-the-engine). Define and retrieve them as follows: ```tsx // lib/commerce-engine-config.ts import { definePagination, defineFacetGenerator, defineSort, // ... } from '@coveo/headless-react/ssr-commerce'; export default { // ... controllers: { pagination: definePagination({options: {pageSize: 9}}), <1> facetGenerator: defineFacetGenerator(), sort: defineSort(), // ... }, } satisfies CommerceEngineDefinitionOptions; ``` <1> [Define the `pagination` controller](https://docs.coveo.com/en/headless-react/latest/reference/functions/SSR_Commerce.index.definePagination.html) with the target default page size. ## Facets [Facets](https://docs.coveo.com/en/1571/) let users filter search results by specific attributes, making it easier to find relevant items. ### Facet generator Use a [`FacetGenerator`](https://docs.coveo.com/en/headless-react/latest/reference/interfaces/SSR_Commerce.index.FacetGenerator.html) controller hook to access a list of facets that can be rendered in the UI. See [About the Facet Generator](https://docs.coveo.com/en/n9sd0159/). There are five types of facets: * Regular * Numerical range * Hierarchical * Date range * Location The following code snippet shows how to render facets using the `FacetGenerator` based on their type. ```tsx import type { MappedFacetState, RegularFacet, RegularFacetState, NumericFacetState, NumericFacet, RegularFacetValue, CategoryFacetState, CategoryFacet, } from '@coveo/headless/ssr-commerce'; import {engineDefinition} from '~/lib/coveo.engine'; type FacetGenerator = ReturnType< typeof engineDefinition.controllers.useFacetGenerator >; export function Facets() { const facetGenerator = engineDefinition.controllers.useFacetGenerator(); <1> return (
{facetGenerator.state.map((facet) => { <2> switch (facet.type) { case 'regular': return ( key={facet.facetId} staticState=[facet](https://docs.coveo.com/en/198/) facetController={facetGenerator.methods?.getFacetController( facet.facetId, 'regular', )} /> ); case 'numericalRange': return ( ); case 'hierarchical': return ( ); case 'dateRange': return ( ); default: return null; } })}
); } function RegularFacetContent({ staticState, facetController, }: { staticState: RegularFacetState; facetController?: RegularFacet; }) { return ( <> {staticState.values.map((facetValue) => ( <4>
facetController?.toggleSelect(facetValue)} />
))} ); } ``` <1> Retrieve your [`facetGenerator`](https://docs.coveo.com/en/headless-react/latest/reference/interfaces/SSR_Commerce.index.FacetGenerator.html) controller hook. <2> Iterate over the facets returned by the controller. Render a different component based on the facet's type. <3> Render the `RegularFacetContent` component for regular facets, passing in the facet and the facet controller. <4> Render the facet values as checkboxes. When the user selects a checkbox, call the [`toggleSelect`](https://docs.coveo.com/en/headless-react/latest/reference/types/SSR_Commerce.index.CoreCommerceFacet.html) method to select or deselect the facet value. > **Note** > > For details on implementing other types of facets, see the [Barca Sports Hydrogen sample repository](https://github.com/coveo-labs/barca-sports-hydrogen/blob/main/app/components/Search/Facets.tsx). ## Sorting Sorting lets users order results based on certain criteria like relevance, popularity, or price. The following snippet shows how to implement sorting: ```tsx import {engineDefinition} from '~/lib/coveo.engine'; import type {SortCriterion} from '@coveo/headless-react/ssr-commerce'; import {SortBy} from '@coveo/headless-react/ssr-commerce'; export function Sorts() { const sort = engineDefinition.controllers.useSort(); <1> const handleSortSelection = (option: SortCriterion) => { sort.methods?.sortBy(option); }; const getSortLabel = (option: SortCriterion) => option.by === SortBy.Fields ? option.fields[0].displayName : option.by; return ( <> {sort.state.availableSorts.map((option) => ( <2> ))} ); } ``` <1> Retrieve your [`sort`](https://docs.coveo.com/en/headless-react/latest/reference/interfaces/SSR_Commerce.index.Sort.html) controller hook. <2> Display buttons for each available option. <3> When a user selects a button, call the `handleSortSelection` helper method. This method uses the [`sortBy`](https://docs.coveo.com/en/headless-react/latest/reference/interfaces/SSR_Commerce.index.Sort.html#sortby) method to sort results based on the selected option. <4> Display the option label. > **Important** > > Metadata keys defined in [variant](https://docs.coveo.com/en/m53g0506/) and [availability](https://docs.coveo.com/en/m53g0124/) data can be used for filtering with [facets](https://docs.coveo.com/en/198/), but can't be used for sorting results. ## Pagination Pagination breaks large sets of results into smaller, manageable pages, improving navigation. The following snippet shows how to implement pagination in a Shopify Hydrogen interface: ```tsx import {engineDefinition} from '~/lib/coveo.engine'; export function Pagination() { const pagination = engineDefinition.controllers.usePagination(); <1> return ( pagination.state.totalPages > 1 && (
<2>

) ); } ``` <1> Retrieve your [`pagination`](https://docs.coveo.com/en/headless-react/latest/reference/interfaces/SSR_Commerce.index.Pagination.html) controller hook. <2> Display buttons to navigate between pages.