Documentation
BlockWall is one file, blockwall.js, with no dependencies. It detects ad blockers and locks your content until the visitor turns the blocker off for your site.
Quick start
1. Upload blockwall.js to your site. Keep the name neutral: some blocker lists block files with "ads" or "adblock" in the name.
2. Wrap the content you want to lock in one element, for example <div id="content">.
3. Add this before the closing </body> tag:
<script src="blockwall.js"></script>
<script>
AdBlockWall.init({ target: "#content" });
</script>
If you prefer no second script block, put the options on the script tag:
<script src="blockwall.js" data-auto data-target="#content" data-mode="blur"></script>
The data attributes are data-target, data-mode, data-title, data-message, data-button-text, data-recheck-interval and data-network-check="false".
target to body or html. The wall is added to the body, so a target that contains it is skipped. Leave target out to lock every direct child of the body.Options
Pass these to AdBlockWall.init() or AdBlockWall.configure().
| Option | Default | Description |
|---|---|---|
| target | body children | CSS selector of the elements to lock. Several matches are all locked. |
| mode | "blur" | "blur" leaves content visible but unreadable. "hide" hides it completely. |
| title | "Please turn off your ad blocker" | Heading on the wall. |
| message | built in | Text under the heading. Plain text only. |
| buttonText | "I've turned it off" | Label of the re-check button. |
| checkingText | "Checking…" | Shown while the re-check runs. |
| stillBlockedText | built in | Shown if the blocker is still detected after the button is pressed. |
| networkCheck | true | Also request a well-known ad script. Set false if your Content Security Policy blocks outside requests. |
| baitUrl | Google ad script URL | The URL requested by the network check. |
| recheckInterval | 15000 | Milliseconds between automatic checks. 0 turns the timer off. |
| zIndex | 2147483000 | Stacking order of the wall. |
| onDetect | null | Function called when the wall goes up. |
| onClear | null | Function called when the wall comes down. |
To keep one element usable while everything else is locked, such as a contact link, add the attribute data-abw-ignore to it. This works for direct children of the body, or for matches of your target selector.
JavaScript API
The script adds one global, AdBlockWall.
| Method | Returns | Description |
|---|---|---|
| init(options) | AdBlockWall | Starts checking: once on load, then when the tab regains focus, and on the timer. Calling it twice does nothing. |
| configure(options) | AdBlockWall | Merges options without starting anything. |
| detect() | Promise<boolean> | Resolves true if a blocker is detected. Does not touch the page. |
| check() | Promise<boolean> | Detects, then raises or lowers the wall to match. |
| lock() | AdBlockWall | Raises the wall by hand, for previews. The next check() overrides it. |
| unlock() | AdBlockWall | Lowers the wall by hand. |
| isLocked() | boolean | True while the wall is up. |
| destroy() | void | Stops all checking, removes the listeners and lowers the wall. |
Events and callbacks
When the wall goes up or comes down, BlockWall calls your onDetect or onClear function and fires a DOM event on document. Use whichever you prefer.
document.addEventListener("adblockwall:detected", function () {
console.log("wall is up");
});
document.addEventListener("adblockwall:cleared", function () {
console.log("wall is down");
});
The events fire only when the state changes, not on every check.
Styling the wall
BlockWall adds its own stylesheet with a single-class selector for each part. Override them with a more specific selector in your own CSS.
| Class | Part |
|---|---|
| .abw-overlay | Full-screen backdrop. |
| .abw-card | The dialog box. |
| .abw-title | The heading. |
| .abw-msg | The message. |
| .abw-btn | The re-check button. |
| .abw-status | The line under the button. |
| .abw-blur, .abw-hide | Added to locked content. |
.abw-overlay .abw-card { max-width: 520px; border-radius: 4px; }
.abw-overlay .abw-btn { background: #0a7d4b; }
BlockWall resets the overlay's class and inline style if they are changed, so style it through your stylesheet rather than through scripts.
Examples
Hide content completely
AdBlockWall.init({ target: "#article", mode: "hide" });
Custom text
AdBlockWall.init({
target: "#content",
title: "Ads pay for this site",
message: "Please add us to your blocker's allow list, then press the button.",
buttonText: "Done, let me in"
});
Count how many visitors see the wall
AdBlockWall.init({
target: "#content",
onDetect: function () {
navigator.sendBeacon("/count-wall", "shown");
}
});
Check without locking
AdBlockWall.detect().then(function (blocked) {
if (blocked) { /* show a banner instead of the wall */ }
});
Single-page apps
Lock the stable container that holds your routes, such as #app, and call init() once. Content that your framework adds inside that container later is covered by the container's lock.
Testing
Install an ad blocker such as uBlock Origin in a browser profile, open your page, and the wall should appear within a second. Press the button with the blocker still on and you should see the "still detected" message. Turn the blocker off for the site, press the button, and the wall should come down without a reload.
To test the wall with no blocker, run AdBlockWall.lock() in the browser console on a page that loads the script. Press the button to lower it again.
Test in a private window with your extensions switched off as well, so you know ordinary visitors never see the wall.
Troubleshooting
The wall never appears
Open the browser console. If AdBlockWall is not defined appears, the script did not load: check the path, or the blocker blocked the file. Rename it to something neutral.
The wall appears for visitors without a blocker
Your Content Security Policy probably blocks the network check. Set networkCheck: false, or add the bait URL's host to your connect-src rule. Privacy extensions and some corporate networks also block ad domains, and they look the same as an ad blocker.
The wall does not cover everything
Content outside your target stays unlocked. Either widen the selector or leave out target to lock all direct children of the body. Elements added to the body after the wall went up are locked automatically.
The wall appears but the page behind can still be tabbed through
BlockWall marks locked content as inert, which is supported in Chrome 102, Safari 15.5, Firefox 112 and newer. Older browsers still get the blur and the blocked clicks, but keyboard focus can reach the content behind.
The wall stays up after the visitor allow-lists the site
Some blockers need a page reload before the change takes effect. The re-check button does not reload the page, so add a line to your message such as "If this stays, reload the page."
Limits
BlockWall runs in the visitor's browser. A determined visitor can remove it with developer tools, a user script, or by turning off JavaScript. Use it to ask casual visitors for support, not to protect content that must stay private. Detection is a best guess, and a few blockers and privacy tools can slip through or cause false alarms, so keep your message friendly.
The wall is a dialog that keyboard and screen reader users can operate, but some visitors cannot install or configure a blocker themselves, such as people on a managed work network. Give them a way to reach you if the wall does not clear.