PMPro Content Visibility Blocks: What's Supported
Paid Memberships Pro offers two ways to restrict content on your site. Understanding how each one works with XYZ Protect will help you choose the right setup for your pages.
Two Ways PMPro Restricts Content
Page-level restrictions — You assign a page or post to a membership-required category, or apply a PMPro content rule. The entire page is restricted. Non-members can't see any of it.
Block-level visibility — Using PMPro's Content Visibility controls in the WordPress editor, you show or hide individual blocks on a page based on membership level. This lets you mix public and members-only content on the same page.
What XYZ Protect Supports
XYZ Protect's media URL rewriting works with page-level restrictions. When a page is restricted to specific membership levels, all media URLs on that page are rewritten for authorized members. Unauthorized visitors don't see the page at all, so they never see the media URLs.
XYZ Protect does not rewrite media URLs inside block-level visibility restrictions. Media in blocks hidden by PMPro's Content Visibility controls will retain their original, unprotected URLs.
Why Block-Level Media Protection Isn't Supported
The core issue is page caching. A page with both public and members-only blocks is still one page at one URL. When your caching plugin stores that page, it captures one version of the HTML. It can't serve different versions of the same page depending on which blocks each visitor is supposed to see.
This creates an impossible choice for media URL rewriting:
- If all media URLs on the page are rewritten, public images break for non-members viewing the cached version.
- If no media URLs are rewritten, members see unprotected URLs for media inside their restricted blocks.
This isn't a limitation specific to XYZ Protect. PMPro's own block-level Content Visibility feature has the same constraint — when a page is cached, the cached HTML either includes the restricted blocks or it doesn't. PMPro can't evaluate a visitor's membership level on a page that's served from cache.
Recommended Alternatives
Use page-level restrictions instead of block visibility
This is the simplest and most reliable approach. Assign pages or posts to a PMPro membership-required category, or apply a PMPro content rule to the entire page. All media on the page is protected. Page caching works normally.
Use path-based protection for mixed-content pages
If you need public and restricted media on the same page, use XYZ Protect's path-based strategy:
- Organize restricted media into a dedicated uploads directory (e.g.,
/wp-content/uploads/protected/)
- Set XYZ Protect's protection scope to cover that directory
- Media in the protected directory is always rewritten regardless of page-level rules
Public images stored outside the protected directory remain accessible and cache-friendly. This approach works even on pages that mix public and members-only content.
Separate restricted content onto its own pages
Instead of mixing public and restricted blocks on one page, put membership-only content (including media) on dedicated restricted pages. Link to them from your public pages. This works with all caching configurations and avoids the block visibility limitations entirely.
Quick Reference
| How you restrict content | Media protected? | Works with page caching? |
|---|---|---|
| PMPro page-level rule or category | Yes — all media on page is rewritten | Yes |
| PMPro block-level Content Visibility | No — media URLs are not rewritten | Block visibility itself is cache-incompatible |
| XYZ Protect path-based (any page) | Yes — media in protected directories is always rewritten | Yes |