How to Optimize Client Side Ad Loading

This post is also available in: Russian

размещение баннеров

In a previous post, we discussed how to configure OpenX Ad Server to maximize its performance. However banner load performance is not just a server issue. In this article, we would like to brief you on the client side methods to attain the same goal.

The main issue with client side banner performance is that in most advertising systems, including OpenX, the banner code is often directly embedded into the page by the

1
script

tag and the

1
document.write

function. As a result, the banner code loads and runs in a synchronous mode, so no other page elements are shown before the banner is loaded. For instance, if your banner is at the top of the page, and ad server response is very slow, then the whole page will load at a substantial delay.

Fortunately, there are several options to solve the issue. The easiest way is to upload banners within

1
IFRAME

. However, this option has several drawbacks:

  • The banners that resize or redesign the current page are not supported.
  • The ad server will be unaware of the real referrer page browsed by the user.
  • The context of the page displaying the banner is not analyzed, which affects ad relevance.

To overcome

1
IFRAME

limitations, but still upload banners asynchronously, we can use a jQuery-plugin, LazyLoad Ad. It intercepts

1
document.write

, converting synchronous ad code calls to asynchronous. In addition, it does not load all banners at once, but only those currently scrolled to. On the plugin site you can find examples of using LazyLoad Ad with the code of various advertising systems.

Here we would like to show how you can use the plugin to load graphic banners asynchronously from OpenX. Typically, the ad code looks like this (we use Smarty substitution templates):

<script type=’text/javascript’><!–//<![CDATA[
var m3_u = (location.protocol==https:?https://{$ad_base}/ajs.php:http://
{$ad_base}/ajs.php
);
var m3_r = Math.floor(Math.random()*99999999999);
if (!document.MAX_used) document.MAX_used = ,;
document.write (
"<scr"+"ipt type=’text/javascript’ src=’"+m3_u);
document.write (
"?zoneid={$zone_id}");
document.write (
&amp;cb= + m3_r);
if (document.MAX_used != ,) document.write ("&amp;exclude=" +
document.MAX_used);
document.write (document.charset
? &amp;charset=+document.charset : (document.characterSet ? &amp;charset=+document.characterSet : ));
document.write (
"&amp;loc=" + escape(window.location));
if (document.referrer) document.write ("&amp;referer=" +
escape(document.referrer));
if (document.context) document.write ("&context=" + escape(document.context));
if (document.mmm_fo) document.write ("&amp;mmm_fo=1");
document.write (
"‘><\/scr"+"ipt>");
//]]>–></script><noscript><a href=’http://{$ad_base}/ck.php?n=a1eaf622&amp;
cb={math equation="rand(1,10000000)"}’ target=’_blank’><img src=’http://{$ad_base}/avw.php?zoneid={$zone_id}&amp;cb={math equation="rand(1,10000000)"}&amp;n=a1eaf622′ border=’0′ alt=” /></a></noscript>

To prepare this code for LazyLoad Ad, let’s modify it as follows:

  1. 1. Remove the
    1
    noscript

    tag. In case scripting is not supported by the browser, advertising will not load anyway.

  2. 1. Change the code to call the
    1
    document.write

    function only once, since otherwise the ad code may be truncated by Google Chrome.

  3. 1. Put the JavaScript
    1
    code

    inside the code tag, as required by the plugin.

  4. 1. Wrap the resulting ad code by
    1
    div

    with the

    1
    lazyload_ad

    class, to invoke the plugin using this selector.

This will give:

<div class="lazyload_ad">
<code type="text/javascript"><!–
var m3_u = (location.protocol==’https:’?’https://{$ad_base}/ajs.php’:’http://{$ad_base}/
ajs.php’);
var m3_r = Math.floor(Math.random()*99999999999);
if (!document.MAX_used) document.MAX_used = ‘,’;
document.write ("<scr"+"ipt type=’text/javascript’ src=’"+m3_u
+"?zoneid={$zone_id}"
+’&amp;cb=’ + m3_r
+(document.MAX_used != ‘,’ ? "&amp;exclude=" + document.MAX_used : ”)
+(document.charset ? ‘&amp;charset=’+document.charset : (document.characterSet ? ‘&amp;charset=’+document.characterSet : ”))
+"&amp;loc=" + escape(window.location)
+(document.referrer ? "&amp;referer=" + escape(document.referrer) : ”)
+(document.context ? "&context=" + escape(document.context) : ”)
+(document.mmm_fo ? "&amp;mmm_fo=1" : ”)
+"’><\/scr"+"ipt>");
//
–>
</code>
</div>

Put the resulting ad code to your webpage. Add the following call to the JavaScript:

$(document).ready( function() {
$(
.lazyload_ad).lazyLoadAd({
forceLoad:
true
});
});

While running the plugin, we found the following issues in its implementation:

  • The above discussed issue with incomplete output of the advertising code in Google Chrome.
  • Lazy loading of banners is enabled by default, but runs incorrectly, so we had to disable it using
    1
    forceLoad: true

    .

  • When loading a page via a narrowband connection, two banners can load to the same banner space. This problem has not been solved by developers yet.

Video Advertising

With video advertising, the situation is slightly different: the logic of loading ads and overlays is implemented by a Flash player, and the player developer must ensure asynchronous ad loading without interrupting display of the main content. In this case, ad insertion points will be slightly shifted forward from the needed points, and pre-roll may become mid-roll, and post-roll will have to be initiated before the end of playback. This is not a problem in terms of implementation, but you’d have to explain all this to advertisers.

How to Bypass Ad Filters

There is another issue with client side ad load which is faced by any Web advertiser. Those are different ad blockers like AdBlock, one of the most popular Firefox extensions. Most often they filter ads by URL, less often – by standard sizes. In any case, they are intercepting all HTTP requests sent by the user browser. What can we do with this? If you use your own ad server, the most evident solution is to change ad request URLs so that they do not match ad blocker URL lists. Further, you can come up with an intricate scheme of URLs that change dynamically or mimic useful content. But in most cases, experienced users will have no problem adding your uncommon ad URLs to their filters.

Another, more efficient, way to bypass ad filters is to proxy ad requests inside RTMP. To do this, on the Adobe Flash Media Server side you’ll have to enable a special proxy plugin to provide communication between the RTMP client and the ad server. On the client-side, all ad requests must be initiated by the Flash Player. This method is very convenient for video ad load, but you can also load the common graphic banners using an external JavaScript interface to interact with Flash. As far as we know, currently there are no advertising filters affecting interaction within the RTMP streams. Locking of RTMP at TCP port layer will not work, if RTMP also transmits useful video content, or if video is streamed over RTMPT on port 80. However this method has its downsides: dependence on Flash and paid Adobe FMS, the need to develop a proxy plugin for the server side and a special Flash object on the client side.

Leave a Reply