XYZ Age Verification

Plugin Banner

XYZ Age Verification

by xyzageverify

Download
Description

XYZ Age Verification provides real age verification for WordPress sites that need to comply with age-gating regulations. Unlike simple “click to confirm” plugins, XYZ uses biometric liveness detection and optional government ID verification to confirm that a visitor is not a minor.

How it works:

  1. Visitors from configured regions are redirected to an age gate page.
  2. They complete a face liveness check (Tier 1) or liveness + government ID verification (Tier 2).
  3. Upon verification, a secure cookie is set and the visitor is granted access.
  4. All biometric data is processed in real-time and is not stored.

Key features:

  • Two-tier verification: face liveness check or liveness + government ID
  • Region-specific rules with Cloudflare geo detection
  • Configurable minimum age per region (Tier 2 auto-enforced for non-18 thresholds)
  • QR code for mobile phone verification
  • Popup or same-device verification options
  • Real-time session status polling
  • Configurable bypass cookies for pre-verified users
  • Configurable fail-open or fail-closed behavior for API outages and credit exhaustion
  • Cryptographically signed verification cookies (HMAC-SHA256)
  • Server-side API key handling (never exposed to the browser)
  • Logged-in WordPress users automatically bypass the age gate
  • Built-in free plan admin: manage regions, thresholds, and view verification history
  • Setup checklist and API health check on the settings page
  • Admin notices for common misconfigurations
  • Contextual help tabs with setup guide and troubleshooting
  • Compatible with standard WordPress page caches (not compatible with WP Rocket — see FAQ)
  • Privacy-focused: no biometric data stored

Free plan included:

This plugin includes a free plan with 100 verification credits per month — no credit card required. Register directly from the plugin settings page with just your email address. Credits reset monthly and do not roll over. Additional credit packs are available for sites that need more capacity.

Requirements:

  • An XYZ Age Verification API key (register for a free plan directly from the plugin settings, or sign up at xyzinc.com)
  • Cloudflare proxying — free plan or higher (required for geo detection headers CF-IPCountry and CF-Region-Code)
  • HTTPS enabled

External service — XYZ Age Verification API:

This plugin connects to the XYZ Age Verification API at https://age-verify.xyzinc.com, operated by XY Zinc (a brand of Chaos Unlimited LLC), to perform biometric liveness detection and government ID document verification. The plugin cannot function without this service — it is the core verification engine.

When a visitor triggers age verification, the plugin sends the visitor’s country and state codes (derived from Cloudflare headers) to the API to create a verification session. The visitor then interacts directly with the verification UI hosted by the service. No biometric data passes through your WordPress server. The plugin polls the API for session status and receives only a pass/fail result.

Planned Features

The following enhancements are planned for future releases:

Restricted path mode (Pro)

Currently the age gate applies to your entire site based on visitor region. A future release of the Pro plugin will add a restricted paths mode, allowing site owners to age-gate only specific URL paths (e.g., /mature/, /adult-content/) while leaving the rest of the site accessible without verification. This is ideal for sites that contain a mix of general and age-restricted content — such as sexuality education sites, media outlets with adult sections, or e-commerce stores with age-restricted product categories.

Additional credit packs

Credit packs will be available for purchase via PayPal for sites that need more capacity. Purchased credits will be added to a prepaid balance that persists until used — they will not expire or reset monthly. Multiple packs can be stacked.

Media file protection

We are investigating methods to extend age gate protection to files served from /wp-content/uploads/. Because media files are served directly by the web server and do not pass through WordPress PHP execution, this requires server-level solutions (e.g., Nginx/Apache rewrite rules, signed URLs, or a PHP-based file proxy). A future release will provide guidance and/or built-in support for common hosting configurations.

Third-Party Libraries

This plugin includes the following third-party library:

No build tools are required. The library is included as-is from the upstream repository with a minor CSS modification (image display style changed from “block” to “inline-block” for QR code placement). The unminified source is included in the plugin for review.

  1. Upload the xyz-age-verification-free folder to /wp-content/plugins/.
  2. Activate the plugin through the “Plugins” menu in WordPress.
  3. Go to Settings > Age Verification.
  4. If you don’t have an API key, enter your email under “Get Started with a Free Plan” and click Start Free Plan. Check your email to confirm and receive your API key.
  5. Enter your API key in the settings.
  6. Click Fetch from API next to the Cookie Signing Key field to enable secure cookie verification.
  7. Create a WordPress page with the slug age-gate and add the [xyzav_age_verify] shortcode to its content.
  8. Copy mu-plugin/xyz-age-gate-redirect.php from the plugin folder to /wp-content/mu-plugins/. Create the mu-plugins directory if it does not exist.
  9. Go to Settings > Free Plan to configure your regions, welcome content, and verification thresholds.
  10. If using a page cache plugin, exclude /age-gate/ from caching. Note: WP Rocket is not compatible (see FAQ).
  11. Check the Setup Checklist on the settings page to verify all steps are complete.
  1. Settings page with setup checklist and API health check

    Settings page with setup checklist and API health check

  2. Age gate page with QR code and verification options

    Age gate page with QR code and verification options

  3. Free Plan Admin — region management with minimum age

    Free Plan Admin — region management with minimum age

  4. Free Plan Admin — recent verifications with detailed attempt history

    Free Plan Admin — recent verifications with detailed attempt history

  5. Plan status showing credit usage and remaining balance

    Plan status showing credit usage and remaining balance

  6. Test mode in action — simulating a region with ?reg= parameter

    Test mode in action — simulating a region with ?reg= parameter

Is this plugin free?

Yes. The plugin itself is completely free and open source. It connects to the XYZ Age Verification API, which includes a free plan with 100 verification credits per month. One credit is consumed per face liveness attempt, and two credits per document verification attempt. Additional monthly credit packs are available for sites that need more capacity.

What are verification credits?

Credits represent verification attempts. Each face liveness check (Tier 1) costs 1 credit. Each document verification attempt (Tier 2) costs 2 credits. Your free plan includes 100 credits per month, which resets on the first of each month. Unused credits do not roll over.

What happens when my credits run out?

This depends on your API Failure Behavior setting. In “fail open” mode (the default), visitors are allowed through unverified. In “fail closed” mode, visitors are redirected to an error page until credits reset or you purchase additional credits. Verifications that are already in progress when the limit is reached are allowed to complete.

Why does this plugin require Cloudflare?

The plugin uses Cloudflare’s CF-IPCountry and CF-Region-Code headers to determine visitor location for region-specific age verification rules. These headers are added automatically when your site is proxied through Cloudflare. A free Cloudflare plan provides these headers.

What happens if the API is unreachable?

The behavior is controlled by the API Failure Behavior setting on the Age Verification settings page. “Fail open” (the default) allows visitors through unverified to prevent your site from going offline. “Fail closed” redirects visitors to an error page. European site operators may need “fail closed” for regulatory compliance.

What is the must-use plugin for?

The MU plugin (xyz-age-gate-redirect.php) runs early in the WordPress loading process, before most plugins. It checks Cloudflare geo headers and the verification cookie on every request, redirecting unverified visitors to the age gate page. This early execution is essential for the age gate to work reliably.

Is this plugin compatible with WP Rocket?

No. WP Rocket’s page cache serves static HTML files via its advanced-cache.php drop-in, which executes before must-use plugins load. This means WP Rocket can serve cached pages to unverified visitors, bypassing the age gate entirely. WP Rocket does not currently offer a way to conditionally cache based on cookie presence. Other page cache plugins that respect the standard WordPress loading order are compatible — just exclude /age-gate/ from caching.

Can visitors bypass the age gate with browser dev tools?

The verification cookie is cryptographically signed using HMAC-SHA256. Setting a fake cookie value will not pass signature verification.

What data is collected during verification?

Only the verification result (pass/fail), session metadata, a timestamp, and the visitor’s IP address (for fraud detection) are retained. Biometric data (face images, liveness frames) is processed in real-time and discarded immediately. No government ID content is stored — date of birth is used transiently for age calculation and then discarded. Full details can be found in the Privacy Policy.

Will the age gate block me from my own WordPress admin?

No. The /wp-admin/ area and the login page are always exempted from the age gate. Additionally, all logged-in WordPress users are automatically bypassed at the redirect level, so administrators, editors, and other authenticated users will not encounter the age gate while browsing the site.

How does this work with membership or subscriber sites?

The age gate redirect runs at the must-use plugin level, which executes before WordPress loads user roles. At this stage the plugin can detect that a visitor is logged in, but cannot distinguish between an administrator and a regular member. As a result, all logged-in WordPress users bypass the age gate, not just administrators.

For most sites this is not an issue — anonymous visitors are verified before they can register or log in, so members have already passed verification. However, if your site requires age verification for content that logged-in members can also access (e.g., tiered content where some sections require re-verification), this plugin is not a fit for that use case. Plan your registration flow with this behavior in mind.

What is the Cookie Signing Key?

The Cookie Signing Key is an HMAC-SHA256 secret used to cryptographically sign verification cookies. This prevents visitors from forging a verification cookie with browser dev tools. The key is generated per-site by the XYZ API. Click “Fetch from API” on the settings page to set it up automatically.

How do I know if the plugin is configured correctly?

The settings page includes a Setup Checklist that shows green checkmarks for completed steps and red Xs for missing items. There is also an API Status indicator that tests the connection to the XYZ verification API. Click the Help tab at the top-right of the settings page for a full setup guide and troubleshooting tips.

How do I test the age gate without being in an age-gated region?

Enable Test Mode in Settings > Age Verification. Once enabled, anyone can add a ?reg= query string parameter to any page URL to simulate a visitor from that region. For example, ?reg=US-TX simulates a visitor from Texas, USA, and ?reg=DE simulates a visitor from Germany. Test mode bypasses both the verification cookie and the logged-in user exemption so you experience the full age gate flow. This works in incognito/private browsing windows without a WordPress login, which is the most common way to test as an anonymous visitor. Remember to disable test mode when testing is complete — a persistent admin notice will remind you.

Does this plugin protect files in wp-content/uploads?

No. The age gate applies to WordPress pages and posts — it does not restrict direct access to media files served from /wp-content/uploads/. If a visitor knows or guesses the direct URL to an uploaded file, they can access it without verification. This is a limitation of the WordPress architecture: media files are served directly by the web server (Apache/Nginx) and do not pass through WordPress’s PHP execution. Protecting uploaded files requires server-level configuration beyond what a WordPress plugin can provide. See Planned Features for updates.

What is the minimum age setting?

Each region can have its own minimum age threshold (default is 18). For regions with a minimum age other than 18, the plugin automatically requires Tier 2 verification (government ID) because Tier 1 (face liveness) can only assess minor probability, not exact age. The ID document is needed to extract the date of birth for precise age calculation.

2.5.0

  • Interstitial consent gate before session creation — no API call on page load, eliminating passive bot session consumption
  • Biometric consent checkbox serves as explicit user consent capture (supports BIPA/CIPA compliance requirements)
  • HMAC-signed timing gate rejects automated interactions faster than 1 second after page render
  • Visitor IP address now passed to the API for per-IP rate limiting (CF-Connecting-IP with REMOTE_ADDR fallback)
  • Verification UI dynamically rendered after consent via AJAX — same QR code, popup, and polling functionality
  • Added FAQ about wp-content/uploads limitation
  • Added planned features: media file protection and additional credit packs

2.4.2

  • MU plugin: Replaced cookie array iteration with direct computed cookie name lookup
  • MU plugin: Enhanced phpcs:ignore annotations with detailed technical justifications

2.4.1

  • Plugin display name simplified to “XYZ Age Verification” (removed redundant “Free”)
  • Migrated Free Plan Admin data operations from AJAX to WP REST API (regions, content, thresholds, verifications)
  • Added HMAC verification to MU plugin redirect URLs for enhanced input validation
  • Documented QRCode.js third-party library source and license in readme
  • Added xyzageverify to plugin contributors

2.4.0

  • Aligned text domain with WordPress.org assigned slug (xyz-age-verification-free)
  • Renamed all plugin identifiers to use xyzav_ prefix for WordPress.org compliance
  • Replaced inline scripts with properly enqueued JavaScript
  • Removed WordPress.org directory asset files from plugin ZIP
  • Added Domain Path header and languages directory

2.3.0

  • Free plan registration directly from the plugin settings (100 credits/month, no credit card)
  • Built-in Free Plan Admin page for managing regions, welcome content, and thresholds
  • Detailed verification history with expandable attempt details
  • Minimum age setting per region with automatic Tier 2 enforcement for non-18 thresholds
  • Configurable fail-open/fail-closed behavior for API outages and credit exhaustion
  • Credit usage tracking with monthly reset
  • Site URL binding for free plan API keys
  • Test mode now works for all visitors (incognito window testing support)
  • Verification cookie HttpOnly flag disabled in test mode for easier testing
  • Plugin renamed to XYZ Age Verification

2.2.0

  • Test mode: simulate any region with ?reg=US-TX query string
  • Cryptographically signed verification cookies with per-site HMAC-SHA256 keys
  • Logged-in WordPress users automatically bypass the age gate redirect
  • Setup checklist with status indicators on the settings page
  • API connection health check on the settings page
  • Admin notices for missing API key, MU plugin, age-gate page, and signing key
  • Contextual help tabs with overview, setup guide, settings reference, and troubleshooting
  • Restructured plugin with properly enqueued CSS and JS assets
  • Replaced external QR code service with bundled local generation (privacy improvement)
  • Added configurable bypass cookies for pre-verified users
  • Added internationalization (i18n) support for all user-facing strings
  • Added uninstall cleanup for all plugin options
  • Added activation hook with PHP and WordPress version checks
  • Added version constant for asset cache busting
  • Fixed file extension for proper WordPress plugin loading
  • Removed hardcoded client-specific default values
  • Added Host header security documentation in MU plugin

2.1.0

  • Removed region query parameter override vulnerability (critical security fix)
  • Added nonce and capability checks to admin tool actions
  • Added sanitization callbacks to all registered settings
  • Added session ID format validation in AJAX poll handler
  • Removed client-specific hardcoded bypass cookies from MU plugin

2.0.0

  • Initial public release
  • Two-tier verification (face liveness + government ID)
  • Region-specific rules via Cloudflare geo headers
  • QR code and popup verification options
  • Server-side API key handling
  • MU plugin architecture for early redirect (not compatible with WP Rocket page cache)
Back to top