After I published my adblock counter plugin BlockAlyzer (Update: deprecated) for WordPress, I started to analyze the number of adblock users during our AdSense-Reviews. Some of our clients did have a serious adblock-problem, others didn’t and we could spare them the time and money to implement anti-adblock strategies. Anyway, not all of our clients use WordPress as the content-management-system of their choice, so I wasn’t able to use BlockAlyzer. In this article I am going to explain how you can count adblock-users with simple JavaScript and a bit of PHP, so most website owners can implement this. You can even download the complete files.

How does an adblocker work?

To understand the following code and scripts, you should first get an idea of how an adblocker works. In a nutshell, an adblocker is blocking HTTP-requests. Those are done to load additional files like styles, scripts or images. To distinct a “normal” script or image from a script that loads an ad like the file show_ads.js from Google AdSense or a static image banner, adblockers like AdBlock Plus use lists with sources of ad-related HTTP-requests. These lists are also called filters.

The adblocker now monitors the HTTP-requests and compares them to the filters. If it finds a match, the ressource is not loaded. A lot of the filters are patterns that match such small things like file names. Allowing some ad ressources (called whitelisting) is possible, but this is a completely different topic.

A filter for an ad script like Google AdSense can be as simple as /show_ads.js or more complex, especially if they are design to work only on specific websites. You should be able to not only see the full list of filters in your adblocker, but also add some new elements if you feel disturbed by them.

How to detect an adblocker?

After you know now how an adblocker works it is quite easy to detect it. Basically, I would divide the methods into two groups.

  1. Check, if the content has changed
  2. Check, if a ressource has been loaded

Check, if the content has changed

Some adblock test scripts like the great one from Saurdo suggest to put some containers with a specific class around your ads. The adblock script than checks the height of these blocks after the site (and probably the ads) have been loaded. If the height of the containers is still 0, the user probably uses an adblocker. The very basic test in plain JavaScript looks like this:

[javascript]

blocked = 0;

if (container.offsetHeight == 0){
blocked = 1;
// do any action now or later with blocked
}

[/javascript]

In my experience, this method has the drawback of not being flexible, especially on websites you don’t know perfectly or where you can’t easily add a container around the ads. It might also be possible that for various reasons the height of an element is never 0, like when the web-developer assigned a mininimal height using CSS.

Check, if a ressource has been loaded

For the reasons mentioned above and to be more independent of the actual content of the website of my clients, I suggest to test for adblocker with an additional ressource. There are two methods for that, and just to be sure, I use both in my BlockAlyzer plugin.

Check for a banner image

The first method to test for adblock with an extra ressource is similar to the method before, but instead of using an element that already exists on the website, you load an additional ressource. This way you don’t have to modify your script every time you use it on another website. Well, maybe this is just a problem for someone who is doing ad optimization for clients or multiple of own projects.

The extra ressource in this case is the image banner.gif with the size of 1×1 and a transparent background. Simply load it anywhere with an <img> tag and an unformated containter with a specific id around it. Than use the code from above to check the height and voilá, you can start counting. banner.gif should be included in the popular adblockers, but if you want to be a 100 percent sure, move the file into a folder called ads.

Check adblock with JavaScript file

The second method using an additional ressource is with the help of the (under adblocks perspective) suspicious named file advertisement.js. In case of BlockAlyzer, this file contains just the three following lines:

[javascript]

jQuery(document).ready(function($) {
$.adblockJsFile = true;
});

[/javascript]

Be aware that this is jQuery. To use simple JavaScript try the following code:

[javascript]

var adblockJsFile = true;

[/javascript]

In your main code you now just need to check if the variable is set. In the full script you can download below this is done with the following snippet.

[javascript]
blocked = 0;
if ( typeof adblockJsFile == 'undefined' ) {
blocked = 1;
}
adblockRecordBlock(blocked); // record value
[/javascript]

Even though I prefer the adblock test with advertisement.js, I don’t want to hide the argument I see against it: an additional ressource is being loaded. That means an extra HTTP-request that will make every performance purist cry a little.

The whole adblock test script

To make this post valuable for you, I updated the plain JavaScript code from Saurdo to work with the advertisement.js. Please feel free to use his code instead, if you like the container-check method more or want to display a message to your users.

Download the files here

Files included:

  • adblocks.php
  • adblocks.txt
  • advertisement.js
  • index.html (sample code)
  • readme

How to install the adblock counter

1. Copy adblocks.php, adblocks.txt and advertisement.js in your websites root folder or any other folder if you are more experienced.

2. Include advertisement.js in your header writing the following line between your <head> tags.

[html]

&amp;lt;script type="text/javascript" src="advertisement.js"&amp;gt;&amp;lt;/script&amp;gt;

[/html]

You might need to adjust the path to the file if advertisement.js is not in the root folder of your website.

3. Copy the code in the <script> tags in index.phtml (line 33 to 69) into your websites code. The best place for it is before the closing </body> tag.

4. Edit php_url in line 34 if your php-file is not in the root directory.

5. Visit your website and check if the content in adblocks.txt has updated.

If this didn’t work, please check spelling and paths of the files. If file names and paths are fine, please leave a comment telling me about your problem.

How to evaluate the result

After a while you might want to check adblocks.txt for your numbers. You find two values seperated with a hyphen there. The first value represents the total number of page impressions. The second number is the amount of page views with adblock enabled.

To get the percentage, just divide the number of adblock views by the total number of page views and multiply it by 100:

adblock page views / total page views * 100 = percentage of adblock pageviews.

Update October 16th: I added the percentage of the adblock users. The output of adblocks.txt should now look similar to this:

540-243 – (45%) – started: 16/10/2013 10:54

To compare the numbers, I installed this script together with BlockAlyzer on one of my private blogs. The numbers did vary a bit (19% to 17.3%), what I don’t find too bad.

Additional notes

If you write your JavaScript code for all the adblock checks into an additional file you need to be carefull not to call it with a name that alarms an adblock-filter like ad_script.js or something like that. Even if you come up with a non suspicious name, the adblock developer might add it to the filter, because some of the adblock users might feel disturbed by this method. To be save, implement the JavaScript in your html file.

If you don’t run your website in php, you need to change the file adblock.php into a file of your programing language. The file is quite simple and if you know your programing language, you won’t have a problem transfering it.

Updating the numbers in the adblock.txt-file is not the best choice, but the easiest for me to use the script on a clients site to just get an impression on the number of adblock users. I recommend you don’t use this script for a longer period.

BlockAlyzer writes the information into the database and I am working on other ways too. You might want to subscribe to the newsletter to get updates on this.

Updates

October 16th: thanks to Tom’s comment below, I updated the script so adblocks.txt also includes the percentage of adblock users and the date when counting was started. I also added some tests to check, if adblocks.txt does already exist.

The Author

Comments

  1. thomas

    Changed the adblocks.php code, so it calculates the percentage itself and a little remark field at the end, for example for the start date/time.
    Second, the script is not always able to read correctly, so the output override the results, kind of reset. A simple check solved this problem.

    <?php

    // detect if sent by AJAX
    if ($_SERVER['HTTP_X_REQUESTED_WITH'] == "XMLHttpRequest")
    {
    $blocked = $_GET['b'] == 1 ? 1 : 0;

    if ($file = explode('-',file_get_contents('adblocks.txt')))
    {
    $impressions = $file[0];
    $blocks = $file[1];
    $percentage = $file[2];
    $rest = trim($file[3]);

    $impressions++;
    $blocks += $blocked;

    file_put_contents( 'adblocks.txt', $impressions . '-' . $blocks . ' – (' . round((($blocks/$impressions)*100),2) . '%) – ' . $rest);
    }

    }

    ——-
    Example of the adblocks.txt

    187-5 – (2.67%) – Started 21/09/2013 10:07
    ——-

    When the script succesfully runs 24hours, percentage is 23% on my forum (automobile related)

    1. Thomas Maier Article Author

      Hi thomas, thanks for your contribution. I am not sure what you ment with the override, but will give it a try.
      Thanks
      Thomas

      1. thomas

        Well, the script always assumes the file is read correctly, even when it is not.
        While i was watching the results online by viewing {url}/adblocks.txt, suddenly they went from 4600-920 to 0-0 after a refresh issued by me.

        I guessed that the script must have been executed as normal, but was not able for some reason to read the file correctly, so $impressions and $blocks where undefined.
        Even though ‘file_get_contents’ function failed, ‘file_put_contents’ did not fail, and as the variables where undefined, 0-0 was written to the file, overriding the 46…
        …Oh crap, reading this back i see a lousy translation error, NOT override, but overwritten ….so sorry

        Well, anyway, i thought using a simple …if…then… with ‘file_get_contens’ might do the trick of checking if the file was successfully read.
        It was my understanding that a successful file-read would result in a ‘1’ or TRUE, in which case the ‘file_put_contents’ was legit, as $impressions and $blocks where defined.

        No more glitches since..

        Now to find a trick to give non-adblockers a little more page-speed then adblock users. Not to really nag, just my ‘thank you’ for not blocking ads which i use to pay the hosting bill. 🙂

        Regards, Tom

        1. Thomas Maier Article Author

          Thomas, thanks again! Now I understand the issue and will add the fix asap.
          Regarding page-speed you might add a visible timer that counts down before showing the content. It is not really a page-speed solution, but feels like it for most of the visitors.
          Best regards
          Thomas

          1. thomas

            Found another (polite?) way.

            In the code to be copied from index.html, i found the following:

            onload=function(){

            // initiate variable
            blocked = 0;

            // check if our variable from advertisement.js was set
            if ( typeof adblockJsFile == ‘undefined’ ) {
            blocked = 1;
            }
            // activate recordBlock function
            adblockRecordBlock(blocked);
            }

            After the blocked = 1; definition, i added a nice message to the customers how good AdBlock is working for them, with the following instruction:

            setTimeout(function() { alert(‘AdBlocker blocked 3 AdSense banners for you on : {sitename} ‘);}, 150);

            Now they get an alert on each page they visit that AdBlocker blocked 3 banners for them, and depending on the browser, it looks like messages from AdBlocker itself.
            Oh, and they have to click OKAY each time, that’s just the nature of the beast called Alert().
            The delay is set on 150ms, but you can change it if you want, so it looks like AdBlocker had to do some more work.

            It is not asking to turn of the AdBlocker or to white-list the site, it is not complaining what over-excessive use of adblockers do to community’s or make fora admins begging for donations to keep up the good work, it’s is just telling them that their neat little favorite add-on has blocked 3 banners for them.

            I’m not really ANTI-adblock; some sites really do deserve to be blocked, but I am against that the ‘good’ behaving sites get the same treatment, and the fact that unless the advertising company pays AdBlock (wtf??) to NOT block their advertisements, every advertisement, no matter how relevant, gets blocked by default.

          2. Thomas Maier Article Author

            I must admit, that even though I would never use this method, this idea was so mean and creative at the same time, it made me smile.

    2. Thomas Maier Article Author

      Hi thomas, I finally found some time to have a look at your suggested code. I updated the script with some minor optimizations.

  2. Jason

    hello, I used your plugins, but it looks like simple error on the dashboard WP (dashboard_widget.php)
    wp-content/plugins/blockalyzer-adblock-counter/templates/dashboard_widget.php on line 3
    may you help me to fix it, please
    regards

    1. Thomas Maier Article Author

      Hi Jason, thank you for getting in contact. Please report bugs for BlockAlyzer on the plugin page on wordpress.org. Thanks. Thomas

    1. Thomas Maier Article Author

      Hi Ivan, thank you for your comment. The principle in your code is a lot like my method using the advertisement.js.

  3. randy

    hello thomas,
    your banner.gif solution or the saurdo solution would work better in my case than your js file option for my non-blog website. (because i’ve tried to avoid using any of the adblock flag-terms in my file, directory, class or id names, my ads still appear to be slipping past adblocks.)
    unfortunately, when i try to download Saurdo’s zip file from his site, all i get is an error message. do you happen to have the code that would write to a text file, the number of times a gif that’s wrapped inside a div is being suppressed due to adblocks (ie: your “Check for a banner image” option)?
    thank you very much!

  4. randy

    hi again thomas,

    you know what, you can disregard my question about the code for your banner.gif option that i posted a short while ago. i was able to get things working with your js option.

    thanks again

      1. randy

        hi thomas,
        i misunderstood how your js option worked. i didn’t realize that it will record ANYTHING that an adblocker blocks… regardless of what the button image is named (or the wording in text links, i guess).
        thanks again,
        randy

      2. randy

        hello thomas,

        i hope you don’t mind if i bother you just one last time regarding this topic.

        in order to play around with your script, i initially created a test page on a domain i’ve owned for a pretty long time but never developed. after i was done tweaking things, i reset adblocks.txt to 1 – 0 and asked just one friend to visit the site. a couple hours later, i was curious to see if he’d done so, so i checked adblocks.txt to see if it would reflect his visit. surprisingly, it showed something like 24 – 2. i was so shocked that i set it back to your default 1 – 0. overnight, however, it has grown to 37 – 7.

        i’m pretty certain that no humans would be landing on this test site and there are a small number of backlinks so i suppose these visitors could be scrapers, bots, etc… but would they use adblock? i always assumed that scrapers and bots had their js disabled… so your script wouldn’t even be capturing them with js disabled.

        do you have any thoughts on whether bots would influence your adblock stats?

        randy

      3. randy

        hi thomas,
        (if you wouldn’t mind deleting some of mycomments, that may be best because i’ve been such a pest.

        but, am i correct in understanding that your script will capture only the first visit on a site. adblocks.txt reports my first landing on a site but it doesn’t seem to update if i visit subsequent pages on the site. is this correct?

        also, you mentioned above “I recommend you don’t use this script for a longer period.” why would it not be wise to keep the script active all the time?

        thanks a million,
        randy

        1. Thomas Maier Article Author

          Hi Randy, I am not going to delete good questions 🙂
          The script should capture each impression. Did you implement it on every page?
          I recommended to not use it for a longer period because it might not be needed and – even if not significantly – uses some performance. However, I know many publishers to measure it all the time and no one every felt an impact on performance.

          1. randy

            thanks for your reply thomas,

            i realized that my htaccess file was causing your script to only capture the landing page. i haven’t determined the exact conflict, but once i removed my htaccess, every page visit started showing up in adblocks.txt.

            thanks again!
            randy

  5. Ashley Jones

    I noticed some things are being blocked like ebates.com and a few links in google. Unfortunately even adding ebates.com to my whitelist I was having it blocked. Another problem I’ve been having has been finding a simple way to turn this off. It seems if I just remove the startup/firewall commands and reboot my router tends to hang forcing me to do a 30/30/30 reset and reload all my settings. Any suggestions or ideas for an easier way to turn filtering on and off?