Le vendeur silencieux : comment optimiser les filtres produits de votre boutique Magento 2 pour la conversion
Why your product filtres are the silent salesperson
Think of product filtres as the quiet colleague who always nudges a shopper toward the right shelf. They don’t shout, they don’t upsell aggressively, but when they are in the right place and speak the client’s language, conversion happens. In Magento 2 stores, layered navigation and product filtres are exactly that — a silent salesperson working 24/7. Optimize them badly and you frustrate clients; optimize them well and you boost conversion, reduce abandonment, and increase average commande valeur.
What good filtreing actually does for conversion
- Reduces recherche friction: fewer clicks to the desired SKU.
- Sets realistic expectations: if shoppers can quickly exclude out-of-stock items, they are more likely to add what they see to cart.
- Guides purchase decisions: strategic filtres (prix ranges, attributes, categories, and stock status) focus attention on the items that convert best.
- Improves perceived site speed: returning a smaller, relevant set of products is faster and feels faster to clients.
Key metric improvements to expect
Quand vous optimize filtres correctly you should measure improvements in:
- Filter-to-add-to-cart rate (how often applying a filtre leads to add-to-cart)
- Cart conversion rate for filtreed sessions
- Average commande valeur (best when combining attribute filtres that promote higher-margin SKUs)
- Bounce rate on page de catégories (expected to drop)
- Customer satisfaction signals (time-to-find product, fewer recherchees)
Make stock status a strategic filtre — not just an afterthought
Stock status is your friend. Showing unavailable products or making clients wade through items that are out of stock increases frustration and abandonment. Instead of hiding stock data, use it to guide clients:
- Offer a default “In stock only” toggle on page de catégories during peak traffic or when inventaire is low.
- Show stock-based tri options like “In stock first” or “Available now.”
- Combine stock status with shipping/fulfillment availability (e.g., entrepôt-specific stock) when you run mulconseille inventories.
Practical Magento 2 exemple: add an “In stock only” filtre (étape-by-étape)
Below is a simplified exemple to add an “In stock only” checkbox filtre in Magento 2 layered navigation. This exemple demonstrates the main ideas: front-end toggle, contrôleur/observateur that modifies the product collection, and query join against stock status.
1) Create a small module skeleton
// registration.php
\
Place a minimal module.xml under etc/module.xml to enable the module. I won’t paste the boilerplate here — most Magento devs already have a module template. The important parts are the PHP classes we’ll add next.
2) Add a small observateur to inject the filtre into the category product collection
We hook into the catalog layer to alter the collection when the request contains our filtre param (for exemple: stock_status=1).
// etc/frontend/events.xml
<event name="catalog_block_product_list_collection">
<observer name="vendor_stockfilter_apply" instance="Vendor\StockFilter\Observer\ApplyStockFilter" />
</event>
// Observer: Vendor/StockFilter/Observer/ApplyStockFilter.php
namespace Vendor\StockFilter\Observer;
use Magento\Framework\Event\ObserverInterface;
use Magento\Framework\Event\Observer;
class ApplyStockFilter implements ObserverInterface
{
protected $request;
public function __construct(\Magento\Framework\App\RequestInterface $request)
{
$this->request = $request;
}
public function execute(Observer $observer)
{
$collection = $observer->getEvent()->getCollection();
$stockParam = $this->request->getParam('stock_status');
if ($stockParam == '1') {
// Join cataloginventory_stock_status table and filter by stock_status = 1
$connection = $collection->getConnection();
$select = $collection->getSelect();
$stockTable = $collection->getTable('cataloginventory_stock_status');
// be careful with table aliases to avoid duplicate joins
$select->joinLeft(
['stock_status' => $stockTable],
'e.entity_id = stock_status.product_id',
[]
)->where('stock_status.stock_status = ?', 1);
}
}
}
Notes:
- This works for stores without MSI (Multi-Source Inventory) or where you rely on
cataloginventory_stock_status. Si vous use MSI, the join/table set is different (see the MSI section below). - We’re changing the SQL layer early so the layer navigation pagination and counts stay consistent.
3) Add the front-end toggle
A simple checkbox on the category toolbar can add the query param and reload the listing. Ideally, use AJAX, but start simple:
<!-- in catalog/product/list.phtml or a block template you inject -->
<form id="stock-filter-form" action="" method="get">
<label>
<input type="checkbox" name="stock_status" value="1" <?php if ($block->getRequest()->getParam('stock_status')=='1') echo 'checked' ;?>>
In stock only
</label>
<button type="submit">Apply</button>
</form>
For better UX, add JavaScript to rewrite and preserve existing query paramètres so applying the stock filtre doesn’t remove category, attributes, or tri params.
4) Maintain filtre state and SEO concerns
Assurez-vous filtreed pages are not indexed in a way that creates huge spider traps. Use canonical tags or robots directives if you produce many paramètre combinations. For "In stock only" it's usually safe to allow indexation if it meaningfully changes utilisateur experience, but exercise caution on large catalogs. Consider:
- Use rel="canonical" on paramètreized pages pointing to the category base (if filtreed pages add little SEO valeur).
- Or add the filtre valeur into the canonical if the filtreed result is a persistent, useful landing page (e.g., "clearance" + "in stock").
Handling MSI (Multi-Source Inventory) in Magento 2.3+
MSI changes how inventaire is stored. Instead of a single cataloginventory_stock_status, you may need to check the inventory_stock_* views or use Magento Inventory APIs. A robust approche is to use the StockRegistry or recherche criteria against the Inventory source and join the stock index table used for vitrine queries (like inventory_stock_1 view).
Example (simplified):
// For MSI shops you can use the stock index table alias such as inventory_stock_1
$stockIndex = $collection->getTable('inventory_stock_1');
$select->joinLeft(
['stock_idx' => $stockIndex],
'e.entity_id = stock_idx.product_id',
[]
)->where('stock_idx.is_salable = ?', 1);
To be safe, detect the presence of MSI and the correct index table at runtime rather than hard-coding names.
Advanced filtreing techniques: combining stock status, categories and attributs personnalisés
The real magic happens when filtres act together. Voici patterns that convert well:
- Default “in stock” during promotions: Temporarily set the page de catégorie to only show in-stock items so utilisateurs don’t bookmark out-of-stock offers.
- Priority stacking: When utilisateurs select mulconseille filtres, give precedence to stock status + shipping availability first, then attribute filtres. This prevents showing a product that matches attributes but is unavailable.
- Attribute weighting: Use analytics to see which attributes lead to purchases and highlight them (position them higher in the UI) when stock for those SKUs is high.
- Bundled filtres: Create combined pre-defined filtres like “Under $100 — In stock — Fast ship” to help shoppers land on high-converting sets quickly.
Code exemple: programmatically apply combined filtres
// Compose filters in an observer or block before collection load
$collection->addAttributeToFilter('color', ['in' => ['red','blue']]);
$collection->addAttributeToFilter('price', ['lteq' => 100]);
// stock join as earlier
$select = $collection->getSelect();
$select->joinLeft(
['stock_status' => $collection->getTable('cataloginventory_stock_status')],
'e.entity_id = stock_status.product_id',
[]
)->where('stock_status.stock_status = ?', 1);
Keep conditions indexed-friendly (avoid non-SARGable constructs) and reuse Magento attribut produit indexes to maintain performance.
Case study: Force Product Stock Status to create smart “In stock only” filtres
Extensions that let you force a product's stock status (for exemple to mark certain SKUs as always in stock for marketing or bundling reasons) are a practical tool in your toolkit. Voici comment to use such a capability responsibly:
- Identify SKUs that devrait être artificially set to “in stock” (e.g., drop-shipped items you can source quickly or virtual products bundled with services).
- Use the extension settings to mark those SKUs as "forced in stock" au lieu de changing the real inventaire quantity — this prevents inventaire tracking problèmes while enabling vitrine availability.
- Expose these flagged SKUs in a separate filtre or a combined filtre: e.g., "In stock or Force-available" so clients can understand the difference if necessary.
- On the page produit, surface the fulfillment note: “Usually ships in 2 days (forced in stock)” to keep expectations clear.
Important caveat: forcing products as in stock must match the operational reality — using it on a large scale without proper supply processes will create client service problems.
Performance considerations
Filters touch collections and SQL. Badly implemented filtres slow down page de catégories. Keep an eye on:
- Query complexity: avoid joining many large tables on every request.
- Indexes: make sure the stock index table is used and you don’t force full table scans.
- Cache: use full-page cache and Varnish; cache results for popular filtre combinations (e.g., category + in-stock + prix bucket) and serve cached HTML whenever possible.
- AJAX approche: for mobile and interactive experiences, fetch filtreed blocks via AJAX and let the FPC cache the unfiltreed shell.
UX conseils that actually increase conversion
- Show counts next to filtre options (e.g., In stock (112)). That immediate feedback sets expectations.
- Offer an “In stock only” quick toggle in the toolbar and keep it sticky across categories.
- When combining filtres produces zero results, offer “Notify me” or show close matches au lieu de a dead end.
- Label forced-in-stock SKUs clearly on product cards so shoppers understand any special fulfillment conditions.
Measuring the impact: comment prove filtres move revenue
Measurements are crucial. Voici concrete étapes and event ideas you can implement quickly to quantify the effect of optimized filtres on conversions.
1) Track filtre application events
Use Google Tag Manager (GTM) and the dataLayer to push an event whenever a client applies a filtre. Example dataLayer push:
dataLayer.push({
'event': 'magefine_filter_applied',
'filterName': 'stock_status',
'filterValue': 'in_stock'
});
Create GA4 custom events or Universal Analytics events to capture: filtreName, filtreValue, categoryId, and the number of products returned. In GA4, define custom dimensions for filtreName/filtreValue so you can segment funnels by utilisateurs who used the stock filtre.
2) Measure downstream KPIs
- Rate of Add-to-Cart after filtre application: count add-to-cart events within the same session and pageview after a filtre event.
- Conversion rate differences: compare sessions with filtre applied vs. sessions without.
- Average commande valeur for filtre utilisateurs: segment revenue by the filtre custom dimension.
- Cart abandonment after applying the filtre: do utilisateurs who apply stock filtres stick around?
3) A/B test filtres
Use an A/B test tool (e.g., Google Optimize, VWO) or server-side experimentation to compare default views (all products visible) vs. stock-limited defaults (in-stock-only). Run the test for several thousand sessions or until statistical significance. Track revenue-per-utilisateur and add-to-cart rates as primary metrics.
4) Build a simple SQL rapport
Si vous have a data entrepôt or can query Magento DB & analytics data, create a rapport that joins sessions where the filtre param exists with commandes to compute conversion:
-- pseudo SQL
SELECT
f.filter_value,
COUNT(DISTINCT s.session_id) AS sessions,
SUM(o.grand_total) AS revenue,
SUM(CASE WHEN o.entity_id IS NOT NULL THEN 1 ELSE 0 END) as orders
FROM
analytics_sessions s
LEFT JOIN analytics_events e ON e.session_id = s.session_id AND e.event_name = 'magefine_filter_applied'
LEFT JOIN sales_order o ON o.session_id = s.session_id
GROUP BY f.filter_value;
Start small: even simple GA custom rapports can show you if “In stock only” improves conversion.
SEO and indexation bonnes pratiques for filtreed pages
Filters can create huge paramètre spaces. For SEO and crawl budget:
- Disallow benign but infinite combos in robots.txt or use paramètre handling in Google Search Console.
- Decide which combinations are worth indexation. Par exemple, category + brand + in-stock might be useful; random attribute permutations usually are not.
- Use rel=canonical wisely: either canonicalize paramètre pages to the base category or to a canonical that reflects the most relevant view.
- Consider server-side rendering for critical filtreed landing pages for SEO, and use structured data when appropriate.
Operational conseils for merchandising with filtres
- Run weekly rapports of best-selling filtres and stock levels. If high-converting filtres drive sales, prioritize stocking those SKUs.
- Communicate with merchandising: highlight which attribute-filtre combos produce high AOV and push campaigns around those.
- Use forced-in-stock sparingly and only when supply chain fulfills reliably — ticket spikes from broken promises destroy trust.
Common pitfalls and comment avoid them
- Too many filtres: overwhelms utilisateurs. Focus on conversion-driving attributes.
- Poor performance: always test filtres under realistic load and use DB explain plans to identify slow queries.
- Broken counts: if counts shown next to filtres are expensive to calculate, they peut être stale. Consider precomputing counts during low-traffic windows for large catalogs.
- User confusion about forced availability: be transparent about which SKUs are forced-in-stock and what that means.
Putting it all together: an optimization checklist
- Audit current filtres: list attributes, counts, and their conversion performance.
- Make stock status filtre visible and usable: add toggle + counts.
- Implement back-office filtre safely (use joins on stock index for performance, detect MSI).
- Track filtre usage with GTM/dataLayer and tie to revenue.
- Run A/B tests for default behaviors (in-stock-first vs. all products).
- Optimize caching and precompute heavy counts where possible.
- Document forced-in-stock policies and use them only when supported by operations.
Sample checklist for a release
Avant you push a filtre change to production:
- Unit test the product collection modifications.
- Smoke test on a staging mirror with realistic inventaire and MSI config.
- Check SQL explain on category + stock query; ensure indexes are used.
- Verify FPC/varnish behavior and that the filtre toggle does not unintentionally bust caches unnecessarily.
- Deploy GTM dataLayer changes and verify events in GA real-time.
Final thoughts — make filtres part of your conversion stratégie
Filters are not a “nice-to-have” UI flourish; they’re a conversion lever. Quand vous treat stock status as a strategic filtre and combine it sensibly with categories and high-impact attributes, you make it far easier for clients to find and buy what’s actually available. Use data to decide which filtres matter, instrument them for analytics, and don’t be afraid to experiment with defaults like "In stock only" during promotions. Si vous have an extension like Force Product Stock Status available, use it to help present accurate availability while maintaining operational sanity.
Quick reference: code snippets and resources
Voici the clé snippets from above that you can copy into your module as a starting point:
// Observer join example (core idea)
$select = $collection->getSelect();
$stockTable = $collection->getTable('cataloginventory_stock_status');
$select->joinLeft(['stock_status' => $stockTable], 'e.entity_id = stock_status.product_id', [])
->where('stock_status.stock_status = ?', 1);
// Front-end quick form
<form id="stock-filter-form" action="" method="get">
<label>
<input type="checkbox" name="stock_status" value="1">In stock only
</label>
<button type="submit">Apply</button>
</form>
// dataLayer push
dataLayer.push({
'event': 'magefine_filter_applied',
'filterName': 'stock_status',
'filterValue': 'in_stock'
});
Si vous want help
If you’d like, I can:
- Draft a ready-to-install module with MSI support detection and a toggle for in-stock filtreing.
- Create a GTM container snippet to capture filtre events and wire them into GA4.
- Sketch an A/B experiment plan and a SQL rapport for measuring impact.
Tell me which one you want first and I’ll prepare the next étapes with code and déploiement notes.
— a colleague who’s done too many filtre PRs