Add product filtering

You've got shop pages featuring products, categories, and sort options. You want buyers to be able to filter the shop's products. Product filtering allows buyers to narrow down the products a merchant has published to the channel, based on specific attributes. This can help buyers discover products that are relevant to their preferences.

In this tutorial, you'll add filtering functionality to products. You'll set up filters by price range and availability. Price range options will be in intervals of $49 and availability options will be "In stock" and "Sold out". However, you can follow a similar structure to provide filtering by other product attributes.

An image of the merchant's shop page with filtering checkboxes, showing products that are in stock and less than $49

What you'll learn

After finishing this tutorial, you'll know how to add product filtering functionality to shop pages.


Step 1: Add the product filtering component

You'll create a UI component to render checkboxes with price range and availability options.

  1. In pages/shops/[id].js, create a list of price range filters.

    You'll use greater than or equal to (gte) and less than or equal to (lte) to create a string for each price option.

  2. Create a ProductFilters component that accepts a currencyCode property and uses it to create the price filter options.

    The price range options are static, so you'll use the useMemo React hook to prevent the code from re-running on every page render.

  3. Update the ProductFilters component to return a list of price and availability filters rendered as checkboxes.

    The component accepts a list of the selected availability and price filters. It also accepts a list of current URL parameters so that when filters change, any category, sort, and existing filters persist as required.

Step 2: Update shop page components

In this step, you'll include the filter component on the shop pages. You'll need to verify that your app is retrieving the data the ProductFilters component requires.

You'll use URL parameters to manage the filtering state, similar to what was done for product categories and sorting. The URL will include availability and price parameters. Each parameter can accept multiple values. For example, if both the “In stock” and “Sold out” options are selected, then the URL parameters would look like ?availability=1&availability=0.

  1. In pages/shops/[id].js, create a getFilterArray helper function to return an array containing all selected filters.

    If a single filter is selected, then the router query returns a string instead of an array of strings. This helps to maintain a consistent data structure when buyers use the filters.

  2. Update the getUrlsParams helper to include filters. The helper accepts availability and price arguments and includes them in the return object.

    This step is required because multiple filters can be selected, and you need to ensure that previously-selected filters should be available in the base urlParams object. Using the helper method that ensures that filter parameters are always an array, if they exist.

  3. Update the ProductSection component to get the selected availability and price filters from the router query, and update the component to use a grid layout to filters are rendered to the left of the grid on larger screens.

    You'll also update the ProductSection to do the following:

    • Pass the filters into the getUrlParams helper function to get URL parameters that contain the filters.
    • Pass the filters into the getFilterArray helper to get the availability and price filters to pass into the ProductFilters component.
    • Accept a currencyCode parameter and pass it through to the ProductFilters component.

  4. Update the shop query to retrieve the shop's currencyCode.

    Because the data returned from the query is already being added to the Shop component's state, you'll use it to pass the currencyCode parameter into the ProductSection component.

Step 3: Update the product grid columns

Because you're adding the filters to the left of the product grid, you'll update the ProductGrid component to support a three-column layout in addition to the current four-column layout.

  1. In components/productGrid.js, update the ProductGrid component to accept a columns property, with 4 as the default.

    The columns property will control the number of columns in the grid on larger screens.

  2. In pages/shops/[id].js, update the PaginatedProducts component to pass in columns value of 3 to the ProductGrid component.

Your merchant shop page should now look like this:

An image of the merchant's shop page with filtering checkboxes

Step 4: Filter products from Storefront API

To filter products returned from the Storefront API, you'll update the product query to use the selected availability and price filters in the query string. For each filter type (availability/price), you'll concatenate selected options with OR, and you'll join selected options, along with the category string, with AND.

  1. In pages/shops/[id].js update the getProductQuery helper to accept availability and price arguments, and use them to create the query string.

    Because you're already using this helper to get the query variable for the product query, you don't need to change the query itself.

  2. Update the effect in the ProductSection component to run when the filters are changed.

    You should also pass the availability and price variables into the getProductQuery helper.

Step 5: Update pagination and sorting

The selected filters should persist across pagination and when the sorting is updated. Because you've already updated the getUrlParams helper function, the pagination and sorting components should automatically be receiving a base URL parameter object that includes the selected filters.

Next steps