User guide

Layered Navigation for Magento 2: User Guide

Filters that shoppers actually use: several options per filter with correct counts, swatches, a price slider, Ajax updates and optional readable filter URLs, on Luma and Hyvä.

  • Version 2.0.3
  • Magento 2.4.6 to 2.4.9
  • PHP 8.2 to 8.5
  • Hyvä and Luma

Better filters for category pages and search results on Luma and Hyvä: several options per filter with correct counts, swatches, a price slider, Ajax filtering and optional SEO-friendly filter URLs. This guide covers installation, configuration and day-to-day use.

Filters on a Luma category page
Filters on a Luma category page

1. Requirements

MagentoOpen Source or Adobe Commerce 2.4.6 to 2.4.9
PHP8.2 to 8.5 (Magento 2.4.6: PHP 8.2)
Search engineOpenSearch or Elasticsearch (Magento's standard catalogue search)
ThemesLuma, Blank and themes based on them; Hyvä (tested with Hyvä 1.5 and the default theme)
Othercommercegears/module-core (installed automatically)

The module replaces the template of the blocks catalog.leftnav and catalogsearch.leftnav. Themes that move these blocks keep working; a theme that replaces them with its own block needs the template set again.

2. Installation

With Composer. Use the Composer keys from your account on commercegears.com; how to get access is described at https://commercegears.com/composer-access/.

composer config repositories.commercegears composer https://repo.commercegears.com
composer config --auth http-basic.repo.commercegears.com PUBLIC_KEY PRIVATE_KEY
composer require commercegears/module-layered-navigation
bin/magento setup:upgrade
bin/magento setup:di:compile            # production mode only
bin/magento setup:static-content:deploy # production mode only
bin/magento cache:flush

Hyvä: the module registers itself for Hyvä's Tailwind build. After installing, rebuild your theme CSS (npm run build in the theme's web/tailwind folder) so the filter styles are included. Luma loads the same styles as css/layered-navigation.css without a build step.

To update later: composer update commercegears/module-layered-navigation, then the same bin/magento commands.

3. Quick start

  1. Install the module. It is enabled by default, so your category pages show the new filters straight away.
  2. Open Stores > Attributes > Product, pick an attribute that is used in layered navigation (for example color), tab Storefront Properties, and choose Filter Display, Filter Option Order and Filter Expanded on Page Load.
  3. Optional: switch on SEO-Friendly Filter URLs under CommerceGears > Layered Navigation > Settings for the store views where you want readable addresses.
  4. Refresh the page cache (System > Cache Management) after changing settings.

4. Settings

CommerceGears > Layered Navigation > Settings, the same page as Stores > Configuration > CommerceGears > Layered Navigation. Every setting can be set per website and store view. Changing a setting marks the page cache as invalid; refresh it under System > Cache Management.

Layered Navigation settings
Layered Navigation settings

General

SettingDefaultWhat it does
EnabledYesWhen set to No, the standard Magento layered navigation is shown.
Ajax FilteringYesFilters, chips and page links update the product list without a full page reload. Each filtered list keeps its own address, so the Back button, bookmarks and the page cache still work.
Show More Link After8Number of options shown in a filter before a "Show more" link. 0 shows all options.
Search Box for Filters With More Than15A filter with more options than this gets a search box. 0 turns the search box off.
Hide Filters With Only One OptionNoA filter that offers a single option cannot narrow the list, so it can be hidden. Selected filters are always shown.

Filter URLs

SettingDefaultWhat it does
SEO-Friendly Filter URLsNoCategory pages only: readable addresses such as /women/tops-women/color-black-blue/size-m.html instead of ?color=49,50&size=168. Old addresses are redirected (301). Price ranges, sorting and paging stay in the query string.

5. Settings per attribute

Open Stores > Attributes > Product, edit an attribute and go to the tab Storefront Properties. Below "Position" you find three fields:

Filter fields on the attribute page
Filter fields on the attribute page
FieldOptions
Filter DisplayAutomatic (default): swatches for swatch attributes, a slider for price and decimal attributes, checkboxes for everything else. Checkboxes: several options can be selected. Dropdown: one option. Swatches: swatch attributes only. Slider: price and decimal attributes only. Price ranges as links: Magento's price ranges, price and decimal attributes only. A choice that does not fit the attribute falls back to Automatic.
Filter Option OrderOption position (default, as sorted under Manage Options), Name (A to Z), Number of products (most first).
Filter Expanded on Page LoadNo (default) or Yes. A filter with a selected option is always expanded.

"Use in Layered Navigation" and "Position" are Magento's own fields and work as usual: they decide whether the attribute is a filter and where it appears in the list.

6. What your customers see

Filters on Hyvä
Filters on Hyvä

Several options per filter. Options of one attribute are combined with OR, different attributes with AND. A shopper can pick Black and Blue and then size M and sees products that are black or blue and available in M. The counts next to the options of a filter that is already in use are calculated without that filter's own selection, so they show what the shopper would get by adding that option. This costs one extra search request per filtered attribute (at most six per page).

Chips. Every selected option appears under "Now shopping by" with a remove link. "Clear All" removes every filter, and each filter has its own "Clear <filter>" link.

Swatches. Colour, image and text swatch attributes keep their swatches and allow several choices. Colour swatches only accept hex colour values.

Price slider. Price (and decimal attributes set to Slider) get a range slider plus from and to boxes and a Go button. Numbers typed into the boxes are used as typed. The slider needs JavaScript; without it the other filters still work as links.

Long lists. After the number of options set in Show More Link After a "Show more" link appears. Filters with more options than Search Box for Filters With More Than get a search box that narrows the visible options.

Mobile. On small screens the whole filter block folds behind a "Shop By" bar with a badge for the number of active filters.

Mobile filters on Luma (left) and Hyvä (right)
Mobile filters on Luma (left) and Hyvä (right)

Ajax filtering. With Ajax on, clicking a filter, a chip or a page link replaces the product column and the filter block with the same HTML a normal page load returns and updates the address bar. Back and Forward work. Every filtered list is a normal GET address, so it also works without JavaScript and the full page cache stores it like any other page.

Search results. The same filters appear on the search results page, with query-string addresses.

Accessibility. Filters are <details> elements, checkbox options are links with role="checkbox" (Space or Enter), and the slider uses native range inputs plus number inputs.

7. SEO-friendly filter URLs

Switch on SEO-Friendly Filter URLs for the store views you want. Filtered category pages then use this scheme:

<category path without suffix>/<attribute code>-<slug>[-<slug>...][/<attribute code>-<slug>...]<category suffix>

Example: /women/tops-women/color-black-blue/size-m.html.

  • One path segment per attribute, sorted by attribute code; slugs within a segment are sorted alphabetically, so each combination has exactly one address. Other orders redirect (301) to it, and so do the old query-string addresses.
  • Only dropdown, multiple select and yes/no attributes go into the path. Price and decimal ranges, the category filter, sorting and paging stay in the query string (?price=20-50&p=2).
  • The filter router answers only when the path ends with the category URL suffix, the trailing segments are valid filters, the full path is not an existing URL rewrite (products, CMS pages and real subcategories always win) and the rest of the path is a category of the store view.
  • Links that combine two or more filter values get rel="nofollow", so crawlers are not sent through every combination. Single-filter pages stay crawlable.
Friendly filter URLs in the German store view
Friendly filter URLs in the German store view

Filter URL Slugs

CommerceGears > Layered Navigation > Filter URL Slugs

Filter URL Slugs page
Filter URL Slugs page
  1. Choose an Attribute and a Store View ("All Store Views" or a single view) and click Show Options.
  2. The table lists each option with its admin label, the store view label, the Slug in Use and a Custom Slug field.
  3. Enter custom slugs using a-z, 0-9 and single hyphens. Invalid entries are flagged next to the field and checked again on save; if any entry is invalid, nothing is saved and the form shows your entries again so you can correct them.
  4. Click Save URL Slugs in the page actions bar. Saving cleans the full page cache.

Empty fields use the automatic slug: the transliterated store view label, for example "Light Blue" becomes light-blue. When two options would get the same slug, the option ID is appended. A slug for a single store view takes priority over the one for "All Store Views". Yes/No attributes use yes and no.

Settings in the actions bar opens the module settings, and Edit Attribute opens the attribute.

8. Command line

bin/magento commercegears:layered-navigation:slugs <attribute_code> [--store=<code or ID>]

Lists the option IDs, labels and the URL segment of each option for a store view (read-only). Example: bin/magento commercegears:layered-navigation:slugs color --store=de.

9. For developers

JavaScript event. After every Ajax update this event fires:

document.addEventListener('commercegears:layered-navigation:updated', function (event) {
    // event.detail.url      - the new address
    // event.detail.document - the parsed HTML document of the new page
});

Use it to re-run code that reads the product list on page load, such as analytics list views, sliders or lazy loaders. window.CommerceGearsLayeredNavigation.load(url) loads a filtered address the same way.

PHP API. CommerceGears\LayeredNavigation\Api\FilterStateInterface tells other modules what is filtered on the current category or search page: isFiltered(), getAppliedFilters() and isFriendlyUrl(). It is filled while the layered navigation is built, so read it when the page head or body is rendered. The filters are also added to Magento's layer state as usual, so code that reads the layer state keeps working in both URL modes.

10. Permissions (ACL)

Under System > Permissions > User Roles > Role Resources, CommerceGears > Layered Navigation:

ResourceGives access to
CommerceGears_LayeredNavigation::layered_navigationThe menu entry
CommerceGears_LayeredNavigation::slugsFilter URL Slugs
CommerceGears_LayeredNavigation::configSettings

A role can be given either page on its own. The fields on the attribute page use Magento's own attribute permissions.

11. Troubleshooting

ProblemSolution
The old filters are still shownCheck Enabled for the store view and refresh the page cache. If your theme replaces the catalog.leftnav block with its own block, set the module's template on it again.
Filters look unstyled on HyväRebuild the theme CSS (npm run build in web/tailwind) so the module's styles are compiled in.
A setting has no effect on the storefrontSettings mark the page cache as invalid; refresh it under System > Cache Management.
Ajax filtering does a full page loadThe theme has no .column.main element, so the module falls back to normal page loads. Filtering still works.
A filter is not in the friendly URLOnly dropdown, multiple select and yes/no attributes go into the path; price, decimal and category filters stay in the query string. Search results always use the query string.
Filter names or options are in English in another language's store viewThe module's own texts ship in English and German. Filter names ("Color", "Size", "Price") and option labels come from the attribute: set the store view labels under Stores > Attributes > Product > Manage Labels and Manage Options.
An old friendly address returns 404The option label (and with it the automatic slug) was changed. Set a custom slug under Filter URL Slugs to keep the address.
An option stays in the query string with friendly URLs onIf a combination of slugs could be read in two ways, that filter stays in the query string. Give one of the options a different custom slug.

12. Uninstall

bin/magento module:disable CommerceGears_LayeredNavigation
composer remove commercegears/module-layered-navigation
bin/magento setup:upgrade
bin/magento cache:flush

With friendly URLs switched off (or the module removed), category pages use Magento's own filter addresses again.

This guide is for version 2.0.3 and also comes with the module, in docs/user-guide.md. All user guides