AJAX Faceted Filters for PrestaShop — Documentation
Install, configure and operate AJAX faceted navigation: facets, price slider, filtered-URL SEO, Creative Elements compatibility, performance under crawler traffic.
This guide covers installing, configuring and operating the AJAX Faceted Filters module for PrestaShop 8 and 9. The module replaces the native faceted search with faster AJAX navigation, a price slider with histogram, and fine-grained control over the SEO indexability of filtered pages.
Installation
In your back office, open Modules > Module Manager, click Upload a module and drop the dffacetedfilter.zip file. On installation the module automatically:
- creates its tables and admin tab;
- runs a first facet sync from your catalog;
- warms up the price index (within a few seconds).
The module takes priority on the productSearchProvider hook so it runs ahead of PrestaShop’s native faceted search. No theme file is overridden.
First configuration
Go to Catalog > Faceted filters. There you’ll find the facet list, an overview dashboard and the general and SEO settings.
Sync facets
The Sync facets from catalog button automatically creates the missing facets from your attribute groups, features and built-in facets (price, brand, on-sale, availability, condition). Existing facets are never modified: you can re-run the sync safely after adding an attribute or a feature.
Rebuild the price index
The Rebuild price index button recomputes the price bounds of every product, in batches, with a progress bar. Run it after installation and after any bulk product import.
Managing facets
Each row can be reordered by drag and drop (the order drives both the front-office display order and the normalized URL order), enabled or disabled, and edited.
Facet options
- Label: the displayed name, translatable per language.
- Display: checkboxes, color / texture swatches, or plain links. Color groups automatically inherit the swatch display.
- Multi-select: allows selecting several values of the same facet at once, combined with OR.
- Show counters: shows the product count next to each value.
- Hide empty values: hides zero-product values instead of showing them greyed out.
- Collapsed by default: the facet shows closed and the visitor expands it on click.
- Values before “Show more”: number of values shown before the expand button (0 = show all).
Disjunctive counting is applied: each facet is counted taking every other selection into account, but not its own. Selecting “Red” therefore never zeroes out “Blue” within the same facet.
The price slider and its index
The Price facet appears as a dual range slider. Above it, a product distribution histogram over twelve buckets helps visitors gauge the price range. This data comes from a dedicated price index, separate from PrestaShop’s tables, to stay fast even on a large catalog.
Index maintenance
The index is updated in real time by hooks whenever a product, a specific price or a combination changes. For a scheduled full rebuild, use the cron endpoint shown in the back office:
/module/dffacetedfilter/cron?token=YOUR_TOKEN
The call processes the index in chunks with a time guard of about 20 seconds; if products remain, the response returns the continuation URL to call again. A nightly call is enough in most cases.
The Filter prices tax included setting controls whether the slider reasons on tax-inclusive or tax-excluded prices. The index stores prices in the default currency; the display is converted to the current currency.
The On-sale facet
The On sale facet filters products currently reduced: items flagged “on sale” or covered by an active specific price (a running reduction, within its date range, for the current currency, country and group). It is created enabled by default during the sync.
Availability and condition
Two complementary built-in facets are created disabled, to enable as needed:
- Availability: an “In stock” value that respects your out-of-stock ordering setting.
- Condition: new, used, refurbished.
Restricting a facet to categories
By default a facet appears on every listing page. The edit form offers two fields to change that: a category rule and the categories tree it applies to.
- Show only on the categories below: the facet appears solely on the ticked categories and their subcategories. This is the right setting to show “Shoe size” only under Shoes, or “Screen size” only under Tech.
- Show everywhere except on the categories below: the facet appears across the shop, except on the ticked categories and their subcategories. This is the right setting to hide “Wine type” on Red Wines and White Wines, where the facet adds nothing, while keeping it everywhere else.
Unticking a category never hides a facet. While the tree is entirely unticked, the rule does not apply and the facet stays global. To remove a facet from a few categories, tick those categories and pick the “except” rule.
A rule set on a category also covers its subcategories. Ticking “Wines” in “only” mode therefore shows the facet on Red Wines and White Wines: to exclude those two, switch to “except” mode and tick them directly.
Facet SEO
This is one of the module’s strengths: you decide precisely which filtered pages may be indexed. Filter URLs are readable and follow this format:
/category?dff=color:red,navy/price:10,50/brand:nike
The parameter is named q instead of dff in full Creative Elements mode; the format itself is identical. Facets are separated by a slash, a facet slug and its values by a colon, and values by a comma. The facet order and the value sorting are normalized so that a given combination always produces a single canonical URL.
SEO settings
- Indexable (per facet): a non-indexable facet forces the filtered page to
noindex, followand addsrel="nofollow"on its links. - Max. indexable values: beyond this number of selected values, the page switches to
noindex, follow. A value of 1 is the safest against crawl-budget explosion. - Self-canonical on indexable pages: indexable pages get a canonical tag pointing to their own normalized filter URL. The theme canonical is removed on the front end to avoid duplicates.
- Noindex all filtered pages: forces
noindex, followon every filtered page, whatever the per-facet settings.
A filtered page is also set to noindex, follow when a sort parameter is present, since it is a duplicate of the page in its default order.
AJAX modes
The AJAX mode setting determines how the page updates when a filter is clicked:
- Theme (native events) — recommended: the module emits PrestaShop’s native event and lets the core and theme refresh the list, the facets and the browser history. This is the most compatible mode with classic-based themes.
- Self-managed: for non-standard themes, the module fetches the page over AJAX itself and swaps the relevant blocks. Use it only if the Theme mode doesn’t refresh the page correctly.
Keeping robots away from filters
A noindex tag prevents indexing, not loading: the robot must first fetch the page to read the tag. For it to stop loading filter combinations, it must not discover them. Two settings take care of that, in Catalog > Faceted filters.
- Crawlable filter links: Indexable facets only keeps a real link on the facets you marked indexable and turns the others into JavaScript-driven links. Your customers click exactly as before, but robots no longer find those combinations in the page.
- Old native filter URLs (?q=): URLs left by PrestaShop’s native faceted search, such as
?q=Brand-..., can receive a 410 Gone response before any catalog query even starts, or a 301 redirect to the unfiltered listing. A 410 is the cheapest answer for the server and the one that makes search engines drop the URL. This setting applies neither in full Creative Elements mode, whereqis the module’s parameter, nor on the search page.
For a shop that has suffered a wave of robots on its filters, the recommended combination is: crawlable links set to Indexable facets only with very few indexable facets, old URLs set to 410 Gone, and the “Theme” AJAX mode.
Mobile filter panel and active filters
Below a given screen width, the filter sidebar is hidden and opens as a panel from a “Filters” button. The Filter panel below (px) setting sets that breakpoint: 767 matches phones, 1024 suits layouts that also move the filter column on tablets. The panel closes with its “Show results” button, a click outside or the Escape key.
The Active filter labels setting chooses what each active filter chip shows: the facet and value (“Colour: Red”) or the value only (“Red”). Screen readers always get both.
Creative Elements compatibility
Creative Elements (WebshopWorks) does not read the facet block a module renders. Its Filters and Active Filters widgets, and its mobile Filters button, rebuild their own markup from the native facet collection carried by the search result. Since version 1.3 the module publishes that collection: all three widgets work and keep every one of their design controls, color swatches and price slider included.
The two settings
In Catalog > Faceted filters > Creative Elements compatibility:
- Compatibility mode: Full, when Creative Elements is installed, Full, always, Partial or Off. Full mode uses the Creative Elements filter widgets and
?q=URLs; partial mode keeps?dff=URLs and uses the module’s blocks (see below). - Filter block rendered by: Automatic hands the sidebar to Creative Elements on the listings whose template it owns, and keeps the module’s own block everywhere else. Pick This module if your Creative Elements listing template has no Filters widget and you want the DataFirefly sidebar instead.
In full mode, the URL parameter becomes q
Creative Elements hardcodes the q parameter, in its widgets as well as in the script of its price slider. In full mode the module therefore aligns on q instead of dff:
/category?q=color:red,navy/price:10,50/brand:nike
The format itself does not change, only the parameter name. URLs already generated with dff are 301-redirected to their q equivalent, so nothing indexed or bookmarked is lost.
If you filter or block traffic on the q parameter at your CDN or web application firewall, for instance after a crawl incident caused by the native faceted search, review those rules before enabling compatibility mode. Otherwise your own customers will be blocked as soon as they filter. Target behaviour (request rate, ASN, user agent) rather than the parameter name. Or pick partial mode, which keeps dff: your rules on q can then stay in place.
Partial mode: keeping dff URLs
In partial mode, the module does not publish its facets for the Creative Elements filter widgets, which stay empty, and URLs keep the ?dff= parameter. Instead, you place the module’s blocks in your listing template with the Creative Elements Module widget: select the module, then type one of these hook names.
displayDffFacets: the filter sidebar (also what shows when the hook field is left empty);displayDffActiveFilters: the active filters and the “Clear all” link;displayDffFiltersButton: a “Filters” button that opens the mobile panel.
To keep control over the button’s design, you can also use a Creative Elements Button widget and give it the CSS class dff-open-filters in its Advanced tab: it then opens the same panel. The Creative Elements product list, pagination, sort and counter widgets keep working as usual. In exchange, the filters’ look is set through the module’s accent colour and your own CSS, not through the Creative Elements Style tab.
Remove the Creative Elements Filters and Active Filters widgets from your template when you switch to partial mode: they no longer display anything.
Good to know
- Keep the Theme AJAX mode. Creative Elements relies on PrestaShop’s native event and returns its own rendered blocks; self-managed mode would not know how to swap them.
- From Creative Elements 3.x onwards, facet links are no longer real links but JavaScript-driven elements. That is good news for your crawl budget: filter combinations are no longer discoverable by a robot. In exchange, filtering becomes strictly JavaScript-dependent inside its interface.
- Avoid a
/character in the label of your Price facet: the Creative Elements slider builds its URL client-side from that label.
Counter cache
Computing disjunctive counters can be costly on a large catalog. The module caches their result for a short, configurable time (300 seconds by default). This cache is automatically invalidated on every catalog change and every facet edit. A Clear counter cache button is available in the back office.
Usage statistics
The dashboard at the top of the admin page summarizes the last 30 days: products indexed, number of filtered page views, share of crawl budget kept out of the index (filtered pages served as noindex) and a ranking of the most-used facets. Robot traffic is excluded from these figures, so they describe your customers’ behaviour. You can disable statistics recording in the performance settings.
Supported pages
Facets apply to category, brand, supplier, new-products, best-sellers, specials and search results pages (respecting PrestaShop’s native ranking). The Brand facet is automatically hidden on a brand page, and category-scoped facets on a search page.
Disabling the native faceted search
The module takes priority over ps_facetedsearch, but we recommend disabling the latter to avoid duplicate indexing work. A back-office warning reminds you if it is still active.
Troubleshooting
- Facets don’t show: run a sync, check that at least one facet is active, and that you are on a supported listing page.
- The price slider is missing: rebuild the price index; the Price facet hides itself while the index is empty for the displayed category.
- The page doesn’t refresh over AJAX: switch the AJAX mode to “Self-managed” if your theme doesn’t follow the PrestaShop standard.
- After a click, boxes do not tick and a second filter replaces the first: fixed in 1.4.3. The facet block was not refreshed after the AJAX filter. In the browser console,
dffFaceted.listening()must returntrue. - Filters show below the product list on mobile: fixed in 1.4.1 for Bootstrap 5 themes such as Hummingbird. Also check the filter panel breakpoint setting.
- Facet ordering is not saved: fixed in 1.3.1. Before that version PrestaShop posted the drag & drop payload under a key the module did not read; the notification reported success but nothing was written.
- A facet shows on a category I unticked: unticking does not hide. Tick that category and pick the “Show everywhere except on the categories below” rule.
- The Creative Elements widgets stay empty: in full mode, check that the compatibility mode is set to one of the “Full” options and that the module is in “Theme” AJAX mode. In partial mode this is expected: those widgets are replaced by the module’s blocks placed with the Module widget.
- The filter sidebar appears twice: your Creative Elements template contains a Filters widget and the module renders its own as well. Set Filter block rendered by to Automatic or Creative Elements widget.
- Too many indexed pages: lower the max. indexable values, make high-cardinality facets (color, size) non-indexable, or enable “Noindex all filtered pages” while you regain control.
The source code is shipped unencrypted. You get 12 months of compatibility updates and support within 24 h.
What’s new in version 1.4
Partial Creative Elements mode
URLs keep ?dff=, and the module’s filters, active filters and mobile button are placed in the layout with the Creative Elements Module widget. See the Creative Elements compatibility section.
Crawl control
Facet links can be reserved for indexable facets, and old ?q= URLs from the native search can receive a 410 before any catalog query. See the Keeping robots away from filters section.
Mobile panel and active filters
The mobile filter panel no longer depends on the theme’s utility classes, missing from Bootstrap 5 themes such as Hummingbird, and follows a configurable width breakpoint. Active filters can show the value only.
AJAX refresh
The module refreshes its own facets and active filters after every filter, without relying on the theme’s selectors. Two defects that prevented this refresh are fixed: the subscription to PrestaShop events happened too early to succeed (1.4.3), and the automatic switch to self-managed mode after 900 ms left page-builder widgets on the previous state (1.4.1).
What’s new in version 1.3.1
Two fixes reported in production.
Facet ordering is saved. PrestaShop posts the drag & drop payload under the identifier stripped of its id_ prefix, that is facet, not under the table name. The module read the wrong key and wrote nothing, while the browser still showed a confirmation. The order is now rebuilt in full from the payload, which makes the write idempotent, and the call returns a real status.
An “except” category rule. Category restriction used to be a whitelist only: a facet could be limited to some categories, never excluded from them. See the Restricting a facet to categories section above.
What’s new in version 1.3
Creative Elements compatibility
The module now publishes its facets as a native collection, the structure the page builder expects. Its Filters, Active Filters and Clear widgets, and its mobile Filters button, work with the module and keep all their design controls. See the Creative Elements compatibility section above, in particular the change of URL parameter name.
Performance under crawler traffic
Faceted navigation collapses under automated traffic because every distinct combination is a cache miss. This version removes the per-request work that does not depend on the selection:
- Pooled value maps: the possible values of each facet depend on the catalog, not on the selection. They are loaded from a single cache entry instead of one query and several disk lookups per facet on every page.
- Counter cache shielded: beyond three facets or six values, a combination is computed but no longer stored. Those are what crawlers generate, they are never read back, and storing them only inflated the table. Both thresholds are configurable.
- Catalog visibility: the customer-group check subquery, previously replayed inside every counting query, is dropped on category pages when no active category is restricted for the visitor’s groups.
- Landing pages without a query: the set of active targets is kept as a compact index, so the negative answer, by far the most frequent case, costs nothing.
- Statistics: no writes at all for robots.
These optimizations lower the cost of each filtered page, but they do not stop the crawl itself. A noindex tag still requires the page to be fetched and rendered before the robot can read it, and rel="nofollow" is only a weak discovery signal. Keeping robots away from filter URLs remains the job of your robots.txt and your edge filtering.
What’s new in version 1.2
SEO landing pages
In Catalog > Faceted filters > SEO landing pages, turn one precise filter combination (say Shoes × Color: red × Brand: Nike) into a real landing page: meta title, meta description, H1 and an editorial intro, per language. To target a combination, copy the value of the dff parameter (or q in full Creative Elements mode) from a filtered URL of your shop and paste it into the form.
An active landing is always indexable: it overrides the per-facet flags, the value cap and even the “Noindex all filtered pages” switch. The “noindex everything except my curated pages” strategy becomes possible.
Every active landing is listed in a dedicated XML sitemap with hreflang alternates, ready to submit in Search Console:
/module/dffacetedfilter/sitemap
Other improvements
- Sub-categories facet: offers the direct children of the displayed category; the listing then automatically includes the whole subtree.
- Per-facet value sorting: catalog position, alphabetical or descending product count.
- Color swatches as a grid or a list: each color facet can render as a horizontal swatch grid or a vertical list with labels and counters.
- Hide single-value facets: a facet whose only value covers the whole listing adds no filtering power; this setting removes it automatically.
- Accent colour: pick the colour of checked boxes, switches, the slider and badges; the text contrast is computed automatically.
- Resilient AJAX: if the theme does not answer the native event, the module automatically switches to self-managed mode; the scroll position is preserved after every filter action and mobile filters open in a full-screen modal.
- 8 front-office languages: EN, FR, ES, DE, IT, PL, PT, NL shipped with the module.