Paywall & Access
How content gating works end-to-end — access levels, the magazine access ladder, entitlement resolution, content access rules, metered preview, and where every access setting is configured.
What Is the Paywall & Access System
The paywall is the part of the platform that decides, every time someone opens an article or magazine issue on the Reader Portal, whether they may read the full content or whether they hit a gate (a sign-in prompt or a subscribe prompt).
It does this by comparing two things:
- What the content requires — the article's (or issue's) access level, set by editors in the Admin Console.
- What the reader is entitled to — the entitlements that come from the reader's subscription plan (or the absence of one, for anonymous and free readers).
When the reader's entitlements satisfy what the content requires, the article renders in full. When they don't, the reader sees a paywall gate with a message and a call-to-action button (Sign in / Subscribe / Upgrade).
This single guide covers both halves of the system:
- The Paywall & Access settings page in the Admin Console (master on/off switch, preview length, gate messages, content-protection, session limits, and Content Access Rules), and
- The content-driven access model — per-article access levels, the four-tier magazine access ladder, and how entitlements are resolved at render time.
Go to the settings page: Admin Console → Platform & Settings → Reader Portal → Paywall & Access.
Who Uses This System
| Role | What They Do |
|---|---|
| Site Administrator | Enables/disables the paywall; sets preview length, messages, protection, session limits; manages Content Access Rules; defines plan entitlements. |
| Editorial Director / Editor | Sets each article's Access Level in the Article Editor; sets a magazine issue's default access and per-article TOC overrides. |
| QA Team | Verifies gates appear correctly for anonymous, free, and subscribed readers across articles and issues. |
How It Works (Behind the Scenes)
The access decision is resolved at render time on the Reader Portal — nothing is "baked in" when an article is published. That means changing a plan's entitlements or a content rule takes effect for the next page load, without re-publishing content.
The data path:
- Authoring (Admin Console). An editor sets an article's Access Level (
free/restricted_free/premium_limited/subscriber_only) in the Article Editor. For magazine content, an admin sets the issue default access level and optional per-article TOC overrides in the Issue Editor. Admins define plan entitlements in Subscription Plans and optional Content Access Rules on the Paywall & Access page. - Storage (Postgres / Prisma). Article access level is stored as the
AccessLevelenum on theArticlerow (access_level). Issue defaults live on theIssuerow; TOC overrides live onissue_articles.access_level_override. Plan entitlements live in the plan'sfeaturesJSON plus dedicated columns. Content rules live incontent_access_rules. Article rows are mirrored to Strapi for content delivery, but the access level is owned by Postgres. - Reader resolution (Reader Portal). When a reader requests an article or issue, the portal builds the reader's
ResolvedEntitlements(from their active subscription, orDEFAULT_READER_ENTITLEMENTSfor anonymous/free), resolves the effective access level of the content, and calls a pure decision function (decideArticleAccess/decideIssueAccessinreader-portal/src/lib/magazineAccess.ts). - Outcome. The decision is one of:
allow,redirect_to_login,redirect_to_subscribe,redirect_to_issue, ornot_found. The page renders the article, shows the metered preview with a paywall overlay, or redirects. - Crawler verification. Search-engine crawlers are allowed to see full content for indexing — but only after the request's IP is verified against published crawler ranges (
reader-portal/src/lib/crawlerVerification.ts), which blocks User-Agent spoofing used to bypass the paywall.
Access Levels & Entitlement Resolution
This section explains the concepts the whole system is built on: the access levels, how a reader's entitlements are represented, and the order in which everything is resolved.
The access levels
Articles use a single four-value enum, AccessLevel, stored on the article (and reused for magazine issues and TOC overrides):
Access Level (AccessLevel) | Who can read | Entitlement required |
|---|---|---|
free | Everyone, including anonymous readers | None |
restricted_free | Anyone who signs in (free account) for web articles; for magazines, holders of the restricted-magazine bit | accessRestrictedMagazines (magazine path) / sign-in (web metered path) |
premium_limited | Readers within their monthly premium quota / with the premium-limited magazine bit | accessPremiumLimitedMagazines + premium quota |
subscriber_only | Active paid subscribers with digital-issue access | accessDigitalIssues (and hasAccess) |
Note on naming. The Article Editor and the
AccessLevelenum use these four canonical values. The older Content Access Rules UI and some labels still surface friendly aliases (e.g. "Registered", "Subscriber", "Institutional"); these map onto the same gating behaviour. The four enum values above are authoritative for new content.
Reader entitlements
Every reader is resolved to a ResolvedEntitlements object (reader-portal/src/lib/entitlements.ts). Anonymous and unsubscribed readers get DEFAULT_READER_ENTITLEMENTS (hasAccess: false, every access bit false, metered limits 0). Key fields the paywall reads:
| Field | Type | Meaning |
|---|---|---|
hasAccess | boolean | Reader has an active access source (paid / gift / institutional / complimentary / bulk). The master gate — false for anonymous & free. |
accessDigitalIssues | boolean | Full magazine / digital-issue access (drives subscriber_only). |
accessRestrictedMagazines | boolean | Grants the restricted_free magazine tier. |
accessPremiumLimitedMagazines | boolean | Grants the premium_limited magazine tier. |
accessPremiumArticles | boolean | Grants premium web articles (quota-governed). |
premiumArticlesPerMonth | number | Premium-limited monthly quota (-1 = unlimited, 0 = blocked). |
monthlyArticleLimit / articlesReadThisMonth | number / number | Metered web-article quota (null = unlimited, 0 = blocked). |
monthlySubscriberOnlyLimit / subscriberOnlyReadThisMonth | number / number | Independent subscriber-only quota. |
planSortOrder | number | Drives the "Upgrade to [next plan]" CTA (-1 = no plan). |
The platform (Hyphen) is the source of truth for entitlements — they are derived from the reader's subscription, never from the billing provider directly.
Entitlement resolution order
For a plain web article the portal compares the article's accessLevel against the reader's entitlements (boolean bit + relevant quota). For a magazine article the effective access level is resolved through a cascade first, then graded against the four-tier ladder.
The effective access level cascade (resolvePerArticleAccessLevel / resolveEffectiveArticleAccessLevel, mirrored admin-side):
effectiveAccessLevel = IssueArticle.accessLevelOverride (TOC row override, if set — always wins)
?? Issue.accessLevel (the issue default)
?? Article.accessLevel (the article's own level)The resolved level is then graded against the four-tier ladder (decideIssueAccess / decideArticleAccess):
| Effective level | Bit required | Anonymous viewer | Signed-in, missing the bit |
|---|---|---|---|
free | none | allow (incl. anonymous) | allow |
restricted_free | accessRestrictedMagazines | redirect to /login | redirect to /subscribe |
premium_limited | accessPremiumLimitedMagazines | redirect to /login | redirect to /subscribe |
subscriber_only | accessDigitalIssues (+ hasAccess) | redirect to /login | redirect to /subscribe |
Key resolution rules
- Override always wins. A per-article TOC
accessLevelOverrideis authoritative — it beats the article's own level and Content Access Rules, even when more permissive (afreeoverride makes that one article open to everyone, bypassing the magazine gate). - Free is never penalised. A
freearticle/issue is readable by everyone including paid subscribers — the anti-downgrade rule. Marking an articlefreeoverrides magazine tier inheritance. - Parent-issue cascade. A child article in a gated issue inherits the gate before per-article rules run — "children can be more restrictive but never more permissive than the parent."
- Per-issue entitlement is additive. A reader explicitly granted a specific issue (
hasIssueEntitlement) reads it even after their broad subscription lapses (within the grant window). - Subscriber check is strict.
subscriber_onlyrequireshasAccess && accessDigitalIssues, so a stale CANCELED subscription doesn't leak access via the plain bit.
Metered preview, preview tokens & coupons
- Metered preview. Gated web articles render a preview (first N words / characters / paragraphs) with a paywall overlay rather than a hard redirect. Anonymous readers have metered limits of
0(blocked after the preview). The premium-limited and subscriber-only quotas are independent counters. When the quota window resets depends on the plan: for a paid plan the window is anchored to the subscription'scurrentPeriodStart, so the counter resets on each renewal (a reader who renews mid-month gets a fresh allotment that day, not on the 1st); a free plan uses the calendar-month anchor (the 1st of each UTC month), because the free subscription is a single perpetual period (currentPeriodEnd = 2099-12-31) that never renews; institutional readers anchor to the institution'sstartDate(falling back to the calendar month for legacy rows with no start date). - Preview tokens. Editors can preview unpublished/gated content via a signed HMAC preview token (
reader-portal/src/lib/preview/articlePreviewToken.ts,issuePreviewToken.ts), scoped to one slug, valid for 4 hours. A valid token bypasses the gate — used for editorial review and for sharing drafts. - Coupons. Coupons influence access indirectly, by changing what subscription a reader buys (discount / split-payment at checkout). A coupon does not itself flip an article's gate; once it results in an active subscription, the resulting entitlements drive access. See the Marketing and Subscriptions guides.
Legacy back-compat
Older articles may still carry a magazineAccess enum (exclusive / free_to_magazine) from the previous three-option model. It is honored at read time (exclusive → subscriber_only, free_to_magazine → free/registered) and retired as articles are re-saved — no migration required. A plan with accessDigitalIssues: true but the two newer magazine bits unset is treated at read time as also having accessRestrictedMagazines and accessPremiumLimitedMagazines (a read-time shim, no data mutated).
The visible_in_listings magazine tier. Magazine articles are normally hidden from public home/section/tag/search/related listings (they live behind the issue). Setting an article's magazine access to visible_in_listings lets that one article appear in public listings while still belonging to the issue — but only once its parent issue is in a portal-visible status (published or archived). Crucially, a visible_in_listings article does not run the legacy magazine gate: it gates on its own accessLevel exactly like a Web Exclusive article (free → open to all; gated → metered/redirect by entitlement). Use it to surface a standout magazine piece on the home page without exposing the rest of the issue. See the Magazine guide for the authoring side.
The Paywall & Access Settings Page
The settings page (Platform & Settings → Reader Portal → Paywall & Access) has these sections in order:
- Paywall Settings — master on/off switch.
- Content Preview — how much content to show before gating.
- Paywall Messages — what readers see at the gate (Registration + Subscribe variants).
- Content Protection — download / print / copy restrictions.
- Session Limits — max simultaneous logins.
- Content Access Rules — override access for sections, categories, tags, or authors.
- Save Changes (at the bottom).
Section 1 — Paywall Settings

The Enable Paywall toggle is the master switch. When off, every article is readable by everyone regardless of its access level. When on, access levels and the rules below are enforced. Use the toggle (not per-article edits) to temporarily open the whole site, then remember to turn it back on.
Section 2 — Content Preview
Controls how much of a gated article a non-entitled reader sees before the gate.
- Preview Type —
Words,Characters(HTML tags excluded), orParagraphs. Changing the type resets the count to a sensible default (200 words / 500 characters / 3 paragraphs). - Preview Count — whole number;
0hides all content immediately. 150–200 words or 2–3 paragraphs is a common starting point.
Section 3 — Paywall Messages
Two blocks because different readers need different prompts:
- Registration block — shown to anonymous (not signed in) visitors. Fields: Registration Message, CTA Button Text (default
Sign in free), CTA Button URL (default/register). - Subscribe block — shown to signed-in readers without a qualifying subscription. Fields: Subscribe Message, CTA Button Text (default
Subscribe Now), CTA Button URL (default/subscribe).
Leave a message blank to use the platform default. The Subscribe gate shows an upgrade CTA ("Upgrade to [Next Plan]" linking to /subscribe?plan=...) when the reader is on a paid plan below the top tier; otherwise the generic CTA falls back to "Subscribe".
Gate copy defaults. When no admin message is set, the subscribe/metered gate uses Hyphen brand-voice defaults: the headline reads "We'll keep this page bookmarked." for both the subscriber-only and metered states; the metered body reads "Beyond this page lies more stories, languages, and literary discoveries. Subscribe now to continue reading." The registration gate headline is "Pause here for now." with the single CTA "Sign in or Create an Account", and the restricted-free state shows "Free Article Limit Reached" with "Register for Free". There is no secondary "View subscription plans" link under the gate — the primary CTA already routes to
/subscribe. Anything you type into the message/CTA fields overrides these defaults.
Section 4 — Content Protection
Three checkboxes — Disable image downloads (all content), Disable printing (all content), and Disable copy/paste & text selection (all content).
Site-wide enforcement. These deterrents are enforced by a single global controller (
ContentProtectionController, mounted in the Reader Portal root layout) that applies them to every reader page — free and premium alike — independent of the Enable Paywall master switch. Turning a checkbox on protects the whole portal; turning it off lifts it everywhere.
How each toggle behaves:
- Disable image downloads — blocks the native image drag and the right-click "Save image as…" over images (suppresses the context menu over
img/picture/canvas). - Disable printing — hides page content from the print renderer via an
@media printrule (substituting a copyright notice) plus a best-effort Ctrl/Cmd+P keyboard guard. - Disable copy/paste & text selection — blocks copy, cut, text selection, and the context menu across the page. Editable fields are exempted (search box, sign-in form, comment boxes stay fully usable), so turning this on does not break forms.
These are client-side deterrents only — a determined user with developer tools can still extract content. They raise the bar against casual copying, printing, and image saving, which is what the requirement asks for. Enable for reproduction-sensitive literary content; leave off for news where readers quote.
Section 5 — Session Limits
Max Simultaneous Logins (1–10) is the global fallback for the number of devices a reader can be signed in on at once. If the reader's active plan defines its own Max Devices (Subscription Plans → Limits & Quotas), the plan value wins. Set this global value for free/registered readers with no plan.
Section 6 — Content Access Rules
Rules override the access level for a whole group of content (section / category / tag / author) regardless of each article's own level.
- Each rule targets a content type + a content ID/slug (e.g.
fiction), and applies an access level. - When multiple rules match, the lowest priority number wins.
- Rules can be toggled off without deleting; they save immediately (Add/Update Rule), independent of the page's Save Changes button.
- A per-article TOC override still beats a Content Access Rule.
Add a rule via Add Rule (top-right of the card): Rule Name, Priority (lower wins), Content Type, Content ID/Slug (use the Strapi slug, not the title), Access Level.
Configuration Reference
Where every access setting lives, what it controls, its type, defaults, and the UI path.
Content access (set by editors)
| Setting | What it does | Type | Values / Default | Where configured (UI path) | Role |
|---|---|---|---|---|---|
| Article Access Level | Required level to read this web article | enum AccessLevel | free (default), restricted_free, premium_limited, subscriber_only — mandatory | Admin → Content → Article Editor → Access Level | Editor / Editorial Director |
| Issue default access | Default tier applied to every article in the issue's TOC | enum AccessLevel | free / restricted_free / premium_limited / subscriber_only (optional; falls back to article level) | Admin → Magazine → Issue Editor → Configuration → "Default access for articles in this issue" | Admin / Editor |
| Per-article TOC override | Overrides one article's level inside an issue; always wins | enum AccessLevel? | empty = inherit issue default; any tier overrides | Admin → Magazine → Issue Editor → TOC tab → per-row Access override | Admin / Editor |
Plan entitlements (what grants access)
| Setting | What it does | Type | Default | Where configured | Role |
|---|---|---|---|---|---|
accessDigitalIssues | Full magazine / subscriber_only access | boolean | false | Subscription Plans → [Plan] → Access & Entitlements | Admin |
accessRestrictedMagazines | Grants restricted_free magazine tier | boolean | false | Subscription Plans → Access & Entitlements | Admin |
accessPremiumLimitedMagazines | Grants premium_limited magazine tier | boolean | false | Subscription Plans → Access & Entitlements | Admin |
accessPremiumArticles + Premium-Limited Monthly Limit | Premium web articles + monthly quota | boolean + int | false / 0 | Subscription Plans → Limits & Quotas | Admin |
Subscriber-Only Monthly Limit (monthlySubscriberOnlyLimit) | Quota for subscriber-only articles | int? | null (unlimited); 0 blocks | Subscription Plans → Limits & Quotas | Admin |
| Max Devices | Per-plan simultaneous logins (overrides global) | int | from plan | Subscription Plans → Limits & Quotas | Admin |
Paywall behaviour (site-wide)
| Setting | What it does | Type | Default | Where configured | Role |
|---|---|---|---|---|---|
| Enable Paywall | Master gating on/off | boolean | on | Paywall & Access → Paywall Settings | Site Admin |
| Preview Type / Count | Length of free preview | enum / int | Words / 200 | Paywall & Access → Content Preview | Site Admin |
| Registration / Subscribe message + CTA | Gate copy and buttons | text / url | platform defaults | Paywall & Access → Paywall Messages | Site Admin / Editorial Director |
| Content Protection | Disable image download / print / copy + selection — applies site-wide to all content, independent of the Enable Paywall switch | 3× boolean | off | Paywall & Access → Content Protection | Site Admin |
| Max Simultaneous Logins | Global device fallback | int (1–10) | 1 | Paywall & Access → Session Limits | Site Admin |
| Content Access Rules | Group-level access overrides | rule list | none | Paywall & Access → Content Access Rules | Site Admin |
| Preview token | 4h HMAC bypass for editorial review | generated link | n/a | Article/Issue editor preview action | Editor |
| Coupon | Discount that drives which subscription is bought (indirect access) | coupon | none | Marketing → Coupons | Marketing Admin |
Dependencies & Impact
The paywall sits at the intersection of several modules. Changes here ripple outward:
- Editorial — editors set each article's Access Level; this is the primary input to web-article gating. A miscategorised article is either over-exposed or wrongly locked.
- Magazine — issue default access + per-article TOC overrides drive the four-tier ladder; this guide and the Magazine guide share that ladder. Flipbook delivery has its own cover-only preview gate.
- Subscriptions — plan entitlements (
accessDigitalIssues, magazine bits, quotas) are what grants access. Changing a plan's entitlements changes who gets through the gate on the next page load. - Reader Management — a reader's active subscription, gift/comp/institutional grants, and per-issue entitlements determine their
ResolvedEntitlements. - Marketing — coupons and campaigns influence access indirectly by driving subscription purchases; CTA URLs on the gate route to marketing/checkout pages.
Impact notes: Turning the master paywall off exposes all gated content immediately. Content Protection is separate — its three toggles are enforced site-wide independently of the paywall switch, so turning the paywall off does not disable copy/print/download protection (and vice versa). Setting a plan's quota to 0 blocks that tier for all its readers. Editing a Content Access Rule or plan entitlement takes effect at next render — no re-publish needed. Crawler verification means SEO indexing keeps working even with the paywall on, as long as crawler IPs verify.
FAQ
Conversion Surfaces
Comprehensive technical reference for conversion surfaces — modals, banners, slide-ins, sticky notifications, and inline prompts that drive registrations, subscriptions, and newsletter signups on the Reader Portal, with targeting rules, frequency control, and impression/conversion analytics.
Events Management
Complete guide to creating literary events, workshops, and webinars in the Admin Console, configuring the Events Listing and Event Detail pages, and handling Reader Portal RSVP/registration with capacity control.