Skip to main content

Documentation

No results found.
Features

Age Verification Gate

WebProCMS ships with a built-in Age Verification Gate for sites that sell or discuss age-restricted products — breweries, wineries, distilleries, tobacco/vape shops, cannabis dispensaries, adult-adjacent content. It's off by default and add...

WebProCMS ships with a built-in Age Verification Gate for sites that sell or discuss age-restricted products — breweries, wineries, distilleries, tobacco/vape shops, cannabis dispensaries, adult-adjacent content. It's off by default and adds zero overhead to sites that don't use it. When enabled, a full-screen overlay blocks the site (or just selected pages) until the visitor confirms their age, remembers the choice for a configurable number of days, and redirects visitors who fail the check away from the site.


What it does

  • Full-screen gate — an opaque overlay covering the whole page, styled with the site's brand colors and following light/dark mode automatically. Optionally shows the site's branding logo on the card.
  • Two verification modes:
    • Simple confirmation — two buttons: "I am 21 or older" / "I am under 21" (the number follows your configured minimum age).
    • Date of birth — the visitor enters their birth date and the gate computes their age against the configured minimum (default 21).
  • Region-aware minimum age — optionally apply a different minimum age by visitor country (e.g. 18 in the EU, 21 in the US). Rules map comma-separated ISO country codes to an age; the shorthand EU covers the EU/EEA plus the UK and Switzerland; the first matching rule wins. Country detection uses the same CDN headers as Cookie Consent (Cloudflare CF-IPCountry, CloudFront, Vercel) — visitors without one get the default minimum age.
  • Remembers the choice — a first-party cookie (wpcms_age_ok) keeps verified visitors from seeing the gate again for a configurable duration (default 30 days). Changing the mode, minimum age, or region rules automatically re-gates everyone whose cookie predates the change.
  • Bounce URL — visitors who fail the check see a configurable deny message, then are redirected to a configurable URL (default https://www.google.com).
  • Site-wide, per-page, or per content type — gate the whole site, only specific paths (e.g. only /shop and certain blog posts), or whole content types (the type's listing page and every item page under it).
  • Customizable copy — headline, body text, button labels, and deny message are all editable. Use :age anywhere in the copy to insert the configured minimum age (with region rules active, each visitor sees their region's age).
  • Analytics goals — when the Analytics feature is on, every pass and deny is counted in the conversion goal registry (Analytics → Conversions, goal types age_pass / age_deny), so you can see how much traffic the gate turns away. Counts are anonymous, respect DNT/GPC, and exclude logged-in CMS staff.

How to turn it on

  1. Dashboard → Settings → Features → enable Age Verification Gate.
  2. Dashboard → Settings → Age Verification (appears in the sidebar once enabled) → configure mode, minimum age, scope, and copy.

Architecture: how the cache stays intact

WebProCMS uses Spatie's response cache for the public site — every page is cached once and served to every visitor. Like the Cookie Consent system, the gate is designed to never vary the cached HTML by visitor:

  • The overlay markup and its configuration payload are identical for every visitor of a given URL, baked into the cached HTML. When region rules are active the payload also carries the raw copy templates (:age unsubstituted) — still identical for everyone.
  • The gate is server-rendered visible (fail closed). A tiny inline script in <head> runs before first paint: if the visitor's remember-cookie is valid it hides the overlay (html.age-ok) — so returning visitors never see a flash of the gate, and new visitors never see a flash of the content.
  • Every per-visitor decision (cookie check, age math, deny redirect) happens client-side in ~2 KB of JS. With region rules off, there is no per-visitor server round trip at all. With region rules on, the JS fetches the visitor's effective age from /_age-gate/init — the same uncached, browser-cached (~30 min) init-endpoint pattern the cookie consent banner uses — then re-renders the gate copy with that age. Server copy always renders with the default age, so the gate stays fail-closed even if the fetch fails.
  • Pass/deny counts flow through a fire-and-forget sendBeacon to /_age-gate/hit (the same posture as the shared A/B testing beacon: always answers 204, rate-limited, DNT-respecting, staff-skipping) into the Analytics goal registry.
  • Per-page and per-content-type scoping is resolved per URL on the server, which is safe because the response cache is keyed by URL. Pages outside the scope carry zero gate bytes.

Scope: site-wide or selected pages

Site-wide (default): every public page is gated.

Selected pages only: list one path per line under Gated page paths. * works as a wildcard:

/shop
/shop/*
/blog/our-new-imperial-stout
  • /shop gates only the shop page; /shop/* gates everything under it. Use both lines to gate the section and its landing page.
  • Language-prefixed URLs (/es/shop) match their base pattern automatically.
  • Individual pages can also be toggled from the page editor: Page Settings → Require age verification (shown when the addon is enabled). The toggle edits the same path list.
  • Whole content types can be gated with checkboxes under Gate whole content types — the type's listing page, item pages, and taxonomy pages are all covered via the type's URL prefix, so new items are gated automatically with no path patterns to maintain. (A page covered by a gated content type shows as gated in the editor's Page Settings; ungate it by unchecking the type, not the per-page toggle.)
  • Other dynamic URL groups are gated with a wildcard (/blog/*) or by listing individual paths. Automatic gating driven by a content tag (e.g. "every post tagged 21+") is a possible future enhancement.

Search engines and crawlers

Gated content stays indexable. The gate is a client-side overlay, not a server block — the full page HTML (content, links, structured data) is present in the DOM underneath the overlay, and crawlers receive exactly the same HTML as everyone else. Google's crawler does not click buttons or fill in dates, so it indexes the content behind the gate normally. (Be aware the overlay may occasionally appear in rendered snapshots/screenshots of the page.)

This matches how mainstream age-gated brands handle SEO. If you need genuinely private content that crawlers and unauthorized visitors can never fetch, that's what Memberships page gating is for — the age gate is a compliance/deterrence measure, not access control.

  • Name: wpcms_age_ok; contents: a version number, a configuration fingerprint, and a timestamp. No personal data — the visitor's actual birth date is never stored or sent anywhere.
  • Duration: configurable, default 30 days.
  • It is a strictly necessary cookie. It never loads third-party code and exists solely to honor the visitor's own choice, so it is not gated behind the Cookie Consent system's analytics/marketing categories — it works even for visitors who reject all optional cookies.

When both features are enabled, the age gate takes priority: the overlay renders above the consent banner, and the banner stays hidden until the visitor passes the gate. Once passed, the consent banner appears as normal. No configuration needed — this is automatic.

Failing the check

Clicking the deny button (or entering an underage birth date) shows the configurable deny message for a moment, then redirects the browser to the bounce URL. No "failed" cookie is set — a visitor who arrives again later can retry (deliberate: age gates are deterrents, and permanently locking out someone who misclicked is worse than allowing a retry).

Configuration reference

All settings live under Dashboard → Settings → Age Verification (admin only):

Setting Default Notes
Verification mode Simple confirmation Or date of birth
Minimum age 21 1–99; used by both modes and the :age copy placeholder
Region-aware minimum age Off Ordered rules: comma-separated ISO country codes (or EU) → age; first match wins; needs a CDN country header
Remember choice (days) 30 1–730
Redirect underage visitors to https://www.google.com http/https URLs only
Apply the gate to Entire site Or selected pages: path list + whole-content-type checkboxes
Show the site logo On Uses the branding logo; hidden when none is set
Headline / body / buttons / deny message Sensible defaults :age inserts the minimum age (the visitor's regional age when rules are active)

Saving settings — and toggling the feature on the Features page — clears the public response cache so changes appear immediately. Gate copy localizes with the public site the same way the cookie banner does (per-language age_verification.{key}__{lang} settings).

What it's not

  • Not real age verification. Like every mainstream age gate, it trusts the visitor's answer. It is a compliance/deterrence measure, not identity verification — no ID checks, no third-party verification service.
  • Not legal advice. Age-restriction requirements vary by jurisdiction and industry; operators should confirm their obligations with counsel.
  • Not access control. Content remains in the page source and indexable (see above). Use Memberships gating for genuinely private content.
  • Not usable without JavaScript. For no-JS visitors the overlay is server-rendered visible and cannot be dismissed (fail closed) — the safe default for a compliance feature.