BlockWall

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".

Do not set 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().

OptionDefaultDescription
targetbody childrenCSS 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.
messagebuilt inText 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.
stillBlockedTextbuilt inShown if the blocker is still detected after the button is pressed.
networkChecktrueAlso request a well-known ad script. Set false if your Content Security Policy blocks outside requests.
baitUrlGoogle ad script URLThe URL requested by the network check.
recheckInterval15000Milliseconds between automatic checks. 0 turns the timer off.
zIndex2147483000Stacking order of the wall.
onDetectnullFunction called when the wall goes up.
onClearnullFunction 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.

MethodReturnsDescription
init(options)AdBlockWallStarts checking: once on load, then when the tab regains focus, and on the timer. Calling it twice does nothing.
configure(options)AdBlockWallMerges 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()AdBlockWallRaises the wall by hand, for previews. The next check() overrides it.
unlock()AdBlockWallLowers the wall by hand.
isLocked()booleanTrue while the wall is up.
destroy()voidStops 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.

ClassPart
.abw-overlayFull-screen backdrop.
.abw-cardThe dialog box.
.abw-titleThe heading.
.abw-msgThe message.
.abw-btnThe re-check button.
.abw-statusThe line under the button.
.abw-blur, .abw-hideAdded 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.