Product Access Manager
WooCommerce role-based product access control
by Amnon Manneberg · github.com/holisticpeople/product-access-manager
Install
No release zip yet. The repository archive installs, but the folder name will carry the branch suffix and updates will not flow:
wp plugin install https://github.com/holisticpeople/product-access-manager/archive/refs/heads/main.zipVersion: 2.15.2
Status: Production Ready ✅
WordPress: 5.8+
WooCommerce: 6.0+
PHP: 8.0+
ACF-based product access control for WooCommerce with high-performance caching and complete display integration.
What It Does
Controls which products users can see based on ACF site_catalog values and WordPress user roles.
Example:
- Products with
Vimergy_catalog→ Only visible to users withaccess-vimergy-userrole - Products with
HP_catalogorDCG_catalog→ Visible to everyone (public catalogs) - Admins → See everything
Works everywhere:
- Shop pages
- Category pages
- Search results
- Product sliders
- FiboSearch
- Third-party plugins using
wc_get_products()
Quick Start
1. Requirements
- ACF (Advanced Custom Fields) plugin installed
- ACF field
site_catalogconfigured on products - WordPress user roles created (format:
access-xxx-user)
2. Installation
# Upload to plugins directory
wp-content/plugins/product-access-manager/
# Or via WP-CLI
wp plugin install product-access-manager.zip --activate
3. Configuration
Public Catalogs (always visible):
HP_catalogDCG_catalog
Restricted Catalogs (auto-detected):
- Any other
XXX_catalogvalue in ACF field
User Roles Required:
- Format:
access-{catalog-name}-user - Example:
access-vimergy-userforVimergy_catalog
How It Works
Visibility Logic
Is user an admin?
YES → Show ALL products
NO ↓
Does product have site_catalog set?
NO → Show product (default visible)
YES ↓
Is catalog public (HP/DCG)?
YES → Show product
NO ↓
Does user have matching access-{catalog}-user role?
YES → Show product
NO → Hide product
Caching System
Dual-layer cache for maximum performance:
-
Per-User Cache (shop/search/categories)
- Cache key:
pam_hidden_products_{user_id}orpam_hidden_products_guest - Duration: 30 minutes
- Stores: Products THIS user cannot see
- Cache key:
-
Shared Cache (sliders/widgets)
- Cache key:
pam_all_restricted_products - Duration: 30 minutes
- Stores: ALL restricted products (used by sliders)
- Cache key:
Performance:
- First page load: ~1 second (cache rebuild)
- Cached loads: ~0.1 seconds (cache hit)
- Database queries: 74% reduction
Auto-clears on:
- User login
- User logout
- User role change
Integration Points
WooCommerce
Main queries (shop, categories, search):
- Hook:
pre_get_posts - Method:
post__not_inexclusion - Cache: Per-user blocked products
Product Sliders
All wc_get_products() calls:
- Hook:
woocommerce_product_data_store_cpt_get_products_query - Method: Universal filter
- Cache: Shared restricted products
- Note: Sliders NEVER show restricted products (even to authorized users)
FiboSearch
Hybrid approach:
- Server-side: Visibility filters affect indexing
- Client-side: JavaScript removes restricted products from live results
- File:
pam-fibosearch-filter.js - Exception: Admins and authorized users bypass client filter
Adding New Catalogs
Zero code changes required!
Steps:
-
Add ACF choice
ACF Field: site_catalog Add choice: NewBrand_catalog -
Create WordPress role
Role slug: access-newbrand-user Role name: NewBrand Access -
Assign products
Edit product → Set site_catalog to "NewBrand_catalog" -
Assign users
Edit user → Assign role "NewBrand Access"
Done! The plugin auto-detects the new catalog.
See ADDING-NEW-CATALOGS.md for detailed instructions.
Manual Cache Clearing
Via WP-CLI
# Clear all caches
wp cache flush
wp transient delete --all
# Clear specific PAM caches
wp transient delete pam_hidden_products_guest
wp transient delete pam_all_restricted_products
# Clear specific user cache (replace 123 with user ID)
wp transient delete pam_hidden_products_123
Via Code
// Clear for specific user
pam_clear_blocked_products_cache($user_id);
// Clear for guests
pam_clear_blocked_products_cache(null);
// Clear slider cache
pam_clear_slider_transients();
Debugging
Enable Debug Mode
Edit product-access-manager.php:
define( 'PAM_DEBUG', true ); // Line 35
View Logs
# Local development
tail -f wp-content/debug.log | grep PAM
# Production server
ssh -p 12872 holisticpeoplecom@35.236.219.140
tail -f public/wp-content/debug.log | grep PAM
Debug Output
[PAM v2.8.1] Blocked products cache MISS for user 0 - rebuilding
[PAM v2.8.1] Calculated 50 blocked products for user 0
[PAM v2.8.1] Blocked products cache SAVED for user 0
[PAM v2.8.1] Restricted products cache HIT - 50 products
[PAM v2.8.1] wc_get_products(): Applied exclusion of 50 restricted products
Remember: Set PAM_DEBUG to false before production deployment!
Troubleshooting
Products not appearing for authorized user
Symptom: User has access-vimergy-user role but doesn't see Vimergy products
Solutions:
- Clear user's cache:
wp transient delete pam_hidden_products_{user_id} - User should log out and back in
- Verify role:
wp user get user@example.com --field=roles - Check product ACF: Ensure
site_catalogis set toVimergy_catalog
Slider showing restricted products
Symptom: Guest users see restricted products on homepage slider
Solutions:
- Clear shared cache:
wp transient delete pam_all_restricted_products - Clear slider cache:
wp db query "DELETE FROM wp_options WHERE option_name LIKE '%_transient_spwps_%'" - Clear Kinsta cache (if on Kinsta)
- Hard refresh browser (Ctrl+F5)
FiboSearch not filtering
Symptom: Search results show restricted products to guests
Solutions:
- Clear browser cache (JavaScript might be cached)
- Check browser console for errors
- Verify script loaded:
typeof pamFilterFiboResultsshould return"function" - Test AJAX endpoint manually (see AI-AGENT-GUIDE.md)
Site crash / Memory exhaustion
Symptom: White screen, 500 error, "Allowed memory size exhausted"
Cause: Likely recursion issue in cache building
Solution:
- Disable plugin temporarily
- Check error logs for stack trace
- Verify
$GLOBALS['pam_building_cache']flag exists (see AI-AGENT-GUIDE.md) - Report issue if flag is present
File Structure
product-access-manager/
├── product-access-manager.php # Main plugin
├── pam-fibosearch-filter.js # FiboSearch client filter
├── README.md # This file
├── QUICK-START.md # Setup guide
├── ADDING-NEW-CATALOGS.md # Catalog instructions
├── AI-AGENT-GUIDE.md # Developer reference
├── DEPLOYMENT-SETUP.md # CI/CD setup
├── GITHUB-SECRETS-TEMPLATE.md # Secrets template
└── Plans and reports/
└── v2.8.1-production-ready.md # Status report
Version History
v2.15.2 (Current)
- ✅ Declared compatibility with WooCommerce High-Performance Order Storage (HPOS)
- ✅ Added regression coverage for the WooCommerce feature declaration
v2.15.1
- ✅ Added the typed allow/deny/unknown product-access contract
- ✅ Corrected product access gate precedence
v2.8.1
- ✅ Optimized slider caching with shared cache
- ✅ Eliminated redundant static variables
- ✅ Production-ready with debug disabled
- ✅ Documentation updated
v2.8.0
- ✅ Simplified slider strategy
- ✅ Re-enabled slider native caching
- ✅ Removed user-aware slider complexity
v2.5.x
- ✅ Session-based caching (30-minute transients)
- ✅ FiboSearch client-side filtering
- ✅ Memory exhaustion fixes
v2.0.0
- ✅ Migrated from tags to ACF-based control
- ✅ Dynamic catalog detection
Performance Metrics
| Metric | Before Cache | After Cache | Improvement |
|---|---|---|---|
| Shop page load | 2.1s | 0.4s | 81% faster |
| Slider load (cached) | 1.8s | 0.1s | 94% faster |
| Database queries | 47 | 12 | 74% reduction |
Security
⚠️ Important: NOT Fail-Safe
This plugin is NOT fail-safe from a security perspective:
- Products remain set to "visible" in WooCommerce
- Plugin filters hide them dynamically
- If plugin fails or is disabled, restricted products become visible to everyone
For fail-safe security, you would need to:
- Set restricted products to "hidden" in WooCommerce
- Have the plugin REVEAL them to authorized users (opposite approach)
Current Security Features:
- ✅ Admins always see everything
- ✅ Cache isolation (no user data leakage)
- ✅ Capability checks (consistent permission validation)
- ✅ Multiple filter layers (visibility, purchase, direct access)
- ⚠️ Relies on plugin being active and working
Support & Documentation
- Setup:
QUICK-START.md - Add Catalogs:
ADDING-NEW-CATALOGS.md - Developers:
AI-AGENT-GUIDE.md - Status Report:
Plans and reports/v2.8.1-production-ready.md - Deployment:
DEPLOYMENT-SETUP.md
Credits
Author: Amnon Manneberg
License: Proprietary
Support: Internal use only
Last Updated: August 30, 2026