Business Platforms

Membership Site Access Rules: Protecting Content Without Friction

How to set up levels, teasers and drip schedules on a membership site, and how to close the leaks most owners miss: feeds, the REST API, file links, video and cached pages.

Membership Site Access Rules: Protecting Content Without Friction

Most membership sites protect the page and forget everything around it. The lesson is hidden behind a login while the same text sits in the RSS feed, the PDF opens for anyone who has the link, and a cached copy of a members-only page is served to a visitor who never paid. Good membership site content protection is a short list of rules applied in every place the content can come out.

The other half of the job is staying out of the way of the people who did pay. This is how we set up access rules so that members rarely meet a wall, search engines can still find you, and the common leaks are closed.

Keep levels few and attach rules to groups of content

Access rules hold up when they are attached to a category, a tag, a post type or a parent page. A rule such as "everything in the Masterclass category needs the Pro level" keeps working when an editor publishes next month's lesson. Rules set post by post do not, and the first forgotten checkbox publishes paid content to everyone.

Start with two or three levels, each with a plain answer to "what do I get here that the level below does not have". If levels stack, so that Pro includes everything in Basic, test that with one account per level.

The common WordPress membership plugins, MemberPress, Paid Memberships Pro, Restrict Content Pro and WooCommerce Memberships among them, can all restrict groups of content such as a category or a post type, out of the box or with an add-on. Two things differ between them and are worth checking in the documentation:

  • What happens when two rules conflict. In WooCommerce Memberships, for example, the more specific rule wins, so a rule on a single post overrides the rule on its category.
  • What happens to content with no rule. In most plugins it is public, which is why paid content belongs in a protected category or post type from the start.

Decide what a non-member sees

There are three workable answers, and they have different effects on search traffic.

ApproachWhat a visitor getsWhat search engines indexFits
Hide completelyA login screen or a "not found" pageNothingClient portals, internal resources
TeaserAn opening section and an offer to joinThe teaser onlyCourses, communities, most content businesses
Full text for crawlers, wall for readersA sample, then the wallThe whole articlePublishers who depend on search

For a teaser, write the excerpt by hand. An automatic cut after 55 words stops mid-thought and says nothing about what is behind the wall. Under it, show what the level includes and a login link for existing members. That link should bring them back to the page they wanted, which in WordPress is wp_login_url( get_permalink() ). Landing on the home page after login is the friction we remove most often.

The third approach needs care. If Googlebot receives the full text and readers receive a wall, Google asks for paywalled content structured data so it can tell a paywall from cloaking. Wrap the protected part in an element with a class and declare it in the page's JSON-LD:

{
  "@context": "https://schema.org",
  "@type": "Article",
  "headline": "How to price a retainer",
  "isAccessibleForFree": false,
  "hasPart": {
    "@type": "WebPageElement",
    "isAccessibleForFree": false,
    "cssSelector": ".member-content"
  }
}

If everyone, crawlers included, receives the same teaser, you do not need this markup. One rule covers all three approaches: text that is in the HTML and hidden with CSS or a JavaScript overlay is public.

Drip content on a schedule members can predict

Drip runs on one of two clocks: days since the member joined (self-paced courses) or fixed calendar dates (cohorts, a monthly issue). Pick one per product and settle the edge cases before launch:

  • When someone cancels and rejoins, does the clock restart or resume?
  • When a Basic member upgrades, does the Pro schedule count from the upgrade or from the original join date?
  • At what hour does "day 7" begin? Drip follows the site time zone under Settings > General, which may not be the member's.

Show locked items with their date ("Available on March 3") and do not hide them. A hidden lesson turns into a support email asking where it went.

Access is worked out when the page is requested, so it does not depend on scheduled tasks. The "your next lesson is ready" emails do. WP-Cron only runs when someone visits, so on a quiet site add a server cron job that calls wp cron event run --due-now every few minutes.

Test membership site content protection from the outside

Open a private browser window, stay logged out, and look for the text of a protected post in each of these places:

  • The RSS feed at /feed/ and the category feeds. Under Settings > Reading, set "For each post in a feed, include" to Excerpt.
  • The REST API. Posts and custom post types are listed under /wp-json/wp/v2/. Look at the content field, not only the title.
  • Search results and archive pages, where excerpts are generated from the protected text when no manual excerpt exists.
  • Social previews. SEO plugins build the description tag from the content unless you write one.

Two commands cover the feed and the API from a terminal:

curl -s https://example.com/feed/
curl -s "https://example.com/wp-json/wp/v2/posts?per_page=3&_fields=link,content"

Repeat the check after every membership plugin update and whenever you add a custom post type.

Protect the files and the video, too

A PDF in wp-content/uploads is served by the web server directly. WordPress never sees the request, so the membership plugin cannot refuse it, and the link works for anyone it is forwarded to.

Keep member files outside the public folder and deliver them through a script that checks access, then hands the transfer back to the web server. On nginx that is an internal location, which refuses direct requests:

location /protected-files/ {
    internal;
    alias /var/www/private/;
}

The download handler in your plugin then does the check and replies with a header that nginx turns into the file:

if ( ! is_user_logged_in() ) {
    auth_redirect();
}
// Swap this capability for your membership plugin's level check.
if ( ! current_user_can( 'download_member_files' ) ) {
    wp_die( 'This file is for members.', 403 );
}
header( 'Content-Type: application/pdf' );
header( 'X-Accel-Redirect: /protected-files/handbook.pdf' );
exit;

Apache has an equivalent in the X-Sendfile module. If files live in object storage, keep the bucket private and generate a short-lived signed link after the access check.

Video has the same weakness plus a bandwidth bill. Use a video host that can restrict playback to your domain or sign its playback links, and embed the player on a protected page. That will not stop screen recording, but it does stop a raw link being passed around a forum.

Keep the page cache away from member content

A page cache stores the HTML built for one visitor and serves it to the next. Two failures follow on membership sites. The rare one is a member's page being stored and shown to a stranger. The frequent one is the reverse: someone pays, returns to the lesson, receives the cached teaser and concludes that the payment failed.

  • Never cache pages for logged-in users. Caching plugins usually default to this. Host-level caches and CDN rules that cache HTML are configured elsewhere and need the same exception, keyed on the wordpress_logged_in_ cookie.
  • Exclude login, registration, account, checkout and thank-you pages by address.
  • Test the real path: buy with a test account, open a protected page straight away, then log out and load it again in a private window.

Uncached pages cost server time, so a busy member area needs a persistent object cache. Which layer is safe for what is covered in our explanation of WordPress caching, and a slow member area is ordinary performance optimization work.

Handle account sharing without punishing members

Some sharing always happens, so measure it before acting. WordPress keeps a list of session tokens for each user, and the WP_Session_Tokens class can count and end them. A small plugin can cap an account at two or three sessions and sign out the oldest, with a message that says why.

Avoid locking accounts to an IP address. Mobile networks, offices and VPNs change addresses all day, and the people you lock out will be honest members. Where a whole team shares one login, the better answer is commercial: sell a group plan with seats.

When the plugin's rules are enough

If your access model is "these categories for this level", with a standard drip and a handful of downloads, a carefully configured membership plugin will do the job and custom code would be money wasted. Bring in a developer when access depends on something outside the plugin (course progress, a CRM field, seats bought by a company), when files and video need signed delivery, when the host adds cache layers you cannot see from the dashboard, or when a mobile app has to honor the same rules. That is the work behind the membership and subscription sites we build, most often as a WordPress membership site with a small custom plugin holding the rules the off-the-shelf product cannot express.

Frequently asked questions

Will hiding content from non-members hurt search rankings?

Search engines can only rank what they can read, so fully hidden pages bring no traffic. A teaser with a well-written opening still gets indexed, and a public landing page for each course or topic gives search engines something complete to rank.

Can I stop members from copying my content?

No. Anyone who can read a page can copy it. Protection is about stopping access without an account and casual link sharing. For high-value PDFs, stamping the buyer's name or email on each page discourages redistribution.

Do I need a separate tool to protect downloads?

Check your membership plugin first, since several include protected downloads or sell them as an add-on. What matters is how it works: the file must pass through an access check, not sit at a public uploads address that is merely hard to guess.

Add WorldWin Coder to your preferred sources

Add worldwincoder.com as a preferred source on Google, or open this article in your AI assistant to use it as a source.

Swati Priyadrshni
· Founder & CEO at WorldWin Coder

I'm Swati Priyadarshani, Founder & CEO of LMS Advisor and Co-Founder of WorldWin Coder Pvt. Ltd. (est. 2019). Over the last 10+ years, I've helped enterprises build learning platforms that actually get used - not just deployed.

Keep reading

Have something to build, fix or move?

Tell us where you are. A developer reads every inquiry, and you get next steps and a free quote within one business day.