# Troubleshooting Common Issues

This guide covers the most common problems and their solutions when setting up and running the XYZ Age Verification plugin.

## Setup Issues

### Setup Checklist Shows a Red X

The settings page includes a checklist that validates your configuration. Here's what each item means and how to fix it:

**API Key: Missing**
- Go to Settings > Age Verification and enter your API key.
- If you don't have one, register for a free plan using the email form on the settings page.

**Cookie Signing Key: Missing**
- Click "Fetch from API" on the settings page. The key will be retrieved automatically.
- If this fails, check that your API key is valid and the API is reachable.

**Age-Gate Page: Not found**
- Create a WordPress page with the slug `age-gate`.
- The slug must be exactly `age-gate`, not "age_gate" or "agegate" or anything else.
- To check/change the slug: edit the page, open the settings panel, and look for "URL" or "Permalink."

**MU Plugin: Not installed**
- Copy `xyz-age-gate-redirect.php` from `wp-content/plugins/xyz-age-verification-free/mu-plugin/` to `wp-content/mu-plugins/`.
- Create the `mu-plugins` directory if it doesn't exist.
- Make sure the file is directly in `mu-plugins/`, not in a subdirectory.

**API Status: Unreachable**
- Check your server's outbound connectivity.
- Verify that your hosting provider does not block outbound HTTPS requests.
- Try again in a few minutes — the API may be briefly unavailable for maintenance.

### "Could not reach API" When Registering

This usually means the WordPress AJAX handler could not connect to the XYZ API from your server. Common causes:

- **Firewall blocking outbound requests** — some hosting providers restrict which external URLs PHP can connect to. Check with your host.
- **PHP cURL extension not installed** — WordPress needs cURL for `wp_remote_post()`. Check your PHP info for the curl module.
- **Invalid API URL** — the plugin uses the default API URL. If you've modified it (developer mode), verify it's correct.

## Age Gate Not Activating

### Visitors Are Not Being Redirected

If visitors from configured regions can access your site without seeing the age gate:

1. **Check that the MU plugin is installed.** Go to Plugins > Must-Use in your WordPress admin. You should see `xyz-age-gate-redirect.php` listed.

2. **Check Cloudflare proxying.** The DNS record for your domain must be set to "Proxied" (orange cloud) in Cloudflare, not "DNS only" (gray cloud).

3. **Check that regions are configured.** Go to Settings > Free Plan > Regions and verify you have at least one region with the action set to "Verify."

4. **Check the region codes.** Make sure the country code matches what Cloudflare reports. You can verify by looking at the `CF-IPCountry` header in browser developer tools (Network tab > click a request > Headers).

5. **Check for page caching.** If you're using a page cache plugin, cached pages bypass PHP entirely and the MU plugin never runs. See [Caching Compatibility](10-caching-compatibility.md).

### Redirect Loop

If you see a redirect loop (the browser says "this page redirected you too many times"):

1. **Check the age-gate page slug.** It must be exactly `age-gate`. If the slug is wrong, the MU plugin redirects to a URL that doesn't match the age-gate page, which triggers another redirect.

2. **Check for double redirects.** Some security plugins or hosting configurations add their own redirects. Temporarily disable other redirect-related plugins to isolate the issue.

3. **Check test mode.** If test mode is enabled and you're adding `?reg=` to the age-gate page itself, you'll get a loop. The `?reg=` parameter should be added to a content page, not the age-gate page.

### Age Gate Shows But Immediately Redirects Back

If the visitor briefly sees the age gate page but is immediately sent back to the content page:

1. **Check for a stale verification cookie.** Clear cookies in your browser or use an incognito window.
2. **Check the shortcode.** Make sure the age-gate page contains `[xyzav_age_verify]` exactly. A typo in the shortcode will cause the page to render without the verification interface, and the MU plugin may interpret the page load as successful.

## Verification Issues

### QR Code Does Not Appear

- The QR code is generated locally using bundled JavaScript. If it doesn't appear, check your browser's developer console for JavaScript errors.
- Ensure the shortcode `[xyzav_age_verify]` is on the page (not embedded inside another shortcode or block).

### Verification Completes But Visitor Is Not Redirected

After completing verification on their phone, the desktop page should automatically detect the completion and redirect the visitor. If this doesn't happen:

1. **Check that the polling AJAX handler is working.** Open browser developer tools, switch to the Network tab, and look for POST requests to `admin-ajax.php`. They should be returning 200 status codes.
2. **Check session expiration.** Verification sessions expire after a configured period. If the visitor took too long, the session may have expired.
3. **Check the API Status** on the settings page. If the API is unreachable, the polling requests cannot get status updates.

### Verification Passes But Cookie Is Not Set

If verification succeeds but the visitor is asked to verify again on the next page:

1. **Check HTTPS.** The verification cookie has the `Secure` flag set, so it's only sent over HTTPS. If your site serves any pages over HTTP, the cookie won't be included.
2. **Check cookie domain.** If your WordPress address and site address differ (e.g., `www.example.com` vs. `example.com`), the cookie may not cover both.
3. **Check the Cookie Signing Key.** If the signing key is missing or was rotated, existing cookies become invalid. Fetch a new key from the settings page.

## Credit Issues

### "Credits exhausted" Error

Your monthly free plan credits have been used up. Options:

- **Wait for monthly reset** — credits reset on the 1st of each month (UTC).
- **Purchase additional credits** — available through the XYZ website.
- **Switch fail behavior** — if set to "fail closed," your site is inaccessible to unverified visitors. Consider temporarily switching to "fail open" until credits reset.

### Credits Being Used Faster Than Expected

Check the **Recent Verifications** tab in Settings > Free Plan to see exactly where credits are going:

- **Failed attempts consume credits** — if visitors are frequently failing liveness checks, each failure costs 1 credit.
- **Tier 2 costs more** — document verification attempts cost 2 credits each.
- **Escalations** — if many Tier 1 sessions are being escalated to Tier 2, that's 3+ credits per visitor.
- **Test mode** — verification sessions in test mode also consume credits.

## Server / Hosting Issues

### OPcache Serving Stale Code

If you update the plugin or MU plugin file but changes don't take effect:

- Your server may be caching the compiled PHP. Restart PHP-FPM or clear OPcache.
- In Plesk: go to PHP Settings and click "Reset OPcache" or restart the FPM pool.
- In cPanel: restart PHP-FPM from the MultiPHP Manager.

### File Permissions

The MU plugin file needs to be readable by the web server. Typical permissions:

- File: `644` (`rw-r--r--`)
- Directory: `755` (`rwxr-xr-x`)

If the MU plugin isn't loading, check that the file ownership matches your web server user.

## Getting Help

If you've worked through the relevant sections above and are still experiencing issues:

1. Check the **Contextual Help** tabs on the plugin settings page (click "Help" in the top-right corner).
2. Visit [support.xyzinc.com](https://support.xyzinc.com) for the support forum.
3. Include the following when reporting an issue: WordPress version, PHP version, any relevant error messages from the browser console or server logs, and the steps to reproduce the problem.

## Next Steps

- [Caching Compatibility](10-caching-compatibility.md)
- [Membership and Subscriber Sites](11-membership-sites.md)
