Sunday, November 23, 2008

Detect images blocked by AdBlock Plus

I needed to pass a little time so I felt like looking into how AdBlock Plus hide images. Instead of diving into the numerous files used to form that which is AdBlock Plus, I decided to take a simplistic way into the matter. I created myself a sample HTML page with an image displayed on it, then I used Ad-Block to block anything in that folder.

To block the image(s) I used something along the lines of:
http://example.com/images/ads/*
Next I used the JavaScript Shell bookmarklet from squarefree.com
I used it to look at the innerHTML of the page, the difference was that the <img> tag now had "display: none" inside of the style parameter.

Now that we know how the image(s) are hidden we can now detect when it is being done.

What we're going to use to accomplish this is:
  1. JavaScript/MooTools JavaScript framework
  2. A little bit of CSS
  3. Some <div> tags and a <noscript> tag
Download MooTools onto your server from here.
(at the time of writing this I used the current version 1.2.1)

At the top of the .js file add this line:
var mtloaded = 1;
This is just a precaution in case the JavaScript file is blocked from loading. We're going to check for this variable to ensure the file loaded.

Add MooTools to the <head> section of your HTML:
<script src="js/mt.js" type="text/javascript"></script>
Now to add the <div> tags.

The first <div> tag is going to be for the main content of the site.

Now give the <div> an id and a little bit of CSS like so:
<div id="container" style="display: none">
Now at the bottom of the HTML just before </body> add:

<noscript>
<h1>Javascript is required to view this site, enable it to continue.</h1>
</noscript>
<div id="notice" style="display: none;">
<h1>Ad-Block software detected, disable Ad blocking if you wish to view this site.</h1>
</div>

Now add an id to your image that you don't want blocked:
<img id="ad" src="http://example.com/images/ads/17adco.jpg" />

Now for the JavaScript which will be doing all the work, add this to your <head> section:

<script type="text/javascript">
window.addEvent('domready', function() {
// every 2 seconds
var timer = 2;
var periodical;
var ad = $('ad');
var content = $('container');
var notice = $('notice');

if(mtloaded == 1)
content.setStyle('display', 'inline');

var checkad = (function() {
if(ad.getStyle('display') == 'none'){
var adsrc = ad.src;
if(adsrc.contains('adblock')){
content.setStyle('display', 'none');
notice.setStyle('display', 'block');
Cookie.write('adblock', '1');
$clear(periodical);
}else{
ad.setStyle('display', 'inline');
ad.src = ad.src + '?adblock';
}
}
});

periodical = checkad.periodical(timer * 1000, this);
});
</script>
Here is what the code does:

  1. Checks for the variable in the .js file, if found the main content on the page is displayed
  2. A function is created and set to execute every 2 seconds
  3. When the function first executes, it checks if the image diplay equals none.
  4. If it does then it'll try to set it to inline, then it'll add ?adblock to the URL for the image
  5. Next time the function is executed, it'll check the display status again, if still none and it detects the adblock string in the URL it'll hide the main content of the site and display the notice that Ad-Block was detected

At this point you could always add some AJAX to post back to one of your scripts to inform the server that Ads are being blocked and you can take what ever action you see fit, logging, blocking in firewall, etc.

True a person could use another Firefox extension to alter the CSS or even the JavaScript but IMO I still think this is a pretty decent solution and it could always be improved upon.

No comments: