A page can look protected in an administrator session and still behave incorrectly for the people who actually visit it. When I reviewed our free Content Restrictor plugin, the interesting part was the decision order: which rule wins, which identity is tested, and what happens before WordPress gets a chance to run.
For a resource page with a simple reader rule, a small access-control plugin can be enough. In this tutorial, we will build a Member Resource Library, allow the right WordPress accounts to read it, and test what happens when someone else opens the same URL. We will use Content Restrictor, our free plugin, with the normal WordPress block editor.
This is a tutorial for version 2.10.6, checked against its source and a local WordPress 7.1.3 installation. The screenshots below are real settings screens, enlarged and annotated for readability. We also document a redirect issue found during testing, because a useful setup guide should explain the edges as well as the happy path.
What you will build
One published resource page with a reader-access rule. Public pages remain public. You will not need Elementor, a payment gateway, or an elevated user role just to let someone read it.
First, choose the access rule you actually need
“Members only” sounds specific, but it can mean several different things. A registered reader, a paying customer, and a particular client are different audiences. Start by writing down which one you mean.
| Your requirement | Use this visibility option | What it really checks |
|---|---|---|
| Any signed-in account may read the page | Members Only | Whether the visitor is logged in |
| Only accounts with a particular role may read it | Selected User Roles | Whether the account has a selected role |
| Only two named clients may read it | Selected Users | Whether the account is in your selected list |
| Only visitors who are signed out may read it | Guests Only | Whether the visitor is logged out |
| This page must stay public despite a broader rule | Everyone | An explicit public rule for this page |
The important distinction: Members Only does not check whether somebody paid you. Likewise, selecting the WooCommerce Customer role does not establish that a customer bought a particular product or still has an active subscription. Those requirements need an entitlement check connected to the relevant commerce or membership system.
For our example, we will first allow any logged-in member, then narrow access to the Subscriber role. WordPress describes roles as collections of capabilities; they are not a simple ladder of reader access. See the official WordPress roles and capabilities reference if you are deciding which account role to assign.
Download and install the free plugin
The linked ZIP is the prepared Content Restrictor 2.10.6 package. At the time this tutorial was prepared, it was not yet available in the WordPress.org plugin directory, so these instructions use a ZIP upload rather than a repository search.
Download the free ZIP from the original tutorial. Version 2.10.6, GPLv2 or later. Guests verify an email to download; signed-in readers use the direct-download flow.
The package requires WordPress 6.0 or later and PHP 7.4 or later and is distributed under GPLv2 or later. Those are package minimums, not a recommendation to run an old PHP version. Keep a backup and try the setup on staging before applying access rules to a working site.
- Open Plugins → Add New Plugin → Upload Plugin in WordPress.
- Choose the downloaded ZIP as it is; do not upload an extracted folder.
- Click Install Now, then Activate Plugin.
- Open Lumo WP → Content Restrictor in the dashboard menu.
If WordPress says the destination folder already exists, check whether Content Restrictor is already installed before replacing anything. The package in this tutorial is the free Content Restrictor release; do not assume that a differently named legacy plugin has identical settings or an automatic migration path.
For the product overview, requirements, and future release information, see Lumo Content Restrictor. You can complete this tutorial with the ZIP above.
Step 1: Leave global restrictions off
Open Lumo WP → Content Restrictor → General. Keep Enable Global Restrictions off for this walkthrough. We want to control one page first, not unexpectedly change access to other content.
Leave Exclude Administrators enabled while you configure the plugin, then click Save Changes if you changed anything. This helps preserve your working access, but it also means your administrator session is a poor test of the visitor experience.
Real lab screen, cropped and annotated: global restrictions stay off for this one-page tutorial.
The administrator preview trap
“I can still see the page” does not prove the rule failed. You may be looking at it with an administrator account that bypasses the front-end restriction. Test with a separate ordinary account and a signed-out browser window.
Step 2: Create a page and make it members-only
Go to Pages → Add New Page. Call it “Member Resource Library” and add a short introduction plus some harmless sample content. Use a fictional resource while testing; do not put confidential client information on the page to see whether the restriction works.
Publish the page using normal WordPress publishing controls. In the editor, open the Page settings sidebar and find Content Restriction Settings. Depending on your editor layout, the meta box may be lower down in the sidebar or in the meta-box area below the editor.
- Open the plugin's Visibility selector.
- Choose Members Only.
- Save or update the page.
- Copy the public page URL and open it in a signed-out window.
The plugin's Visibility field is separate from WordPress's own public, private, and password-protected publishing options. For this example, the page is published normally and Content Restrictor supplies the reader rule. Setting a page to WordPress Private instead is not a way to give ordinary Subscribers access; native private content uses WordPress permissions. The official post visibility guide explains that distinction.
If you need a refresher on arranging headings, images, and reusable sections, our Gutenberg article-publishing tutorial covers the editor workflow. No page-builder layout is required for the restriction.
Step 3: Restrict the page to a role or named users
Now suppose you want the resource library to be available to Subscribers rather than every logged-in account. In the same page's Content Restriction Settings, change Visibility to Selected User Roles, check Subscriber, and save the page.
Real Gutenberg settings, enlarged and annotated. Select Subscriber, then save the page.
An account with the Author role is not automatically allowed by a Subscriber-only rule. The code checks role membership, not which role sounds more powerful. If you want Subscribers and Customers, select both. An account matching either selected role can satisfy this rule.
For a client-specific page, choose Selected Users instead and select the intended existing accounts. Save, then test with both a selected and an unselected account. This is often a clearer fit for a small client handover page than creating a new role for every client.
Do not give a reader the Editor or Administrator role to solve a viewing problem. Editing permissions and reading permissions are separate decisions. Also, the Plugin Access Control section in the plugin's Advanced tab controls who may manage the plugin settings and meta box. It is not where you grant readers access to your resource page.
Step 4: Give denied visitors a useful destination
A restriction needs a sensible next step. A guest can be sent to your login page; a logged-in user with the wrong role may need an explanation instead of another login form.
Open Lumo WP → Content Restrictor → Redirect and review the default redirect destination. Use a public page on the same site that explains how to sign in or request access. The page editor also provides a Custom Redirect URL when one resource needs its own destination.
Keep that destination outside the restriction it is explaining. For example, if every Page has a members-only rule, make your access-information page explicitly Everyone. Otherwise, the destination can itself be denied and create a confusing redirect loop. Use the Redirect tab for the default destination; do not rely on the similarly named General-tab field in this release.
Version 2.10.6 finding: test the return URL
Our anonymous request correctly received a 302 redirect, but the generated redirect_to value was URL-encoded twice. We therefore do not recommend assuming that “return after login” works in every login flow. If the return destination is malformed, disable that option, use a public login/access page, and open the resource URL again after signing in. Verify the full journey on your own login setup before launch.
This is a version-specific observation, not a reason to quietly modify your login system. The download here remains the original prepared package, so the tutorial and the file refer to the same behavior.
Step 5: Understand which rule wins
Once one page works, you can consider Post Types rules for a larger collection. For example, a custom resource post type could have a default members-only rule, with one introductory resource left public.
Reading the front-end restriction code revealed this decision order:
Explicit rule on this individual post or page
otherwise → enabled rule for its post type
otherwise → enabled global rule
otherwise → public access
The individual option labelled Use Global Settings is therefore best understood as “inherit the applicable rule.” An enabled post-type rule can apply before the global default. Turning off global restrictions does not turn off an independently enabled post-type rule.
Likewise, Everyone on an individual page is an explicit override, not the same as inheriting the default. These details matter when a page unexpectedly stays restricted or unexpectedly becomes public.
Before using a broad rule, list your required public destinations: your home page, access-information page, contact page, and any account or checkout routes involved in your setup. Test those destinations individually. A global content setting is not a web-server access policy for every URL on the domain.
Step 6: Review archives, search results, and excerpts
Restricting a page's contents and removing its listing from discovery are different tasks. Open Lumo WP → Content Restrictor → Advanced and review Hide Restricted Posts from Archives.
Real Advanced settings screen, annotated. Review archive and excerpt behavior separately from page access.
In the reviewed source, the listing filter targets the main home, archive, search, and feed queries. That is useful, but it is not a promise that every custom Elementor grid, secondary query, API response, or third-party search service will hide the same item. Test the places where your site actually displays it.
Also review Show Excerpts for Restricted Content. If you intentionally want a teaser, write a public-safe excerpt. Do not copy confidential details into it and then assume the full-page rule will hide them. Leave debug mode off on a production site unless you are investigating a specific issue.
Step 7: Check caching and direct file access
Two things sit outside the simple “who is this WordPress user?” decision: cached responses and direct media URLs.
A shared cache may serve a response before WordPress runs. Exclude your protected pages from shared full-page caching until you have verified a safe configuration for each audience. Purge any previously public cached copy. Then repeat the guest and member tests through your real host, cache plugin, and CDN—not just while logged into the dashboard.
A protected page does not make its linked PDF private. If a document lives at a publicly accessible uploads URL, a visitor who has that URL may be able to request it directly. This plugin does not turn the uploads directory into a private document store. Sensitive downloads need their own authenticated delivery mechanism or server-level protection.
Protect the resource, not only its introduction
A members-only page can be a useful navigation and reader-access feature. For confidential files, check the file URL separately in a signed-out browser. Hiding the link is not the same as denying the download.
Step 8: Run an access test before sharing the page
Keep one administrator window for making changes and use separate browser sessions for testing. Do not switch between accounts in the same cached tab and assume you are seeing a fresh response.
| Test session | Members Only | Subscriber-only rule |
|---|---|---|
| Signed-out visitor | Denied or redirected | Denied or redirected |
| Logged-in Subscriber | Allowed | Allowed |
| Logged-in Author with no Subscriber role | Allowed | Denied or redirected |
| Administrator with bypass enabled | Not a reliable visitor test | Not a reliable visitor test |
Then check the full journey: open the URL while logged out, sign in, reopen the resource, log out, and request it again. Test your access-information destination, site search, relevant archive pages, and any directly linked file. Repeat after purging caches and again after a permitted user has visited the resource.
In our lab, twelve focused checks passed for the access-decision logic, including role matching, named users, guests-only access, post-type inheritance, and an individual Everyone override. We also saved the role rule through the real editor and confirmed that an anonymous HTTP request was redirected without the sample page content in that response.
Those results support the workflow described here. They are not a full security audit or a guarantee about every theme, REST integration, cache layer, or membership extension. The source files most relevant to this review were includes/Frontend/Restrictor.php, includes/Core/Permissions.php, and includes/Admin/MetaBox.php.
Troubleshooting the most common surprises
| What you see | What to check first |
|---|---|
| The administrator still sees the page | Exclude Administrators and the account used for testing |
| An Author cannot open a Subscriber-only page | Exact selected roles; roles are not inherited reader tiers |
| The page is restricted with global settings off | An individual or enabled post-type rule |
| A protected resource is visible in a custom grid | Whether that grid uses a secondary query outside the archive filter |
| Login succeeds but the return address is wrong | The 2.10.6 redirect_to encoding issue and your login flow |
| A guest can download the PDF | Direct media delivery is separate from page restrictions |
| A guest sometimes sees an old public copy | Shared page cache, CDN rules, and previously cached responses |
A sensible first setup
Start with one resource page, one ordinary test account, and a public access-information page. Keep global rules off, choose the narrowest reader rule that matches your real requirement, and test the URL outside your administrator session.
Once that works, expand deliberately to more resources or a post-type default. The goal is not to put the largest number of pages behind a switch. It is to make the access rule understandable: the right person can open the resource, the wrong person gets a useful next step, and a cache or direct file URL does not undermine the arrangement.
Disclosure: I work on LumoWP, which makes the plugin used here. This is an adapted version of our original tutorial, including the same tested version and known limitation.



Top comments (0)