PBJ.TECH — WordPress Plugins

PBJ Access Control — User Guide

Version 2.2.0 · pbj.tech/wordpress-plugins

PBJ Access Control — Complete User Guide

For version 2.1.0. This is the comprehensive guide; see pbj-access-control-INSTALL-AND-USAGE.md for the quick-start version.

1. What this plugin does

Four related jobs, each independently switchable:

  1. Lock individual pages behind login — a checkbox on any Page. Logged-out visitors get your custom "Members Only" message (HTTP 403) instead of the content.
  2. Gate WooCommerce behind login — shop, cart, checkout, and account become members-only, with an optional carve-out that keeps the registration form reachable.
  3. Show your own restricted-content message — a WYSIWYG-edited page with a sign-in link, shown wherever something is gated.
  4. Approve new users before they can log in — registrations are held as "pending"; you approve or deny from a dedicated admin page or straight from the notification email, with each signup's IP address and detected location shown to help you spot bots.

Since 2.1.0 the gate is airtight: restricted page content is also blanked in the REST API and oEmbed, excluded from search results, marked noindex, and blocked responses are never stored by page caches.

2. Restricting pages

Edit any Page → sidebar meta box Access Restriction → tick Restrict this page to logged-in users only → Update.

What logged-out visitors then get: your restricted message with HTTP 403 at the page's URL; no trace of the content in site search; nothing in the REST API (.../wp-json/wp/v2/pages/... shows empty content marked "protected"); no oEmbed preview; noindex for crawlers.

What they do NOT get protection from: uploaded files. Images and PDFs linked from a restricted page are served directly by the web server and stay reachable by direct URL. Don't put secret documents in the media library expecting this plugin to guard them.

Only Pages have the checkbox by default. A developer can extend restriction to other post types with the pbj_access_control_post_types filter.

3. Gating WooCommerce

Settings → Access Control:

Typical wholesale/trade setup: both toggles on, approval required (section 5), so a new trade customer registers → you vet and approve → they log in and see the store.

4. The restricted message

Settings → Access Control → the editor at the bottom. Full WYSIWYG: headings, links, images. The default is a "Members Only" box linking to sign-in/registration (it picks the WooCommerce My Account URL automatically when Woo is active). Reset message to default restores it at any time.

Notes: <style> tags and stylesheet links are stripped on save (styling comes from the built-in card design); the message is shown for both restricted pages and gated Woo pages — write it generically enough for both.

Prefer a login redirect instead of a message page? A developer one-liner sends logged-out visitors to wp-login with a return-to-page redirect: add_filter( 'pbj_access_control_login_redirect', '__return_true' );

5. User approvals

Settings → Access Control → Require admin approval for new registrations.

The flow: someone registers → their account is created but flagged pending → they cannot log in ("Your account is pending approval") → you (and any addresses on the notification list) get an email with their username, email, registration time, IP address, and detected city/region/country → you approve or deny.

Three ways to act:

What approval/denial does: Approve clears the flag and emails the user "your account has been approved" with a login link. Deny deletes the account (confirmation prompt in the admin UI). There's no "reject but keep" state — deny is delete.

Reading the IP/location column: it's an audit aid, not a guarantee — VPN users show their exit location, and on sites not behind a proxy the value is what the client claimed. A signup with no location + free-mail address + gibberish username is your classic bot pattern.

Notification recipients: comma-separated list; empty = the site admin email. Invalid addresses are silently dropped.

Turning approval on with existing pending users: the flag is set at registration time, so only signups made while the toggle is on are held. Existing users are never affected.

6. Interaction with PBJ Geo Viewer

They stack cleanly and are designed to run together:

7. Verifying it works

In a private/incognito window (logged out):

8. Troubleshooting

A member sees the "Members Only" page while logged in. A stale cached copy from before 2.1.0 — purge your page cache once; 2.1.0 marks all blocked responses uncacheable.

Restricted content appears in Google. It was indexed before restriction. The page now serves 403 + noindex to crawlers, so it will drop out; request removal in Search Console to speed it up.

Registration form unreachable with Woo blocking on. Both toggles must be on: the plugin's "Allow access to registration page" AND WooCommerce's "Allow customers to create an account on the My account page".

No approval emails. Test wp_mail delivery generally (password-reset email is a quick check); then check the recipients field. Consider an SMTP plugin if the host's mail is unreliable.

Approve link says nothing / expired notice. Email links live ~24h. Use Users → PBJ User Approvals.

Pending user complains they can't log in. Working as intended — approve them, or turn approval off if you didn't mean to hold registrations.

Locked myself out of a restricted page while logged out. Just log in — admins see everything. The restriction never applies to logged-in users.

IP column empty or wrong. Private/unresolvable IPs, ip-api.com unreachable (2-second timeout), or a VPN. It's best-effort audit data.

9. Privacy note

Registrant IPs are stored as user meta and, when no proxy geo header is available, sent to ip-api.com (third-party, plain-HTTP) for city/region/country resolution, cached 24h. Mention signup IP collection in your privacy policy if that's relevant to your jurisdiction.

10. Quick reference

ThingValue
Settings screenSettings → Access Control
Approvals screenUsers → PBJ User Approvals
Restricted-response statusHTTP 403 (+ noindex, uncacheable)
Per-page toggle"Access Restriction" meta box on Pages
Deny =account deleted (confirm prompt)
Approval email linksexpire ~24h
File/media protectionnone — pages only
Option namepbj_access_control_options
Filterspbj_access_control_post_types, pbj_access_control_login_redirect