Rotating different ads in one spot is an important feature when selling ads with limited impressions or when testing different ads against each other. One of the biggest challenges when doing this kind of magic are cached websites. In this article you are going to learn how to rotate ads using plain JavaScript.

On a cached website the same content and code is delivered to every visitor. Server side programing languages are not helping us here to make conditions for rotating ads.

If you are not a coder or need advanced features, you can use the cache-busting and visitor conditions in Advanced Ads Pro to dynamically rotate ads and also create conditions for ads.

Update: This article also mentions OIO Publisher, a now abandoned ad management plugin.

I recently solved an interesting puzzle to serve two ads with different ad weights on a cached website and wanted to share the solution with you. If you want, you can call this a cheap frequency cap in plain JavaScript.

I am not going to conceal that the use of an ad server would have been an option here too, but I prefer to use slim solutions in case of small tests or only a few sold ads.

Btw, if you want to build an ad rotation on a website that doesn’t use cache or you don’t need the ads to rotate all the time, try my ad management plugin Advanced Ads.


In this case we are not just talking about a simple ad rotation. My client had sold an ad that should be delivered equally over a given period.

The website cache was a problem here because we were not able to use PHP.

JavaScript based ad rotation

The whole code looks like this. I am going to explain it in more detail below.

<div id="the-ad-box"></div>
var randnr = Math.floor(Math.random() * 2);
if(randnr > 0){
    var s = document.createElement('script');
    src = '';
    s.setAttribute( 'src', src );
    s.setAttribute( 'type', 'text/javascript' );
    document.getElementById('the-ad-box').appendChild( s );
} else {
    // alternative ad code comes here 
</script>Code language: HTML, XML (xml)

 Code breakdown

First, we need an empty container to inject the script tag that we create below into. Nothing magical here.

<div id="the-ad-box"></div>Code language: HTML, XML (xml)

Next, we want to rotate both ads with an equal chance, so we generate a random integer number, in this case 0 or 1.

var randnr = Math.floor(Math.random() * 2);
if(randnr > 0){Code language: JavaScript (javascript)

When using if(randnr > 0){ in the second line, we practically set an ad weight. With 0 and 1 and the check if the random number is greater than 0, we have a 50% chance of the next banner to appear. You can temper with these two lines to adjust your ad weight. I am also going to give you a more advanced example below.

The original code that loads ads dynamically from the OIO Publisher plugin looks like this:

<script type="text/javascript" src=""></script>Code language: HTML, XML (xml)

This is where the magic begins. In order to load the ad tag from OIO Publisher only in case it was selected, I had to mask it. Just so that you get the idea and are able to use your own ad code here.

var s = document.createElement('script');
src = '';
s.setAttribute( 'src', src );
s.setAttribute( 'type', 'text/javascript' );
document.getElementById('the-ad-box').appendChild( s );Code language: JavaScript (javascript)

The next line simply includes the script code we dynamically generated into the ad container we placed at the beginning of the code.

document.getElementById('the-ad-box').appendChild( s );Code language: JavaScript (javascript)

What is an ad rotation without at least on alternative, right? So the else  statement contains this alternative. I left it open here, but we used it to deliver AdSense or Criteo ads. Anyway, you could also leave this part empty and so deliver the original ad only every second time.

} else {
    // alternative ad code comes here 
}Code language: JavaScript (javascript)

Where to put this code?

At first, I thought I am going to be smart and serve the code as an ad itself, but OIO Publisher seemed to filter it. Since some of the ads were delivered in the sidebar, I was just copying the code into a text widget. For another example, I had to write the code into a template file. If this would have been a permanent setup, I might as well have used Advanced Ads to deliver this code.

Btw, keep in mind to always check the site output with firebug or another javascript console open to see if any error comes up.

Limiting ad views per day – a cheap frequency cap

Frequency capping is when setting a limitation to ad views of a specific campaign. This can be per day or per user, or even for total impressions. In my specific example my client sold about 12,500 ad impressions per week while having 100,000 ad impressions in this spot altogether. Since the advertiser asked him to distribute the ad impressions equally over the whole week and OIO Publisher doesn’t allow this, I had to come up with the solution above.

At the end, I wanted to give those of you in the same position a quick look into how I calculated the impressions at set the ad weight accordingly.

  1. I had to know the number of total impressions and the period, 100,000 and 7 days.
  2. I needed to calculate the ratio of sold ads to total impressions: 12,500 to 100,000 is 1/8, so one out of eight page impression should deliver the sold ad
  3. adjust the random number and check from above like this
var randnr = Math.floor(Math.random() * 8);
if(randnr == 0){Code language: JavaScript (javascript)

Since the random number can be 0 to 7, checking against a specific numbers results in a chance of 12,5% (1/8) to show up.

Using the ad tag from OIO Publisher in my example above allowed us to make use of the stats included there, so we can check every now and then if the random choice of the ad resulted in a constant delivery or we had to adjust the proportions. In fact, I created a checklist we can use to check delivered ads against the number we sold. It looks pretty much like this:

dayunsold inventory

With this list we only need a quick look at the ad stats to see if our inventory is going to be sold in time or even sold out earlier. If so, I would quickly adjust the frequency. At day 8, so after the whole week, the number of unsold inventory should be 0.

The Author