Performance Optimization: Lazy-Load Slideout for Large Category Hierarchies
When you have a parent category with:
- Large number of products (500-1000+)
- Deep category hierarchy (multiple levels of subcategories)
- Dynamic Recount enabled
Product filter could generate hundreds of SQL queries on every page load, even if the user never uses the filter. This causes:
- Slow page loading (10+ seconds)
- 504 Gateway Timeout errors
- High server load
- Poor user experience
Why This Happens
With Dynamic Recount enabled, WOOF must:
- Recursively process all child categories
- Execute SQL queries for each term to count products
- Calculate counts considering current category context
Example: A “Sunglasses” category with subcategories (Men → Women → Shapes → Brands) generates massive query load.
Traditional Solutions (Not Enough)
❌ Hiding slideout with CSS/display rules – Filter still processes on server
❌ Disabling Dynamic Recount – Loses important functionality
❌ Removing filter options – Users can’t filter properly
❌ Database indexes – Minor improvement, doesn’t solve root cause
The Optimal Solution: Lazy-Load Slideout
Key Concept: Load the filter ONLY when user actually opens the slideout.
✅ Page loads instantly (no filter processing)
✅ Filter works perfectly when needed
✅ No wasted server resources
✅ Perfect for bots and casual browsers
✅ Keeps all filter functionality intact
Implementation
Add next code to your theme’s functions.php:
/**
* WOOF Lazy-Load Slideout Filter
* Loads filter only when user clicks to open slideout
* Solves performance issues with deep category hierarchies
*/
add_action('wp_footer', function () {
// Only on product category pages (optional - remove condition to show everywhere)
if (!is_product_category()) {
//return;
}
?>
<!-- Slideout Trigger Button -->
<div id="woof-slideout-trigger" style="position: fixed; right: 0; top: 50%; transform: translateY(-50%); z-index: 9999; cursor: pointer; background: #333; color: #fff; padding: 15px 10px; border-radius: 5px 0 0 5px; font-weight: bold; writing-mode: vertical-rl; text-orientation: mixed;">
FILTERS
</div>
<!-- Slideout Panel -->
<div id="woof-slideout-panel" style="position: fixed; right: -350px; top: 0; width: 350px; height: 100%; background: #fff; box-shadow: -2px 0 10px rgba(0,0,0,0.3); z-index: 9998; transition: right 0.3s ease; overflow-y: auto; padding: 20px;">
<!-- Close Button -->
<div style="text-align: right; margin-bottom: 15px;">
<span id="woof-slideout-close" style="cursor: pointer; font-size: 24px; font-weight: bold;">✖</span>
</div>
<!-- WOOF Filter with autohide - loads only on first click -->
<?php echo do_shortcode('[woof autohide=0 start_filtering_btn=1]'); ?>
</div>
<!-- Background Overlay -->
<div id="woof-slideout-overlay" style="position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.5); z-index: 9997; display: none;"></div>
<script>
jQuery(document).ready(function ($) {
var $trigger = $('#woof-slideout-trigger');
var $panel = $('#woof-slideout-panel');
var $overlay = $('#woof-slideout-overlay');
var $close = $('#woof-slideout-close');
var filterLoaded = false;
// Open slideout
$trigger.on('click', function () {
$panel.css('right', '0');
$overlay.fadeIn(300);
// Auto-trigger WOOF "Start Filtering" button on first open
if (!filterLoaded) {
setTimeout(function () {
var $woofBtn = $('.woof_start_filtering_btn');
if ($woofBtn.length) {
$woofBtn.trigger('click');
// Hide the button after triggering
$woofBtn.hide();
filterLoaded = true;
}
}, 500);
}
});
// Close slideout
function closeSlideout() {
$panel.css('right', '-350px');
$overlay.fadeOut(300);
}
$close.on('click', closeSlideout);
$overlay.on('click', closeSlideout);
});
</script>
<?php
}, 999);
Configuration Steps
- Disable your current slideout in WOOF settings if it enabled
- Add the code above to
functions.phpof your active theme - Keep these WOOF settings enabled:
- Cache dynamic recount: Yes
- Cache terms: Yes
- Hide empty terms: Yes
- Dynamic Recount: Yes
- Optional customization:
- Adjust slideout width: change
width: 350pxandright: -350px - Change button position: modify
top: 50% - Customize colors: update
backgroundandcolorvalues - Make it work site-wide: remove the
if (!is_product_category())condition
- Adjust slideout width: change
How It Works
- Page loads: Only the trigger button renders (no filter processing)
- User clicks button: Slideout opens, overlay appears
- First open only: JavaScript automatically clicks the hidden “Start Filtering” button
- Filter loads: WOOF processes all queries and displays filter options
- Subsequent opens: Filter is already loaded, opens instantly
Real-World Results
Before:
- Page load: 10-15 seconds (or 504 timeout)
- 500+ SQL queries per page view
- High bounce rate
After:
- Page load: < 2 seconds
- Filter loads in ~3 seconds (only when requested)
- ~50% reduction in server load (many users never open filter)
Compatibility
✅ Works with all WOOF versions
✅ Compatible with page caching (WP Rocket, LiteSpeed, etc.)
✅ Mobile-friendly
✅ Works with any WordPress theme
Advanced Customization
Match your theme styling:
/* Add to your theme's CSS */
#woof-slideout-trigger {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
font-family: 'Your Theme Font', sans-serif;
letter-spacing: 2px;
}
#woof-slideout-panel {
background: #f8f9fa;
font-family: 'Your Theme Font', sans-serif;
}
#woof-slideout-trigger:hover {
transform: translateY(-50%) scale(1.05);
}
Left-side slideout:
Change these values:
right: -350px → left: -350px right: 0 → left: 0 right: -350px → left: -350px
When to Use This Solution
Use lazy-load slideout when:
- Category has deep hierarchy (3+ levels)
- 500+ products in category
- Dynamic Recount is required
- Page load time > 5 seconds
- Experiencing 504 timeouts
Alternative for Sidebar Filter
If you prefer sidebar instead of slideout, use:
echo do_shortcode('[woof autohide=1 start_filtering_btn=1]');
This creates a “Start Filtering” button in your sidebar that loads the filter on click.
This solution provides the best balance between performance and functionality, ensuring fast page loads while maintaining full filtering capabilities for users who need them.
Troubles? Ask for Support!
