Skip to content

MR-5: Metered Paywall - #28

Open
av3nger wants to merge 23 commits into
mainfrom
feature/MR-5-metered-paywall
Open

MR-5: Metered Paywall#28
av3nger wants to merge 23 commits into
mainfrom
feature/MR-5-metered-paywall

Conversation

@av3nger

@av3nger av3nger commented Aug 31, 2026

Copy link
Copy Markdown
Collaborator

Summary

This PR adds a metered paywall on top of the existing Memberful paywall: a "free article allowance" that lets anonymous visitors and registered free members read a configurable number of matching posts within a rolling period before the paywall is shown.

What's included

  • New Memberful - Metering settings tab: enable toggle, rolling period, anonymous limit, registered free member limit, and an "apply to protected posts" option.
  • Visual rule builder. A post is metered when any rule group matches:
    • post type: is any of / is none of
    • category / tag: has any of / has none of
    • URL: contains / does not contain
  • Server-side engine: decision cached per request; paid members, exempt posts, non-matching posts, and ineligible requests (admin, feed, REST, non-GET, authors) are never metered.
  • Anonymous views tracked in a signed, HttpOnly cookie; registered views in user meta; anonymous views merge into the account on login.
  • Per-post "Exempt from metering" metabox.
  • Metering countdown block with a configurable {count} template, shown only while the visitor is still being sampled.

Test plan

  • Open Memberful - Metering, enable it, set a short period, an anonymous limit (e.g. 2) and a registered limit (e.g. 3), add a rule (e.g. post type is any of: Post), and save.
  • As a logged-out visitor, view matching posts past the limit:
    • confirm the first N render in full and the next shows the paywall
    • confirm re-opening an already-read post still renders (no double count)
    • confirm a non-matching post is never metered
  • Log in as a free member with prior anonymous views - confirm they carry over and the registered limit applies.
  • As a paid member, confirm matching posts are never metered.
  • Tick "Exempt this post from metering" and confirm the post stays fully readable and uncounted.
  • Insert the countdown block, use the {count} button, and confirm it shows the remaining count while sampling and disappears once the meter trips.
  • Disable metering and confirm no metering output or cache headers on protected posts.

Note

High Risk
Touches content filtering, paywall gating, cookie-backed view counting, and cache-bypass behavior—misconfiguration or aggressive edge caching can leak full articles or block legitimate readers.

Overview
Adds a metered paywall on top of the global paywall: publishers get a new Metering settings tab with rolling limits for anonymous vs free-member readers, include/except rule groups (post type, category, tag, URL), optional metering of members-only posts, and a per-post exempt from metering metabox. Runtime logic in Memberful_Metering_Access decides per singular GET request whether to ignore metering, allow a free sample (full post), or trip the meter; views are stored in a signed HttpOnly cookie (anonymous) or user meta (logged in), with no-store / DONOTCACHEPAGE on metered responses and 503 on prefetch when a new view would be counted.

Content protection now consults that decision only for the main queried post: samples bypass the paywall; a tripped meter forces the same gating as lacking access. Listing teasers gain a path to rebuild content above the paywall divider when block parsing strips the marker.

The paywall builder can show an optional {limit} counter (via memberful_paywall_free_view_limit) and swap the primary CTA to free registration when a logged-out visitor hits the meter and registered limits are > 0. A new memberful/metering-countdown block renders remaining free reads while sampling.

Admin metering-admin.js powers the interactive rule builder; the block is registered from block-editor.php and bundled via webpack.

Reviewed by Cursor Bugbot for commit 8cda277. Bugbot is set up for automated code reviews on this repo. Configure here.

@cursor

cursor Bot commented Aug 31, 2026

Copy link
Copy Markdown

Bugbot is paused — on-demand spend limit reached

Bugbot uses usage-based billing for this team and has hit its on-demand spend limit.

A team admin can raise the spend limit in the Cursor dashboard, or wait for the next billing cycle to continue.

@av3nger av3nger changed the title Feature/mr 5 metered paywall MR-5: Metered Paywall Aug 31, 2026
@av3nger av3nger mentioned this pull request Aug 31, 2026

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Want fixes drafted automatically? Bugbot Autofix can create code changes for findings. A team admin can enable Autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 8cda277. Configure here.

$result[] = strtolower( $term->name );
}

return $result;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Term rules match names too

Medium Severity

Category and tag conditions compare saved slugs against both each term's slug and its lowercased name. A rule for one term therefore also matches a different term whose name equals that slug, so the wrong posts are included or excluded.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 8cda277. Configure here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants