How to Detect Ad-Blockers

18th February 2016

Source Code | Demo

There's no doubt about it, the use of ad-blockers is on the rise. Feelings run high on the issue; with web users arguing that advertisements are beyond control, that they have become too intrusive and that their privacy is being undermined. Internet-based publishers, meanwhile, argue that advertisements are a crucial - in many cases, only - source of income online, and that ad-blockers threaten their very existence.

That's not to say that one must sit in either camp - those of us who are involved in producing content still browse the 'Web as consumers, and may feel with some justification that on some sites, the use of advertisements is ruining the online experience.

Wherever you stand on the issue, it's clear that middle ground needs to be found.

Increasingly, online publishers are including scripts which attempt to detect whether users have an ad-blocker installed when they visit their site. They may then display a message explaining the importance of advertisements, politely asking that users consider turning it off. Many publishers also use the opportunity to suggest other ways people can show their support. The Guardian - an on and off line newspaper in the UK - is one example of this; if you browse their site with an ad-blocker enabled, they display a message about their membership scheme. Publishers are exploring other ideas; such as selling PDF versions of their content, or accepting "tips" online.

The purpose of this post isn't to wade into the debate; but rather, to demonstrate how site-owners and publishers can detect whether a user has an ad-blocker enabled, and some approaches to displaying messages or alternative content.

How do Ad-Blockers Work?

In order to understand how to detect ad-blockers, it's useful to understand how ad-blockers themselves work.

A disclaimer: I've had no personal involvement in building or maintaining ad-blockers, so I can't answer this with one hundred percent certainty, or describe the approach taken by all the various ad-blockers out there. Nor will I cover more complex ad-blocking, such as preventing online videos from showing advertisements. However, after a little digging I can describe the approach used by the hugely popular AdBlock plugin.

One approach to ad-blocking is to dynamically inject a CSS rule which matches elements known or thought to contain adverts, and hides them. Simple, really.

How to Ad-Blocker Detectors Work?

In this article I'm going to be using a library, so let's look at how that works - there may well be other approaches.

What this library in particular does is dynamically inject a <div> into the page as "bait". It assigns a bunch of classes designed to make ad-blockers think that it contains adverts.

Once the bait is laid, so to speak, the library simply waits to see what happens to it. Specifically, it uses window.getComputedStyle() to determine whether it's been hidden. If it has, then chances are an ad-blocker is being used. Pretty simple, in essence - although it's probably fair to say that it's neither fool-proof nor future-proof.

For reference, here are the default classes for the library I'm using:

// CSS class used by the bait caught AdBlock
baitClass: 'pub_300x250 pub_300x250m pub_728x90 text-ad textAd text_ad text_ads text-ads text-ad-links'

Now that we understand how it works, we can start looking at the implementation.

Implementing Ad-Block Detection

Im going to demonstrate how to do this using a library named BlockAdBlock. It's actually a clone of a library with a slightly more "colourful" name.

Installation is simple - if you're using Bower:

bower install blockadblock --save

Alternatively, simply clone or download it from Github.

You'll need to include the script in your build, or reference it directly, for example:

<script src="/bower_components/blockadblock/blockadblock.js"></script>

The library offers a couple of alternative approaches to detecting ad-blockers; let's look at the simplest.

It exposes an object which implements two event handlers - onDetected() and onNotDetected(). Each takes a function (anonymous or otherwise) as a parameter.

Let's build an example page to show the plugin in action. We'll incorporate a couple of areas designed to contain advertisements, and we'll implement two "responses" to discovering that the visitor has an ad-blocker:

  1. We'll include a hidden message at the top of the screen, which we'll show appropriately.
  2. We'll inject a message into one of the areas set aside for advertisements.

Here's some simple HTML:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <title>Ad-blocker Detection Demo</title>

    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" integrity="sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7" crossorigin="anonymous">

  </head>

  <body>

    <div class="container">

      <div class="adblock-nag alert alert-info" role="alert" style="display:none;">
        <p>It looks like you're using an ad-blocker.</p>
      </div>

      <div class="pub_728x90">
        <div class="well">
          <p>This is a banner advert.</p>
        </div>
      </div>

      <header>
        <h1>Ad-blocker Detection Demo</h1>
        <p class="lead">This simple demo demonstrates how you might detect ad-blocks, displaying a message for example.</p>
      </header>

      <div class="row">

        <main class="col-md-9">
          <p>This is the main content area. There is an area above the header for banner adverts, as well as a right-hand column (or below on small screens) also designed to display adverts.</p>
        </main>

        <aside class="col-md-3">
          <div class="ad-right">
            <div class="well">
              <p>This is an area which contains adverts.</p>
            </div>
          </div>
        </main>

      </div>

    </div><!-- /.container -->

    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
    <script src="/bower_components/blockadblock/blockadblock.js"></script>

    <!-- The ad-block detection code will go here -->

  </body>
</html>

There are a couple of things to notice here.

The region designed to hold a "banner" image has the class .pub_728x90. This is one of a number of class names used by the plugin to identify an area likely to contain advertisements.

Likewise, we've created a region in the sidebar with the class .ad-right.

Near the top of the page, the <div> with the class .adblock-nag, explicitly defined to be hidden, is our "nag" message which we'll show if an ad-blocker is enabled.

With that in mind, let's implement the detection process.

For the purposes of this demonstration, I'm going to put the code inline in the HTML, but naturally you can put it in an external JavaScript fie if you prefer.

Let's start by defining a function for when an ad-blocker is not detected:

// Function called if AdBlock is not detected
function adBlockNotDetected() {
  console.log( 'AdBlock is not enabled' );
}

In practice, this is probably redundant, although you may find a use for it - collecting metrics, for example.

Now, a function designed to be run if an ad-blocker is detected:

// Function called if AdBlock is detected
function adBlockDetected() {

  $( '.adblock-nag' ).slideDown( 'slow' );

  $( '<div>' )
    .html(' <p>Please support us by turning off your ad blocker' )
    .addClass( 'alert' )
    .addClass( 'alert-info' )
    .insertBefore('.ad-right');

}

As you can see, the first part shows our hidden "nag" message. The second injects content dynamically into our sidebar advertisement region. It's important to note that I'm injecting the message into the column rather than into the area set aside for advertisements. If you try to inject content into the latter, chances are it'll remain hidden by the ad-blocker. As such, I'm using insertBefore() to target the area above the advertisements.

Finally, we need to configure the event handlers.

The first thing to note is that according to the documentation, it's possible that an ad-blocker may block the ad-block detection library, either now or in the future. In order to get around this, we'll first check if the exposed object is undefined. Otherwise we simply use the onDetected() and onNotDetected() methods to attach our event handlers.

if ( typeof blockAdBlock === 'undefined' ) {

  adBlockDetected();

} else {

  blockAdBlock.onDetected( adBlockDetected );
  blockAdBlock.onNotDetected( adBlockNotDetected );          

}

Simple as that.

Note that although we're using JQuery in this example to manipulate the DOM, the library itself does not require it.

There are additional options, which you can find out about by browsing the plugin documentation.

The code from this post is available on Github. There is also an online demo.