{"id":286954,"date":"2026-03-13T21:37:49","date_gmt":"2026-03-13T21:37:49","guid":{"rendered":"https:\/\/wordpress.org\/plugins\/xyz-age-verification-free\/"},"modified":"2026-05-25T14:49:58","modified_gmt":"2026-05-25T14:49:58","slug":"xyz-age-verification-free","status":"publish","type":"plugin","link":"https:\/\/es-mx.wordpress.org\/plugins\/xyz-age-verification-free\/","author":23461250,"comment_status":"closed","ping_status":"closed","template":"","meta":{"version":"2.5.3","stable_tag":"2.5.3","tested":"7.0","requires":"5.6","requires_php":"7.4","requires_plugins":null,"header_name":"XYZ Age Verification","header_author":"XY Zinc","header_description":"Age verification gate for adult content sites. Provides the [xyzav_age_verify] shortcode","assets_banners_color":"0a0a13","last_updated":"2026-05-25 14:49:58","external_support_url":"","external_repository_url":"","donate_link":"","header_plugin_uri":"https:\/\/www.xyzinc.com\/wordpress-plugin","header_author_uri":"https:\/\/www.xyzinc.com","rating":0,"author_block_rating":0,"active_installs":0,"downloads":370,"num_ratings":0,"support_threads":0,"support_threads_resolved":0,"author_block_count":0,"sections":["description","installation","faq","changelog"],"tags":{"2.4.2":{"tag":"2.4.2","author":"xyzageverify","date":"2026-03-13 21:37:36"},"2.5.0":{"tag":"2.5.0","author":"xyzageverify","date":"2026-03-15 09:28:09"},"2.5.1":{"tag":"2.5.1","author":"xyzageverify","date":"2026-03-17 09:21:10"},"2.5.2":{"tag":"2.5.2","author":"xyzageverify","date":"2026-05-25 13:06:51"},"2.5.3":{"tag":"2.5.3","author":"xyzageverify","date":"2026-05-25 14:49:58"}},"upgrade_notice":{"2.5.2":"<p>Readme overhaul plus a fix for a 404 error when editing country-wide regions in the admin. Recommended for all users with country-level regions configured.<\/p>","2.5.1":"<p>Adds credit pack purchasing via PayPal with a 300-credit bonus on first purchase. Recommended for sites needing more than 100 verifications per month.<\/p>","2.5.0":"<p>Interstitial consent gate eliminates passive bot session creation. Visitor IP now passed to API for per-IP rate limiting. Recommended for all users, especially high-traffic sites.<\/p>","2.4.2":"<p>MU plugin cookie handling optimization and improved phpcs annotations.<\/p>","2.4.1":"<p>Security and compliance improvements for WordPress.org review. Free Plan Admin now uses WP REST API. MU plugin redirect URLs are HMAC-verified. Recommended for all users.<\/p>","2.3.0":"<p>New free plan with 100 monthly credits, built-in region management, configurable fail behavior, and detailed verification history. Recommended for all users.<\/p>","2.2.0":"<p>Security improvements including signed cookies, test mode, and setup checklist. Recommended for all users.<\/p>","2.1.0":"<p>Critical security fix \u2014 removes region parameter override vulnerability. Update immediately.<\/p>"},"ratings":[],"assets_icons":{"icon-128x128.png":{"filename":"icon-128x128.png","revision":3482278,"resolution":"128x128","location":"assets","locale":"","width":128,"height":128},"icon-256x256.png":{"filename":"icon-256x256.png","revision":3482278,"resolution":"256x256","location":"assets","locale":"","width":256,"height":256}},"assets_banners":{"banner-772x250.png":{"filename":"banner-772x250.png","revision":3482278,"resolution":"772x250","location":"assets","locale":"","width":772,"height":250}},"assets_blueprints":{},"all_blocks":[],"tagged_versions":["2.4.2","2.5.0","2.5.1","2.5.2","2.5.3"],"block_files":[],"assets_screenshots":{"screenshot-1.png":{"filename":"screenshot-1.png","revision":3482278,"resolution":"1","location":"assets","locale":"","width":765,"height":360},"screenshot-2.png":{"filename":"screenshot-2.png","revision":3482278,"resolution":"2","location":"assets","locale":"","width":921,"height":766},"screenshot-3.png":{"filename":"screenshot-3.png","revision":3482278,"resolution":"3","location":"assets","locale":"","width":1294,"height":512},"screenshot-4.png":{"filename":"screenshot-4.png","revision":3482278,"resolution":"4","location":"assets","locale":"","width":1306,"height":1183},"screenshot-5.png":{"filename":"screenshot-5.png","revision":3482278,"resolution":"5","location":"assets","locale":"","width":704,"height":357},"screenshot-6.png":{"filename":"screenshot-6.png","revision":3482278,"resolution":"6","location":"assets","locale":"","width":775,"height":1250}},"screenshots":{"1":"Settings page with setup checklist and API health check","2":"Age verification page with QR code and verification options","3":"Region management with minimum age configuration","4":"Recent verifications with detailed attempt history","5":"Plan status showing credit usage and remaining balance","6":"Test mode in action \u2014 simulating a region with ?reg= parameter"}},"plugin_section":[],"plugin_tags":[139798,70877,41695,5616,5617],"plugin_category":[],"plugin_contributors":[257723],"plugin_business_model":[],"class_list":["post-286954","plugin","type-plugin","status-publish","hentry","plugin_tags-adults-only","plugin_tags-age-gate","plugin_tags-age-restriction","plugin_tags-age-verification","plugin_tags-age-verify","plugin_contributors-xyzageverify","plugin_committers-xyzageverify"],"banners":{"banner":"https:\/\/ps.w.org\/xyz-age-verification-free\/assets\/banner-772x250.png?rev=3482278","banner_2x":false,"banner_rtl":false,"banner_2x_rtl":false},"icons":{"svg":false,"icon":"https:\/\/ps.w.org\/xyz-age-verification-free\/assets\/icon-128x128.png?rev=3482278","icon_2x":"https:\/\/ps.w.org\/xyz-age-verification-free\/assets\/icon-256x256.png?rev=3482278","generated":false},"screenshots":[{"src":"https:\/\/ps.w.org\/xyz-age-verification-free\/assets\/screenshot-1.png?rev=3482278","caption":"Settings page with setup checklist and API health check"},{"src":"https:\/\/ps.w.org\/xyz-age-verification-free\/assets\/screenshot-2.png?rev=3482278","caption":"Age verification page with QR code and verification options"},{"src":"https:\/\/ps.w.org\/xyz-age-verification-free\/assets\/screenshot-3.png?rev=3482278","caption":"Region management with minimum age configuration"},{"src":"https:\/\/ps.w.org\/xyz-age-verification-free\/assets\/screenshot-4.png?rev=3482278","caption":"Recent verifications with detailed attempt history"},{"src":"https:\/\/ps.w.org\/xyz-age-verification-free\/assets\/screenshot-5.png?rev=3482278","caption":"Plan status showing credit usage and remaining balance"},{"src":"https:\/\/ps.w.org\/xyz-age-verification-free\/assets\/screenshot-6.png?rev=3482278","caption":"Test mode in action \u2014 simulating a region with ?reg= parameter"}],"raw_content":"<!--section=description-->\n<p>Most WordPress age verification plugins are age <strong>gates<\/strong> \u2014 a popup that asks visitors to click \"Yes, I'm 18+\" or pick a birthday from a dropdown. Anyone, including a minor, can click through in under a second. That used to be the standard. It is no longer a defensible compliance measure under the UK Online Safety Act, US state age verification laws (Texas, Louisiana, Virginia, and a growing list), or EU age assurance requirements under the Digital Services Act.<\/p>\n\n<p>XYZ Age Verification is different. It confirms visitors are adults using a real-time selfie liveness check, with automatic escalation to government ID verification for borderline cases or stricter age thresholds. <strong>No biometric data is stored.<\/strong> No checkbox to lie to. No date-of-birth dropdown that a child can spin in five seconds.<\/p>\n\n<p><strong>When you need this plugin:<\/strong><\/p>\n\n<ul>\n<li>UK sites subject to the Online Safety Act and OFCOM enforcement<\/li>\n<li>US sites subject to state-level age verification laws (Texas, Louisiana, Virginia, Utah, and a growing list)<\/li>\n<li>EU sites subject to age assurance requirements under the Digital Services Act<\/li>\n<li>Adult content, cannabis, alcohol, tobacco, firearms, and gambling sites where a click-through popup is no longer sufficient<\/li>\n<li>Any site where \"the visitor clicked Yes\" is insufficient evidence that your audience is adult-only<\/li>\n<\/ul>\n\n<p><strong>Why XYZ Age Verification:<\/strong><\/p>\n\n<ul>\n<li><strong>Real verification, not self-declaration<\/strong> \u2014 Biometric liveness detection (iBeta Level 2 certified) plus optional government ID verification<\/li>\n<li><strong>Privacy by design<\/strong> \u2014 Biometric data is processed in real time and discarded immediately. Nothing is stored. No central database of faces or IDs<\/li>\n<li><strong>Smart escalation<\/strong> \u2014 Most adult visitors complete verification with a quick selfie. Only borderline cases are asked for ID, minimizing friction<\/li>\n<li><strong>Region-specific rules<\/strong> \u2014 Apply verification only where you need it, using Cloudflare's geo detection. Configure different thresholds per country or US state<\/li>\n<li><strong>Free plan included<\/strong> \u2014 100 verifications per month, no credit card required. Sign up directly from the plugin settings page<\/li>\n<li><strong>Cryptographically signed cookies<\/strong> \u2014 Visitors can't bypass the gate with browser dev tools<\/li>\n<\/ul>\n\n<p><strong>Free plan included:<\/strong><\/p>\n\n<p>This plugin includes a free plan with 100 verification credits per month \u2014 no credit card required. Register directly from the plugin settings page with just your email. Credits reset monthly. Additional credit packs are available via PayPal for sites that need more capacity; your first purchase includes 300 bonus credits and switches your site to prepaid billing (credits do not expire or reset monthly).<\/p>\n\n<p><strong>How it works:<\/strong><\/p>\n\n<ol>\n<li>Visitors from configured regions are redirected to an age verification page.<\/li>\n<li>They complete a face liveness check (Tier 1) or liveness plus government ID verification (Tier 2). Tier 1 produces a binary adult\/not-adult result \u2014 it does not estimate age.<\/li>\n<li>If the liveness check indicates the visitor may be a minor, the system automatically escalates to government ID verification. For age thresholds other than 18 (e.g., 21+ for alcohol or cannabis), Tier 2 is required because only an ID document provides a verifiable date of birth.<\/li>\n<li>Upon a successful verification, a cryptographically signed cookie is set and the visitor is granted access.<\/li>\n<li>All biometric data, selfies, and document images are discarded immediately after the verification completes \u2014 regardless of the result.<\/li>\n<\/ol>\n\n<p><strong>Requirements:<\/strong><\/p>\n\n<ul>\n<li>An XYZ Age Verification API key (register for a free plan directly from the plugin settings, or sign up at <a href=\"https:\/\/www.xyzinc.com\/wordpress-plugin\">xyzinc.com<\/a>)<\/li>\n<li>Cloudflare proxying \u2014 free plan or higher (required for geo detection headers <code>CF-IPCountry<\/code> and <code>CF-Region-Code<\/code>)<\/li>\n<li>HTTPS enabled<\/li>\n<\/ul>\n\n<p><strong>External service \u2014 XYZ Age Verification API:<\/strong><\/p>\n\n<p>This plugin connects to the XYZ Age Verification API at <code>https:\/\/age-verify.xyzinc.com<\/code>, 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 \u2014 it is the core verification engine.<\/p>\n\n<p>When a visitor triggers 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.<\/p>\n\n<ul>\n<li><a href=\"https:\/\/www.xyzinc.com\/terms\">Terms of Use<\/a><\/li>\n<li><a href=\"https:\/\/www.xyzinc.com\/privacy\">Privacy Policy<\/a><\/li>\n<li><a href=\"https:\/\/www.xyzinc.com\/wordpress-plugin\">Service information<\/a><\/li>\n<\/ul>\n\n<p><strong>Complete feature list:<\/strong><\/p>\n\n<ul>\n<li>Two-tier verification: face liveness check, or liveness plus government ID<\/li>\n<li>Region-specific rules with Cloudflare geo detection<\/li>\n<li>Configurable minimum age per region (Tier 2 automatically enforced for thresholds above 18)<\/li>\n<li>QR code for mobile phone verification<\/li>\n<li>Popup or same-device verification options<\/li>\n<li>Real-time session status polling<\/li>\n<li>Configurable bypass cookies for pre-verified users<\/li>\n<li>Configurable fail-open or fail-closed behavior for API outages and credit exhaustion<\/li>\n<li>Cryptographically signed verification cookies (HMAC-SHA256)<\/li>\n<li>Server-side API key handling (never exposed to the browser)<\/li>\n<li>Logged-in WordPress users automatically bypass the age gate<\/li>\n<li>Built-in admin: manage regions, thresholds, and view verification history<\/li>\n<li>Setup checklist and API health check on the settings page<\/li>\n<li>Admin notices for common misconfigurations<\/li>\n<li>Contextual help tabs with setup guide and troubleshooting<\/li>\n<li>Compatible with standard WordPress page caches (not compatible with WP Rocket \u2014 see FAQ)<\/li>\n<\/ul>\n\n<h3>Planned Features<\/h3>\n\n<h4>Media file protection \u2014 available now in XYZ Protect<\/h4>\n\n<p>Media files in <code>\/wp-content\/uploads\/<\/code> are served directly by your web server and do not pass through WordPress PHP execution, so a free WordPress plugin cannot restrict them. <a href=\"https:\/\/www.xyzinc.com\/protect\">XYZ Protect<\/a> is a separate licensed plugin that solves this problem using a Cloudflare Worker \u2014 every media request is authorized before the file is served. XYZ Protect can be combined with this plugin for sites that need both page gating and file-level protection.<\/p>\n\n<h4>Restricted path mode<\/h4>\n\n<p>Currently the gate applies to your entire site based on visitor region. A future release will add a <strong>restricted paths<\/strong> mode, allowing site owners to gate only specific URL paths (e.g., <code>\/mature\/<\/code>, <code>\/adult-content\/<\/code>) while leaving the rest of the site accessible. This is ideal for sites that contain a mix of general and age-restricted content \u2014 sexuality education sites, media outlets with adult sections, or e-commerce stores with age-restricted product categories.<\/p>\n\n<h4>Additional credit packs (available now)<\/h4>\n\n<p>Credit packs are available for purchase via PayPal at <a href=\"https:\/\/www.xyzinc.com\/credits\">xyzinc.com\/credits<\/a>. Purchased credits persist until used \u2014 they do not expire or reset monthly. Multiple packs can be stacked. Your first purchase includes a bonus of 300 credits and switches your site to prepaid billing, replacing the monthly free credit allocation.<\/p>\n\n<h3>Third-Party Libraries<\/h3>\n\n<p>This plugin includes the following third-party library:<\/p>\n\n<ul>\n<li><strong>QRCode.js<\/strong> \u2014 Client-side QR code generation\n\n<ul>\n<li>Source: <a href=\"https:\/\/github.com\/davidshimjs\/qrcodejs\">https:\/\/github.com\/davidshimjs\/qrcodejs<\/a><\/li>\n<li>License: MIT<\/li>\n<li>Files: <code>assets\/js\/qrcode.js<\/code> (unminified source), <code>assets\/js\/qrcode.min.js<\/code> (minified)<\/li>\n<\/ul><\/li>\n<\/ul>\n\n<p>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 for review.<\/p>\n\n<!--section=installation-->\n<ol>\n<li>Upload the <code>xyz-age-verification-free<\/code> folder to <code>\/wp-content\/plugins\/<\/code>.<\/li>\n<li>Activate the plugin through the \"Plugins\" menu in WordPress.<\/li>\n<li>Go to <strong>Settings &gt; Age Verification<\/strong>.<\/li>\n<li>If you don't have an API key, enter your email under \"Get Started with a Free Plan\" and click <strong>Start Free Plan<\/strong>. Check your email to confirm and receive your API key.<\/li>\n<li>Enter your API key in the settings.<\/li>\n<li>Click <strong>Fetch from API<\/strong> next to the Cookie Signing Key field to enable secure cookie verification.<\/li>\n<li>Create a WordPress page with the slug <code>age-gate<\/code> and add the <code>[xyzav_age_verify]<\/code> shortcode to its content.<\/li>\n<li>Copy <code>mu-plugin\/xyz-age-gate-redirect.php<\/code> from the plugin folder to <code>\/wp-content\/mu-plugins\/<\/code>. Create the <code>mu-plugins<\/code> directory if it does not exist.<\/li>\n<li>Go to <strong>Settings &gt; Free Plan<\/strong> to configure your regions, welcome content, and verification thresholds.<\/li>\n<li>If using a page cache plugin, exclude <code>\/age-gate\/<\/code> from caching. <strong>Note: WP Rocket is not compatible<\/strong> (see FAQ).<\/li>\n<li>Check the Setup Checklist on the settings page to verify all steps are complete.<\/li>\n<\/ol>\n\n<!--section=faq-->\n<dl>\n<dt id=\"how%20is%20this%20different%20from%20other%20age%20verification%20plugins%20on%20wordpress.org%3F\"><h3>How is this different from other age verification plugins on WordPress.org?<\/h3><\/dt>\n<dd><p>Most plugins listed under \"age verification\" are technically age <strong>gates<\/strong> \u2014 a popup with a \"Yes, I'm 18+\" button or a date-of-birth dropdown. A minor can pass these in seconds by clicking the right button or picking a year. They satisfy a checkbox-level compliance requirement but do not actually verify that the visitor is an adult.<\/p>\n\n<p>XYZ Age Verification performs real verification: a real-time selfie liveness check confirms a living person is present, and a trained classifier evaluates the probability that the person is a minor. Borderline cases automatically escalate to government ID verification. The result is a binary adult\/not-adult determination backed by biometrics or a verifiable identity document \u2014 not a click.<\/p>\n\n<p>If a self-declaration popup is sufficient for your compliance needs, plenty of free plugins offer that. If you need real verification because of OFCOM, US state laws, EU requirements, or your platform's own policies, this plugin is built for that.<\/p><\/dd>\n<dt id=\"where%20is%20my%20biometric%20data%20stored%3F\"><h3>Where is my biometric data stored?<\/h3><\/dt>\n<dd><p>Nowhere. Selfies, liveness frames, and government ID images are processed in real time by the verification service and discarded immediately after the session completes \u2014 regardless of the outcome. The only data retained is the verification result (pass\/fail), session metadata, a timestamp, and the visitor's IP address (for fraud detection). Date of birth from ID documents is used transiently for age calculation and then discarded. Full details are in the <a href=\"https:\/\/www.xyzinc.com\/privacy\">Privacy Policy<\/a>.<\/p>\n\n<p>This is a fundamental architectural choice. The system does not maintain a database of faces, IDs, or verified identities, so there is no honeypot to breach.<\/p><\/dd>\n<dt id=\"is%20this%20plugin%20free%3F\"><h3>Is this plugin free?<\/h3><\/dt>\n<dd><p>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 \u2014 no credit card required. One credit is consumed per face liveness attempt, three credits total per document verification. Additional credit packs are available for purchase via PayPal at <a href=\"https:\/\/www.xyzinc.com\/credits\">xyzinc.com\/credits<\/a>. Your first purchase includes 300 bonus credits and switches your site to a prepaid billing model \u2014 prepaid credits do not expire or reset monthly.<\/p><\/dd>\n<dt id=\"what%20are%20verification%20credits%3F\"><h3>What are verification credits?<\/h3><\/dt>\n<dd><p>Credits represent verification attempts. Each face liveness check (Tier 1) costs 1 credit. Each document verification (Tier 2) costs 3 credits total. Your free plan includes 100 credits per month, resetting on the first of each month. Unused credits do not roll over.<\/p><\/dd>\n<dt id=\"how%20does%20the%20system%20decide%20when%20to%20ask%20for%20id%3F\"><h3>How does the system decide when to ask for ID?<\/h3><\/dt>\n<dd><p>For age thresholds of 18, most visitors complete verification with a quick selfie. The liveness check includes a minor-probability assessment, and any result that crosses a conservative threshold automatically escalates to government ID verification. This means most adult visitors never see the ID step, while visitors whose appearance is ambiguous are asked for verifiable proof.<\/p>\n\n<p>For age thresholds above 18 (e.g., 21+ for alcohol, cannabis, or certain firearms content), ID verification is always required because a selfie alone cannot establish a specific age \u2014 only a date of birth from an ID document can. The plugin enforces this automatically for any region configured with a minimum age above 18.<\/p><\/dd>\n<dt id=\"does%20tier%201%20estimate%20the%20visitor%27s%20age%3F\"><h3>Does Tier 1 estimate the visitor's age?<\/h3><\/dt>\n<dd><p>No. Tier 1 produces a binary adult\/not-adult determination, not an age estimate. The underlying classifier evaluates the probability that the subject is a minor; this probability drives the pass, fail, or escalate decision. The system never claims to know a visitor's age from a selfie. Specific age thresholds (21+, 25+, etc.) require Tier 2 because only an ID document supplies a verifiable date of birth.<\/p><\/dd>\n<dt id=\"what%20happens%20when%20my%20credits%20run%20out%3F\"><h3>What happens when my credits run out?<\/h3><\/dt>\n<dd><p>This depends on your <strong>API Failure Behavior<\/strong> 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 already in progress are allowed to complete. You can purchase credit packs at any time from <a href=\"https:\/\/www.xyzinc.com\/credits\">xyzinc.com\/credits<\/a> \u2014 your first purchase includes 300 bonus credits.<\/p>\n\n<p>European site operators with regulatory compliance obligations typically need \"fail closed.\"<\/p><\/dd>\n<dt id=\"why%20does%20this%20plugin%20require%20cloudflare%3F\"><h3>Why does this plugin require Cloudflare?<\/h3><\/dt>\n<dd><p>The plugin uses Cloudflare's <code>CF-IPCountry<\/code> and <code>CF-Region-Code<\/code> headers to determine visitor location for region-specific verification rules. These headers are added automatically when your site is proxied through Cloudflare. A free Cloudflare plan provides these headers.<\/p><\/dd>\n<dt id=\"what%20happens%20if%20the%20api%20is%20unreachable%3F\"><h3>What happens if the API is unreachable?<\/h3><\/dt>\n<dd><p>The behavior is controlled by the <strong>API Failure Behavior<\/strong> 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. Sites with compliance obligations should generally use \"fail closed.\"<\/p><\/dd>\n<dt id=\"what%20is%20the%20must-use%20plugin%20for%3F\"><h3>What is the must-use plugin for?<\/h3><\/dt>\n<dd><p>The MU plugin (<code>xyz-age-gate-redirect.php<\/code>) 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 gate to work reliably and to prevent unverified visitors from briefly seeing protected content.<\/p><\/dd>\n<dt id=\"is%20this%20plugin%20compatible%20with%20wp%20rocket%3F\"><h3>Is this plugin compatible with WP Rocket?<\/h3><\/dt>\n<dd><p><strong>No.<\/strong> WP Rocket's page cache serves static HTML files via its <code>advanced-cache.php<\/code> drop-in, which executes before must-use plugins load. This means WP Rocket can serve cached pages to unverified visitors, bypassing the 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 \u2014 just exclude <code>\/age-gate\/<\/code> from caching. Confirmed compatible: WP Super Cache (Simple mode only), Jetpack Boost, and W3 Total Cache.<\/p><\/dd>\n<dt id=\"can%20visitors%20bypass%20the%20gate%20with%20browser%20dev%20tools%3F\"><h3>Can visitors bypass the gate with browser dev tools?<\/h3><\/dt>\n<dd><p>The verification cookie is cryptographically signed using HMAC-SHA256. Setting a fake cookie value will not pass signature verification. The verification logic runs at the must-use plugin level before any plugin-level code that could be tampered with via WordPress filters or hooks.<\/p><\/dd>\n<dt id=\"will%20the%20gate%20block%20me%20from%20my%20own%20wordpress%20admin%3F\"><h3>Will the gate block me from my own WordPress admin?<\/h3><\/dt>\n<dd><p>No. The <code>\/wp-admin\/<\/code> area and the login page are always exempted. All logged-in WordPress users are automatically bypassed at the redirect level, so administrators, editors, and other authenticated users will not encounter the gate while browsing the site.<\/p><\/dd>\n<dt id=\"how%20does%20this%20work%20with%20membership%20or%20subscriber%20sites%3F\"><h3>How does this work with membership or subscriber sites?<\/h3><\/dt>\n<dd><p>The gate 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, <strong>all logged-in WordPress users bypass the gate<\/strong>, not just administrators.<\/p>\n\n<p>For most sites this is not an issue \u2014 anonymous visitors are verified before they can register or log in, so members have already passed verification. However, if your site requires re-verification for content that logged-in members can also access (e.g., tiered content where some sections require re-verification), this plugin alone is not a fit for that use case. Plan your registration flow with this behavior in mind.<\/p>\n\n<p>If you need tighter integration with membership levels \u2014 for example, requiring different verification tiers for different membership levels, or protecting media files based on membership \u2014 <a href=\"https:\/\/www.xyzinc.com\/protect\">XYZ Protect<\/a> integrates directly with MemberPress and Paid Memberships Pro to provide membership-aware authorization. It is a separate licensed plugin available at xyzinc.com.<\/p><\/dd>\n<dt id=\"what%20is%20the%20cookie%20signing%20key%3F\"><h3>What is the Cookie Signing Key?<\/h3><\/dt>\n<dd><p>The Cookie Signing Key is an HMAC-SHA256 secret used to cryptographically sign verification cookies. This prevents visitors from forging a verification cookie. The key is generated per-site by the XYZ API. Click \"Fetch from API\" on the settings page to set it up automatically.<\/p><\/dd>\n<dt id=\"how%20do%20i%20know%20if%20the%20plugin%20is%20configured%20correctly%3F\"><h3>How do I know if the plugin is configured correctly?<\/h3><\/dt>\n<dd><p>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.<\/p><\/dd>\n<dt id=\"how%20do%20i%20test%20the%20age%20gate%20without%20being%20in%20a%20configured%20region%3F\"><h3>How do I test the age gate without being in a configured region?<\/h3><\/dt>\n<dd><p>Enable <strong>Test Mode<\/strong> in Settings &gt; Age Verification. Once enabled, anyone can add a <code>?reg=<\/code> query string parameter to any page URL to simulate a visitor from that region. For example, <code>?reg=US-TX<\/code> simulates a visitor from Texas, USA, and <code>?reg=DE<\/code> simulates a visitor from Germany. Test mode bypasses both the verification cookie and the logged-in user exemption, so you experience the full verification 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 you are finished \u2014 a persistent admin notice will remind you.<\/p><\/dd>\n<dt id=\"does%20this%20plugin%20protect%20files%20in%20wp-content%2Fuploads%3F\"><h3>Does this plugin protect files in wp-content\/uploads?<\/h3><\/dt>\n<dd><p>No. The gate applies to WordPress pages and posts \u2014 it does not restrict direct access to media files served from <code>\/wp-content\/uploads\/<\/code>. 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 free WordPress plugin can provide.<\/p>\n\n<p>For full media file protection alongside age verification \u2014 covering images, videos, PDFs, and audio in <code>\/wp-content\/uploads\/<\/code> \u2014 see <a href=\"https:\/\/www.xyzinc.com\/protect\">XYZ Protect<\/a> at xyzinc.com. XYZ Protect adds a Cloudflare Worker layer that authorizes every media request before serving the file.<\/p><\/dd>\n<dt id=\"what%20is%20the%20minimum%20age%20setting%3F\"><h3>What is the minimum age setting?<\/h3><\/dt>\n<dd><p>Each region can have its own minimum age threshold (default is 18). For regions with a minimum age above 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.<\/p><\/dd>\n\n<\/dl>\n\n<!--section=changelog-->\n<h4>2.5.3<\/h4>\n\n<ul>\n<li>MU plugin is now auto-installed on plugin activation and self-heals on every page load if missing or out of date. Fixes a class of silent failures where a stale MU file left behind from a much earlier plugin version (using the old <code>xyz_av_*<\/code> option namespace) would partially match region rules \u2014 state-specific rules added later would redirect correctly, but country-wide rules would silently fail.<\/li>\n<li>New admin notice distinguishes MU plugin \"not installed\" from \"out of date\" from \"wp-content\/mu-plugins\/ not writable\", and only fires when the on-init auto-repair could not fix the situation.<\/li>\n<\/ul>\n\n<h4>2.5.2<\/h4>\n\n<ul>\n<li>Documentation: readme overhaul focused on positioning and discoverability \u2014 clarified the distinction between age gates and real age verification, expanded FAQ with terminology and compliance context, added \"When you need this plugin\" section.<\/li>\n<li>Fix: editing or deleting a country-wide region (no state code) from the admin no longer returns a 404. The plugin now sends the API's documented <code>-<\/code> placeholder in the URL path when state code is empty.<\/li>\n<li>Tested with WordPress 7.0.<\/li>\n<\/ul>\n\n<h4>2.5.1<\/h4>\n\n<ul>\n<li>Credit pack purchasing via PayPal \u2014 purchase additional credits directly from xyzinc.com\/credits<\/li>\n<li>First credit pack purchase includes 300 bonus credits and switches the site to prepaid billing (replaces monthly free credit allocation)<\/li>\n<li>Plan status panel now displays Prepaid plan with credit balance and purchase link<\/li>\n<li>Free plan users see bonus credit incentive on the settings page<\/li>\n<\/ul>\n\n<h4>2.5.0<\/h4>\n\n<ul>\n<li>Interstitial consent gate before session creation \u2014 no API call on page load, eliminating passive bot session consumption<\/li>\n<li>Biometric consent checkbox serves as explicit user consent capture (supports BIPA\/CIPA compliance requirements)<\/li>\n<li>HMAC-signed timing gate rejects automated interactions faster than 1 second after page render<\/li>\n<li>Visitor IP address now passed to the API for per-IP rate limiting (CF-Connecting-IP with REMOTE_ADDR fallback)<\/li>\n<li>Verification UI dynamically rendered after consent via AJAX \u2014 same QR code, popup, and polling functionality<\/li>\n<li>Added FAQ about wp-content\/uploads limitation<\/li>\n<li>Added planned features: media file protection and additional credit packs<\/li>\n<\/ul>\n\n<h4>2.4.2<\/h4>\n\n<ul>\n<li>MU plugin: replaced cookie array iteration with direct computed cookie name lookup<\/li>\n<li>MU plugin: enhanced phpcs:ignore annotations with detailed technical justifications<\/li>\n<\/ul>\n\n<h4>2.4.1<\/h4>\n\n<ul>\n<li>Plugin display name simplified to \"XYZ Age Verification\" (removed redundant \"Free\")<\/li>\n<li>Migrated Free Plan Admin data operations from AJAX to WP REST API (regions, content, thresholds, verifications)<\/li>\n<li>Added HMAC verification to MU plugin redirect URLs for enhanced input validation<\/li>\n<li>Documented QRCode.js third-party library source and license in readme<\/li>\n<li>Added xyzageverify to plugin contributors<\/li>\n<\/ul>\n\n<h4>2.4.0<\/h4>\n\n<ul>\n<li>Aligned text domain with WordPress.org assigned slug (xyz-age-verification-free)<\/li>\n<li>Renamed all plugin identifiers to use xyzav_ prefix for WordPress.org compliance<\/li>\n<li>Replaced inline scripts with properly enqueued JavaScript<\/li>\n<li>Removed WordPress.org directory asset files from plugin ZIP<\/li>\n<li>Added Domain Path header and languages directory<\/li>\n<\/ul>\n\n<h4>2.3.0<\/h4>\n\n<ul>\n<li>Free plan registration directly from the plugin settings (100 credits\/month, no credit card)<\/li>\n<li>Built-in admin page for managing regions, welcome content, and thresholds<\/li>\n<li>Detailed verification history with expandable attempt details<\/li>\n<li>Minimum age setting per region with automatic Tier 2 enforcement for thresholds above 18<\/li>\n<li>Configurable fail-open\/fail-closed behavior for API outages and credit exhaustion<\/li>\n<li>Credit usage tracking with monthly reset<\/li>\n<li>Site URL binding for free plan API keys<\/li>\n<li>Test mode now works for all visitors (incognito window testing support)<\/li>\n<li>Verification cookie HttpOnly flag disabled in test mode for easier testing<\/li>\n<li>Plugin renamed to XYZ Age Verification<\/li>\n<\/ul>\n\n<h4>2.2.0<\/h4>\n\n<ul>\n<li>Test mode: simulate any region with ?reg=US-TX query string<\/li>\n<li>Cryptographically signed verification cookies with per-site HMAC-SHA256 keys<\/li>\n<li>Logged-in WordPress users automatically bypass the age gate redirect<\/li>\n<li>Setup checklist with status indicators on the settings page<\/li>\n<li>API connection health check on the settings page<\/li>\n<li>Admin notices for missing API key, MU plugin, age-gate page, and signing key<\/li>\n<li>Contextual help tabs with overview, setup guide, settings reference, and troubleshooting<\/li>\n<li>Restructured plugin with properly enqueued CSS and JS assets<\/li>\n<li>Replaced external QR code service with bundled local generation (privacy improvement)<\/li>\n<li>Added configurable bypass cookies for pre-verified users<\/li>\n<li>Added internationalization (i18n) support for all user-facing strings<\/li>\n<li>Added uninstall cleanup for all plugin options<\/li>\n<li>Added activation hook with PHP and WordPress version checks<\/li>\n<li>Added version constant for asset cache busting<\/li>\n<li>Fixed file extension for proper WordPress plugin loading<\/li>\n<li>Removed hardcoded client-specific default values<\/li>\n<li>Added Host header security documentation in MU plugin<\/li>\n<\/ul>\n\n<h4>2.1.0<\/h4>\n\n<ul>\n<li>Removed region query parameter override vulnerability (critical security fix)<\/li>\n<li>Added nonce and capability checks to admin tool actions<\/li>\n<li>Added sanitization callbacks to all registered settings<\/li>\n<li>Added session ID format validation in AJAX poll handler<\/li>\n<li>Removed client-specific hardcoded bypass cookies from MU plugin<\/li>\n<\/ul>\n\n<h4>2.0.0<\/h4>\n\n<ul>\n<li>Initial public release<\/li>\n<li>Two-tier verification (face liveness + government ID)<\/li>\n<li>Region-specific rules via Cloudflare geo headers<\/li>\n<li>QR code and popup verification options<\/li>\n<li>Server-side API key handling<\/li>\n<li>MU plugin architecture for early redirect (not compatible with WP Rocket page cache)<\/li>\n<\/ul>","raw_excerpt":"Real age verification for WordPress \u2014 biometric liveness and government ID, not a checkbox. Built for OFCOM, US state, and EU compliance.","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/es-mx.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin\/286954","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/es-mx.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin"}],"about":[{"href":"https:\/\/es-mx.wordpress.org\/plugins\/wp-json\/wp\/v2\/types\/plugin"}],"replies":[{"embeddable":true,"href":"https:\/\/es-mx.wordpress.org\/plugins\/wp-json\/wp\/v2\/comments?post=286954"}],"author":[{"embeddable":true,"href":"https:\/\/es-mx.wordpress.org\/plugins\/wp-json\/wporg\/v1\/users\/xyzageverify"}],"wp:attachment":[{"href":"https:\/\/es-mx.wordpress.org\/plugins\/wp-json\/wp\/v2\/media?parent=286954"}],"wp:term":[{"taxonomy":"plugin_section","embeddable":true,"href":"https:\/\/es-mx.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_section?post=286954"},{"taxonomy":"plugin_tags","embeddable":true,"href":"https:\/\/es-mx.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_tags?post=286954"},{"taxonomy":"plugin_category","embeddable":true,"href":"https:\/\/es-mx.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_category?post=286954"},{"taxonomy":"plugin_contributors","embeddable":true,"href":"https:\/\/es-mx.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_contributors?post=286954"},{"taxonomy":"plugin_business_model","embeddable":true,"href":"https:\/\/es-mx.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_business_model?post=286954"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}