Contents
Introduction
Detecting ad blockers and showing a respectful notice to users is a common need for WordPress publishers who rely on ad revenue. The goal: detect when an ad blocker is likely active and then show a lightweight, accessible, non-intrusive message explaining the impact of ad blocking and giving an easy option to dismiss the notice or whitelist the site. This article covers every practical detail: detection techniques (client and server), WordPress integration, enqueueing, accessible UI patterns, persistence (cookie/localStorage), internationalization, testing, and pitfalls to avoid.
Principles and best practices (summary)
- Be respectful. Avoid blocking core content show a short polite message that explains why ads matter and how to whitelist.
- Be lightweight and performant. Detection should not slow page rendering or introduce heavy network requests.
- Prefer progressive enhancement. The site should work normally even if the notification logic fails.
- Accessible and dismissible. Provide a clear way to dismiss the notice and ensure screen-reader access.
- Minimize false positives. Use robust detection and allow users to dismiss if mistakenly flagged.
- Respect privacy and legal obligations. Do not collect or send tracking data unnecessarily.
Overview of detection methods
No single technique is perfect because ad blockers evolve. Use a combination for higher reliability and a fallback server-side strategy if necessary. The main client-side methods:
- Bait element: insert an element with a class or id commonly blocked (for example, ads, ad-banner) and check if it gets hidden or removed by CSS.
- Blocked resource request: attempt to load a known ad-like URL (for example /ads.js or external ad-domain) and check for failure.
- Script detection: detect if ad-related scripts were blocked (e.g., by injecting a script tag and verifying an expected global doesnt appear).
- Injected variables: check for global signals some adblockers provide (rare and inconsistent).
- Server-side heuristics: examine request headers, patterns, or use client-side result reporting when needed.
Bait element (recommended first approach)
A bait element is the simplest and least intrusive approach. Add a small element with class names that many adblockers target (for example: ad, ads, advert). The adblocker often hides it via CSS script then checks computed style or offsets.
Example JavaScript detection (place in an external file and enqueue in WordPress):
(function () { // Create a bait element var bait = document.createElement(div) bait.className = ad-banner ad adsbox advert ad-placeholder // Position off-screen and low-impact bait.style.position = absolute bait.style.left = -9999px bait.style.height = 10px bait.style.width = 10px document.body.appendChild(bait) // Give the browser a tick to calculate styles setTimeout(function () { var blocked = false try { // If display is none or offsetHeight is 0, likely blocked var style = window.getComputedStyle(bait) if (style (style.display === none parseInt(style.height) === 0 bait.offsetParent === null bait.offsetHeight === 0)) { blocked = true } } catch (e) { // defensive fallback blocked = true } // Cleanup if (bait.parentNode) bait.parentNode.removeChild(bait) if (blocked) { // Trigger your notice function var event = new CustomEvent(adblockDetected) window.dispatchEvent(event) } else { var event = new CustomEvent(adblockNotDetected) window.dispatchEvent(event) } }, 50) })()
Notes:
- Keep the bait small and off-screen so it does not affect layout.
- Use multiple class names to improve coverage.
- Use a small timeout (50–200 ms) to allow CSS to apply avoid long delays.
Blocked resource request (more robust)
This approach tries to load a resource commonly blocked by adblockers. If the request fails or is blocked, that’s a signal. Use a same-origin path you control (e.g., /ads.js) or an intentionally named resource that will be blocked. Important: do not rely on loading external ad networks create a simple endpoint that returns a small JS file.
(function () { var url = /ads.js?v=1 // a short lightweight endpoint you create on your site var timedOut = false var timeout = setTimeout(function () { timedOut = true handleResult(false) // treat timeout as blocked/unreachable }, 1500) var s = document.createElement(script) s.src = url s.async = true s.onload = function () { if (!timedOut) { clearTimeout(timeout) // If script executed, adblock did NOT block this resource handleResult(true) } } s.onerror = function () { if (!timedOut) { clearTimeout(timeout) handleResult(false) // blocked or failed } } document.head.appendChild(s) function handleResult(notBlocked) { if (!notBlocked) { window.dispatchEvent(new CustomEvent(adblockDetected)) } else { window.dispatchEvent(new CustomEvent(adblockNotDetected)) } // cleanup try { s.parentNode.removeChild(s) } catch (e) {} } })()
Notes:
- Use a short timeout (1–2 seconds) and treat errors as blocked.
- Create a tiny endpoint programmatically in WordPress to respond with a no-op JS payload.
- This is generally more robust but can be affected by network errors and proxies, so combine with a bait element.
Server-side fallback (WordPress)
You can add a server-side hook to add a CSS class or inline script to the page when client-side detection is not available. Server-side detection is inherently harder and less reliable for adblockers, so prefer client-side detection with a server fallback to record results (optional).
// Example: functions.php - register a tiny endpoint and enqueue scripts
add_action(init, function () {
// Register a rewrite rule or endpoint for /ads.js
add_rewrite_rule(^ads.js
|
Acepto donaciones de BAT's mediante el navegador Brave :) |