WordPress
The Zero Ad Network plugin announces your Publisher ID, recognises subscribers, and cleans up pages through popular ad, consent, popup and membership plugins.
In short
- You need: WordPress 4.9 or newer, PHP 7.2 or newer with the Sodium extension, and your Publisher ID.
- You do: install the plugin, paste your ID, choose any paid content to include, and make subscriber requests bypass your page cache.
- Done when: a test subscriber sees clean pages and included content, and everyone else sees your normal website.
Your Publisher ID
This is an example Publisher ID. Replace it with your own before using it.
zapub_7Fq2xR9nKd3wV8mB4tL6yH1c
You can also copy it from Websites & creators.
1. Install and configure
- In WordPress, open Plugins → Add New Plugin. Search for Zero Ad Network, then install and activate it. You can also download it from WordPress.org, and use Upload Plugin.
- Open Zero Ad Network → Settings.
- Paste your Publisher ID, and select Enable Plugin.
- Leave Publisher Header Method set to HTTP Response Header. Choose HTML Meta Tag only if your hosting requires it.
- Save your settings.
The plugin takes your allowed hostnames from your WordPress Address and Site Address settings. These must match the public domains you serve.
2. Include paid content
Skip this step if you don't sell access.
- Edit a post or page you want subscribers to read.
- In the Freedom access box, check Include this content with Freedom.
- Save. Repeat for each post or page.
Offer your base subscription content, or a custom selection of paid content. Anything you don't select keeps its current restrictions.
3. Set up page caching
Page caches can serve pages before WordPress runs, so the plugin never sees the subscriber. Configure every cache so requests that carry Better-Web-Token bypass it and reach WordPress. See Page caches and CDNs below.
Then clear all page caches.
4. Check it works
- Visit a public page. Confirm it includes
Better-Web-Publisher, as a response header or meta tag. - Once your website appears in your dashboard, open its page and select Test in your browser.
- Visit pages with ads, cookie banners and popups. They should be gone.
- Open included paid content. It should open. Unselected, private, draft and password-protected content should stay protected.
- Open the same URLs without the extension. Your normal website should still work.
What changes for subscribers
On normal front-end pages, a verified subscriber gets every supported integration at once:
- Ads and known non-essential tracking scripts are removed.
- Cookie consent banners and marketing popups are removed or hidden.
- Posts and pages you included open through the supported membership plugins.
These stay the same:
- Unselected content, higher tiers, private posts, drafts and password-protected posts keep their restrictions.
- The plugin doesn't create purchases, website memberships or admin permissions.
- WordPress admin, AJAX, REST API and JSON responses are never changed.
Visitors with a missing or invalid token get your normal website.
The plugin can't cover every theme or custom ad placement. Check real pages, including protected posts and scripts your theme loads. See the supported plugins reference.
Troubleshooting
Your website isn't detected. Check that the plugin is enabled, the Publisher ID is correct, and old cached pages are cleared.
Subscribers still see ads or a paywall. First, check that their requests reach WordPress with Better-Web-Token. A page cache or CDN is the usual cause. Then check the plugin integration for that ad or paywall.
Page caches and CDNs
A page cache can serve HTML before WordPress runs, so the plugin can't check the token. Configure every caching layer to skip both cache reads and writes when a request includes Better-Web-Token, and to forward that header to WordPress.
Once the plugin runs, it takes care of the response:
- Token requests get
Cache-Control: private, no-store, no-cache, must-revalidate, max-age=0, plus CDN and LiteSpeed no-store signals andDONOTCACHEPAGE. - Public responses stay cacheable, and vary on
Better-Web-Token. - It creates no subscriber cookies or subscriber cache entries. A
zeroad_variantcookie orX-ZeroAd-Variantheader never grants access.
For Nginx, Varnish and Cloudflare rules, and the full cache test, see Page caching and CDNs.
WordPress and server caches
PHP page caches can load through advanced-cache.php, before regular plugins run. If your website already defines WP_CACHE, replace that definition in wp-config.php with this:
$freedomTokenRequest = array_key_exists('HTTP_BETTER_WEB_TOKEN', $_SERVER);
define('WP_CACHE', !$freedomTokenRequest);
if ($freedomTokenRequest && !defined('DONOTCACHEPAGE')) {
define('DONOTCACHEPAGE', true);
}
Don't add a second WP_CACHE definition. This bypasses the PHP drop-in only. It doesn't bypass a CDN, or a web-server rule that serves cached HTML directly. WordPress loads the drop-in early.
| Cache | What to configure |
|---|---|
| WP Super Cache | Use PHP/Simple delivery with the bypass above. Expert (rewrite) delivery also needs a server rule before cached files are served. |
| WP Rocket, W3 Total Cache, WP Fastest Cache | Use the bypass above wherever the PHP drop-in runs. Configure any direct cached-file delivery separately. Automatic compatibility is not claimed. |
| LiteSpeed Cache | Exclude token requests before the server cache lookup. The plugin also marks responses non-cacheable through LiteSpeed's hook and header. |
| Apache, CloudFront, managed hosting | Bypass both lookup and storage, and forward the token header. If you can't, turn off HTML caching on participating pages. |
WP Super Cache's Simple and Expert modes run at different layers. LiteSpeed documents its no-cache response hook. Neither lets a normal WordPress plugin run before an upstream cache hit.
WordPress cache checks
Clear all page caches after changing cache settings or included content. Then run the cache checks, and add these:
- Send a forged
zeroad_variant=subscriber1cookie, and a forgedX-ZeroAd-Variantheader. Neither may grant Freedom access. - Existing WordPress membership permissions still work as before.
These are deployment checks. The plugin's own tests don't certify third-party cache setups.
Token verification caching
Under Performance & Caching, Enable APCu Caching reuses token verification results between PHP requests when APCu is available. Without APCu, results are kept for the current request only. Cache TTL (seconds) sets how long results are kept.
This setting doesn't configure a CDN or full-page cache. Verification works without APCu.
Supported plugins reference
The tables below list the integrations in the current plugin. Depending on the integration, it uses plugin hooks, script removal or CSS. This is not a certification of every plugin version. Check your installed versions and theme with a subscriber visit.
Identifiers are the text domains the plugin checks for active plugins, unless a callback or filter is named. They are not always WordPress.org download slugs. Custom markup and plugin updates can need extra work.
Advertisements
| Plugin | Detection or hook |
|---|---|
| Ads For WP | ads-for-wp |
| Ad Inserter | ad-inserter |
| Advanced Ads | advanced-ads |
| WP Quads | quick-adsense-reloaded |
| AdRotate | adrotate |
| Advanced Ads - Google AdSense In-feed | advanced-ads-adsense-in-feed |
| AdWidget | AdWidget_ callbacks |
| WP AdCenter | wpadcenter |
| Corner Ad | corner-ad |
| Ad Injection | ad-injection |
| Simple Ads Manager | simple-ads-manager |
| BuddyPress Ads | buddypress-ads |
| Google Site Kit (AdSense) | googlesitekit_adsense_tag_blocked filter |
Raptive/AdThrive is not confirmed. Its rule checks the cmb2 text domain before removing AdThrive_Ads callbacks. But CMB2 is a separate custom-fields toolkit, so the rule doesn't reliably detect Raptive. Check your website's ads yourself.
Cookie Consent Banners
| Plugin | Detection or hook |
|---|---|
| Cookiebot | cookiebot |
| Beautiful Cookie Consent Banner | bar-cookie-consent |
| Real Cookie Banner | real-cookie-banner |
| GDPR Cookie Consent | gdpr-cookie-consent |
| Pressidium Cookie Consent | pressidium-cookie-consent |
| WPConsent | wpconsent-cookies-banner-privacy-suite |
| GDPR Cookie Compliance | gdpr-cookie-compliance |
| Complianz | GDPR/CCPA Cookie Consent | complianz-gdpr |
| CookieYes | GDPR Cookie Consent | cookie-law-info |
| Cookie Notice & Compliance for GDPR / CCPA | cookie-notice |
| CookieAdmin | cookieadmin |
| Cookie Notice and Consent Banner | cookie-notice-and-consent-banner |
| Cookies and Content Security Policy | cookies-and-content-security-policy |
| Termly - GDPR/CCPA Cookie Consent Banner | uk-cookie-consent |
| GDPR by Trew Knowledge | gdpr |
| Cookie Consent Box by Supsystic | gdpr-cookie-consent-by-supsystic |
Marketing Dialogs & Popups
| Plugin | Detection or hook |
|---|---|
| Popup Maker | popup-maker |
| OptinMonster | optin-monster-api |
| Popup Maker WP | SGPM callbacks |
| Popup by Supsystic | popup-by-supsystic |
| PopupKit | popup-builder-block |
| Popup Anything - A Marketing Popup | popup-anything-on-click |
| Advanced Popups | advanced-popups |
| Popup Box | ays-popup-box |
| Depicter - Popup & Slider Builder | depicter |
| FooBox Image Lightbox | foobox-image-lightbox |
| MailOptin Lite | mailoptin |
| Poptin | poptin |
| Popup Builder | popup-builder |
| Popups for Divi | divi-popup |
| Hustle | hustle |
| WP Popups Lite | wp-popups-lite |
| Icegram Express | email-subscribers |
| Convert Pro | convertpro |
| Newsletter Popup | newsletter-popup |
| Ninja Popups | ninja-popups |
| Thrive Leads | Thrive_Leads class and tve_leads_should_display filter |
Convert Pro and Convert Plus. The Convert Pro rule checks convertpro and removes Convert_Plug callbacks. An extra cp_show_popup override is registered only when cp_v2_popup_enabled exists. Convert Pro and Convert Plus are separate products, so this shared override doesn't establish full support for both.
Included subscription content
Posts and pages you include are opened through:
| Plugin | Content access hook |
|---|---|
| Paid Memberships Pro | pmpro_has_membership_access_filter |
| WP-Members | wpmem_block |
Each adapter uses the post the membership plugin supplies, so including one post doesn't unlock another. See the Paid Memberships Pro hook reference and WP-Members hook reference.
Other paywalls and custom paid features need their own integration. Freedom access only applies to included content through supported integrations. It doesn't create a website subscription or purchase, or bypass post passwords. Selecting content alone can't unlock an unsupported plugin.
Custom included access
For custom templates, use \ZeroAd\WP\Actions\SubscriptionAccess::allowsPost($post) to decide whether to show included paid content. It checks both the verified subscriber and your selection. Keep any access the visitor already has through your own membership system:
$canRead = $existingAccess || \ZeroAd\WP\Actions\SubscriptionAccess::allowsPost($post);
To include a group of content instead of selecting each post, use the zeroad_freedom_includes_post filter. This example includes a category you create:
add_filter('zeroad_freedom_includes_post', function ($included, $post) {
return $included || has_category('freedom-included', $post);
}, 10, 2);
The filter defines which content is included. It isn't proof of membership, so use allowsPost() for the actual access decision.
- Private, draft, password-protected and non-post/page content stays excluded.
- Map custom paid features separately in your application. Don't grant account-management or purchase permissions.
- Clear page caches whenever your included selection or custom mapping changes.
An already-clean, unrestricted website only needs its Publisher ID. A paywalled website isn't finished until real included access works for subscribers.