Limits and guarantees¶
Advanced Product Filters puts a facet panel beside your category, brand, search and specials pages, so a shopper narrows a listing by brand, price, category, availability, filter group, option and attribute, and sees how many products each tick would leave. This page is where that promise is written out exactly, including where it stops. Read it before you switch Status on in a store you care about.
At a glance¶
| If you are asking | The short answer |
|---|---|
| Does installing change my storefront? | No. Status starts off, and the panel it placed renders nothing until you switch it on. More |
| Do two ticks in one facet narrow or widen? | Widen. Ticks within one facet are OR; facets combine with AND. More |
| Does the page reload when a shopper ticks a box? | Yes. There is no AJAX: every change is a page load that keeps the selection on every page, sort and limit link. It works without JavaScript. More |
| Will search engines index my filtered pages? | No. A filtered page says noindex, follow, and its canonical is the unfiltered page. More |
| Does it filter search results on its own? | No. Facets on search results need Product Search 1.5.0 or later. Without it the search page shows no panel. More |
| Does the price range match what the cart charges? | It bounds the price a listing tile displays. On OpenCart 4.1 that can differ from what the cart charges. More |
| Does it see B2B price lists? | Yes, with B2B Pricing 1.1.0 or later on OpenCart 4.1. Price sort is still OpenCart's order. More |
| Does an import keep the counts right? | Not straight away. A bulk load is stale until you press Rebuild or the nightly run catches it. More |
| How big a catalogue is it for? | Up to about 10,000 products. Every count is worked out live, with no cache. More |
| Does uninstalling remove its tables? | No. Its four tables and its copy of your placements stay, so an update loses nothing. More |
What installing changes¶
Nothing a shopper can see, until you switch Status on. Installing places the panel in Column Left and Content Top of every layout your category, brand, search and specials pages use, on every store. On stock data those are the Category, Search and Default layouts. The brand page and Specials have no layout of their own, so they take Default, and so does every other page that uses Default. The panel draws only on the four product listings, so a placement on Default shows nothing on your information pages.
Status is per store. A store you never saved follows the default store, so you can switch it on for one storefront first.
The panel draws only where it has something to offer. On a listing where every facet is hidden, which happens when every value would give the same products or none, no panel is drawn and the page is exactly OpenCart's.
Phones need the Content Top placement, and installing adds it. OpenCart's default theme hides the side columns below 768px wide, so a phone never sees the Column Left copy. The Content Top copy is the one a phone shows, folded into one Filter (2) · 14 products button, and the stylesheet hides it on a wider screen wherever a column copy is also on the page. Remove the Content Top placement and phones have no filters.
Per-category and per-brand layout overrides are not placed. If you gave a category or a brand a layout of its own in its Design tab, that layout is your exception, and putting the panel there is yours to decide in Design → Layouts.
How a selection narrows¶
Ticks within one facet widen the listing; facets narrow it. Ticking Apple and Canon shows products of either brand. Adding In stock shows only the ones of those brands that are in stock. Every facet is a list of checkboxes, and Price is two boxes, a lowest and a highest. There is no radio button, drop-down or slider, because one value per facet would break that rule.
Each count is what ticking that value would give, with your other ticks applied and that facet's own ticks left out. A value that would give no products is hidden rather than greyed out, unless it is already ticked. A facet left with nothing to offer is hidden too.
Every change is a page load. There is no AJAX. With JavaScript, a tick or a typed price submits at once and the Apply button is hidden; in the phone copy the shopper ticks several boxes and then presses Apply. A browser too old to submit the form for it, Safari before 16, keeps Apply instead. Without JavaScript the panel is an ordinary form: Apply submits it, and so does a small › beside the price boxes. Either way the selection is in the address, so a filtered page can be bookmarked or shared, and page, sort and limit links keep it. A new tick starts the shopper on page 1.
A value that no longer resolves is dropped. A bookmarked link naming a brand you have since deleted shows the listing as if that value were not there, and the page's own links stop carrying it. A link with nothing left but such values is the ordinary, indexable page.
A language switch drops attribute selections. An attribute value is its text, and the text is per language.
Attribute text containing &, +, % or # does not survive OpenCart's
currency switcher. The switcher rebuilds the address without encoding those
characters, so the attribute tick is lost or cut short.
Attribute text over 255 characters carries no value. It is not offered, and a link naming it is ignored. An attribute value is its exact text: case and accents are compared the way your database compares them, text is not split on commas, and numbers are not turned into ranges.
In stock means a quantity above zero, whatever stock status label the product shows. 2-3 Days and Pre-Order are free text a filter cannot rank.
What the price range bounds¶
The price a listing tile displays: the special if there is one, else the price, with tax as your store displays it and in the shopper's currency. On OpenCart 4.0 that already includes a quantity-1 discount, because the tile does. On 4.1 a listing tile ignores the discount (the product page applies it, which is OpenCart's own inconsistency), and the range follows the tile.
The price range bounds what is displayed, not what the 4.1 cart charges. Where OpenCart 4.1 shows one price on the tile and charges another, the range agrees with the tile.
A currency switch reinterprets a typed price bound. The bound is a number in whatever currency the shopper is looking at. Typing 100 in euros and then switching to dollars bounds at 100 dollars; it is not converted.
Other extensions' price rewrites made after the listing is built are not seen, with the one exception of B2B Pricing's list prices below. An extension that changes a tile's price on its way to the page is invisible to the range.
Guests who may not see prices get no Price facet. Where Login Display Prices is on in your settings, a shopper who has not signed in is not offered the facet, and a price range in the address is ignored.
On OpenCart 4.1, while Status is on, the Specials page shows the special the
product page shows. Stock shows the raw figure of an arbitrary row, for
example 10.00 for a 10% special, so prices on that page can differ from stock.
On 4.0 the Specials page is OpenCart's own until a shopper ticks something.
B2B price lists¶
On OpenCart 4.1, with B2B Pricing 1.1.0 or later, the price range bounds the price each buyer is shown, including a price list's price. With B2B Pricing 1.0.0 it bounds OpenCart's own price, so a buyer on a price list can see a product priced outside the range they chose. Update B2B Pricing to fix that.
Price sort stays OpenCart's order for list buyers. A buyer on a price list who sorts by price gets the order of OpenCart's own prices, not of their list prices.
B2B Pricing is asked about every product on the listing, not only the ones your other ticks leave. With a price range typed, the facet asks B2B Pricing once per page for the list prices of the whole listing the shopper is on, with no facet applied. That is deliberate: each count leaves its own facet out, so products the shopper's other ticks exclude come back into some counts, and they have to be bounded by their list price too. A narrower question would make those counts wrong. It is one question per page, and it costs nothing at all on a store without B2B Pricing.
On search results with a price range typed, that question covers your whole catalogue. Product Search says which products matched only after the narrowing has been built, so the narrowing asks B2B Pricing about every product in the store, once. On a catalogue within the size this extension is for, that is one call; on a much larger one with B2B Pricing installed, typed price ranges on search results are where it will be felt first.
Search results need Product Search¶
Facets on search results need Product Search 1.5.0 or later (free). Without it, the search page shows no panel. Advanced Product Filters never replaces OpenCart's own search: it narrows Product Search's results to the shopper's ticks and counts over the products Product Search matched.
Tag links and terms Product Search cannot read also show no panel. A tag link, an empty search, or Product Search switched off leaves nothing to count over, so the page is the search page as it was.
The Category facet on search results offers your top-level categories. On a category page it offers that category's children, so a leaf category's page shows no Category facet.
On 4.0.2.2 and later, a parent category page lists only its own products. OpenCart stopped including subcategories there, so a child value counts only the products filed in both the parent and the child, and a store that files products in leaf categories only shows no Category facet on a parent page. On 4.0.2.0 and 4.0.2.1 a parent page lists its descendants, and the facet counts them.
What a search engine is told¶
A filtered page says noindex, follow, and its canonical is the unfiltered
first page of the same listing, byte for byte the address OpenCart (and SEO
Suite Pro, when installed) builds for it. rel=prev and rel=next are removed.
Search results get no canonical, because OpenCart gives them none.
An unfiltered page is OpenCart's own, and so is a page whose only ticks no longer resolve.
An SEO Suite Pro override with nofollow beats our follow. A robots
override you typed for a page in SEO Suite Pro is printed after ours and wins.
When the counts are stale¶
The counts for brand, category, filter group, option and attribute come from an index Advanced Product Filters keeps beside your catalogue. Price and availability are read live and are never stale.
Saving in admin keeps the index current. Adding, copying, editing or deleting a product, editing or deleting a category, moving a filter to another group, and an order changing option stock all update it as they happen.
Bulk loads, Import/export included, are stale until Rebuild or the nightly run. Anything written straight to the database, or through a tool that does not call OpenCart's own save, goes behind the index's back. Press Rebuild on the Facets tab to bring it up to date now. A nightly job on Extensions → Cron Jobs does the same once a day. While a rebuild runs, the storefront keeps the facets it had.
On OpenCart 4.1.0.4 the nightly run does not happen, because that release's own scheduler cannot start (see requirements). Rebuild is the way round it there.
How big a catalogue¶
Up to about 10,000 products. Every count is worked out when the page is drawn, from the index and from the live price and stock, with no cache, so a filter is never showing yesterday's numbers. The cost of that grows with the catalogue. The extra database queries each listing page pays are published, page by page, on what it costs. The Specials page is not among the pages measured there: on OpenCart 4.1, while Status is on, it pays one extra query on every visit, filtered or not, for the typed specials described above.
Where an unfiltered listing's queries go¶
On the measured category page (+12) and brand page (+11), statement by statement:
| Queries | What for |
|---|---|
| 3 | The counts: one count of every value in the index, one live count giving the total and In stock, and the Price facet's lowest and highest price. |
| 4 on a category page, 3 on a brand page | Names for the values counted: one per kind of facet that has any — brands, options, attributes, subcategories. A facet that cannot narrow the page (Brand on a brand page) is not looked up. The subcategory names repeat a lookup OpenCart's own category page makes for its refine links; the two are not shared. |
| 1 | The Facets list, so a facet you switched off stays off. |
| 1 | The tax classes, so the Price facet's bounds are the prices your tiles show, tax included where you show it. |
| 1 | OpenCart's lookup of your translations for the panel's language file. Loaded once, for both copies. |
| 2 | OpenCart's lookup of a theme override for the panel's template, once per copy: the panel is drawn once for desktop and once for phones. |
A filtered page adds one more count for each facet with a box ticked (In stock excepted: the live count already has it), and runs its own rows and total in place of OpenCart's.
The Facets list¶
The Facets list is set on the settings screen only. There is no import, no API, and no per-store list: one list serves every store. A facet with no row is on, so an attribute created last week appears in the panel without a trip to the settings. Switch off the ones nobody narrows by.
Facet titles and value names are your catalogue's, as you typed them in Catalog. The four titles of our own (Brand, Price, Category, Availability) and In stock are language strings. Values keep the order your catalogue already gives them; there is no second order kept here.
A facet shows its first 6 values and folds the rest behind Show N more. Every facet is open; on a phone the whole panel is already folded behind one button.
Update and uninstall¶
Placements survive an update as they stood when it began. An update is an uninstall and an install. Your placements, including any you moved or deleted, come back exactly as they were, and a panel you removed from every layout is never re-placed. Your settings, the Facets list and a pause or schedule you set on the cron job come back too; see what an update keeps.
Uninstalling for good leaves the four tables and the placement copy behind. Uninstall removes the settings, the events and the cron job, and leaves the index, the attribute dictionary, the Facets list and the copy of your placements, because it cannot tell an uninstall from the first half of an update. None of them holds anything about a person; see what this holds about a person.
Language¶
The panel's own words (Filter, Apply, Clear all, the four facet titles, In stock, Show N more) are shopper text, and so are the settings screen's. Everything else a shopper reads in the panel is your own catalogue: brand, category, filter, option and attribute names, in the shopper's language. Which of our strings a named native speaker has read is counted, per language, on the shared language promise page. A string nobody has read is served in English rather than blank.
Anything not described on this page should be assumed absent. If you are buying on the strength of a behaviour you have not read here, ask first.