Ambassador House Ad Server

Table of Contents

Introduction

Welcome to the documentation for implementing an internal ad server. At Ambassador I use Google DFP to help us manage our ad inventory, and for optimizing our ads based on performance. This gives us lots of additional control over serving our ads, and provides for a modular employee design structure. An ad manager requires no access to the blog, and a content manager requires no access to the ad serving technology.

Ad Inventory

Right Hand Ads

There are two primary placements for right hand ads, with plans to add more based on context in the future. They are on the home page, and on single post views. Eventually I will split these into 4 based on our marketing personas.

RH Ad Sizes

In order for our ads to behave responsivly I need to create 3 seperate ad sizes based on desktop-large, desktop, and tablet.

  • Large Desktop = 330x275. Visible on viewports larger than 1200px wide. The height is adjustable, however the width is required in order to maximize the display inside the text widget. The size 330x275 maintains the same aspect ratio of a default sized 300x250px ad.
  • Desktop = 260x217. Visible on viewports betIen 980px and 1200px in width. The height is adjustable for this size as Ill, hoIver the width is required to maximize the display size inside the text widget. The size 260x217 maintains the aspect ratio of a default sized 300x250px ad.
  • Tablet = 188x156. Visible on viewports betIen 980px and 768px. The height is also adjustable. The width is fixed and is engineered in order to maximize display in the text widget. 188x156 maintains the aspect ratio of a default sized 300x250px ad.

DFP ads dont behave responsively (they will not resize on their own) so I need to include all 3 ad sizes in the text widget and then show/hide them based on the size of the viewport. That also means that I will need to create each adsize in our DFP inventory settings and include all three inside our text-widgets.

RHS Ad Tables

Large-Desktop Desktop Tablet
Size 330x275 260x217 188x156
CSS Class .visible-large-desktop .visible-desktop .visible-tablet
Homepage sidebar_home_large_desktop sidebar_home_desktop sidebar_home_tablet
Single Post sidebar_post_large_desktop sidebar_post_desktop sidebar_post_tablet

Leaderboard Ads

Introduction to DFP

I have selected Google DoubleClick for Publishers (DFP) to act as our ad server. When choosing an ad server I had several factors to consider, such as:

  • Hosted/SaaS
  • Pricing
  • Ease of Use
  • Flexibility/Power
  • Support

I ultimately decided to settle on Google DFP because it provided the basic requirement that I needed (the ability to serve house ads). Google DFP is also backed by the Google machine, and so I have faith in their algorithms for serving ads based on performance. Google DFP is also hosted, and free (for serving house ads). An initial negative was that it is one of the more unwieldy and cumbersome option. This is mostly caused by the large number of options and it's primary function for serving non-display When researching an ad server to use I reviewed

  • OpenX
  • Adzerk
  • DFP
  • Revive Adserver

Adzerk was a good choice early on, however they have transitioned their business model to requiring a minimum monthly spend of $1,000. Since we are going to be primarily serving house ads, we will never hit $1,000 spend.

What is an ad server

Good question. Perhaps it is easier to explain what an ad server is with a quick example.

Imagine that you have a blog, and it has recently become very popular. When you first started to monetize your blog you threw a few Adsense ads up there. Recently, however, you have been getting a ton of traffic, and you are tired of paying such a large percentage to google for the adsense ads. Furthermore, the ads that Adsense were serving were very generic. Since your blog is very specific to your audience, you would rather serve ads that are more relevant to your users first.

Finally, a few of the big players in your industry have reached out to you, and are interested in advertising on your site directly. They want to cut out the middleman.

What you need is an ad server. An ad server is a way for you to act like your own adsense for just your site. You can sell ads directly to advertisers in your industry. You can sell your ad space based on a number of factors. For example you could offer an exclusive deal with an advertiser, where they are the only ads that will be served over a given time period. You could also sell a set number of impressions to your advertisers, and their ads will be rotated evenly with other advertisers until the number of impressions you have sold expires.

If you setup your own ad server, you are in control of these settings, and can run your ads however you see fit.

Lets continue to think through this current situation though. Say you generate around 100,000 impressions per month on your blog. To play it safe, you could sell 9 packages of 10,000 impressions to 9 different advertisers. What happens with the difference?

You are generally presented with 2 options:

  • Fallback to a generic ad pool (like adsense)
  • Serve house ads

It is that second one that interests us. House ads are ads that are owned by the "house," or the publisher. If you have ever driven down the highway and seen a billboard that says "advertise here" you have come across a house ad. House ads are a way to fill in unused ad inventory (impressions) with ads for more ads, or for internal products and services. For a blog that is monetized primarily through advertising revenue this might be a place to advertise more ads ("advertise here"). It could also be a place to sell your ebook, or get enrollment into your class.

For us its a place to leverage our calls to action, to try and convert passive readers into leads.

**By building our own ad server, we can rotate our creative assets. We can automatically serve our best performing creative assets to our readers, we can efficiently prevent banner blindness, most ad servers allow you to set a per user frequency cap, ensuring that your visitors will see the full range of your cta creative assets.

Why DFP

After reviewing several other ad servers out there, it appeared that Google Doubleclick for Publishers was our best option. Although it is a bit more unruly than other options (adzerk was the easiest):

  • I trust google's algorithms for serving top performing ads first.
  • It should be familiar to a broad swath of advertisers.
  • It is cumbersome because it is powerful.
  • House ads are supported.
  • There are powerful custom targeting options available.
  • It is completely free. Other services require a minimum spend/month.
  • It is hosted. I dont want to deal with servers.
  • It will be around for a while. I don't have to worry about it disappearing.

Working inside DFP

One of the downsides of DFP is that it is harder to use than some of the alternatives. Don't stress. I gotchu.

The most confusing part of the process is that you are acting as both the advertiser and the publisher. The line in the sand that defines that distinction is more blurry when you are wearing both hats at once.

The easiest way to split the line between publisher and advertiser is to focus on the two tabs at the top; Inventory and Orders.

Inventory is where you manage your ad inventory. It is where you manage the locations on your website where the ads will appear.

Orders is where you would manage your advertisers. Since you are your advertiser this is where you manage your creative assets.

Important!!!!!

Make sure to turn off Adsense serving. By default, Adsense serving remains ON and will display Adsense ads for any unused inventory. Adsense ads are higher in the ad food-chain than House ads, and will take a priority over any unused inventory.

In order to turn off Adsense by default navigate to the Network Settings menu item from the Inventory tab.

Make sure that Deafult AdSense inventory settings is unchecked. You can double check (and should double check) that AdSense is disabled when you create a new ad unit.

Installing ads on the blog

In order to get started, you need to define each location on the blog where your ads will appear. This is not thing as defining each ad size. For example if you have 3 ads in your right hand sidebar all 300x250 you would want to define 3 ad units in your inventory (top, middle, bottom, etc...)

Get started by creating a new ad unit. You can do this from the Ad units menu item in the Inventory tab.

Build out one of the ads that we previously defined in one of our RHS Ads Table if they arent already built out already. Be sure to add a semantic description and a size that matches the ad tables.

Installing the tracking tags

Once you have created all of your ad units, you will need to add them to your blog so that your ads will begin showing. This is relatively easy to do, and requires adding 3 pieces of javascript to your site.

  • The tracking init
  • The ad unit inventory
  • The specific div tags where your ads will be rendered.

Get started by navigating to the Generate tags menu item in the Inventory tab. Choose which ads you are choosing to include and then click on the generate tags button. You will be presented with two windows of code to place on your site, split into 3 pieces.

The tracking init:

<script type='text/javascript'>
var googletag = googletag || {};
googletag.cmd = googletag.cmd || [];
(function() {
var gads = document.createElement('script');
gads.async = true;
gads.type = 'text/javascript';
var useSSL = 'https:' == document.location.protocol;
gads.src = (useSSL ? 'https:' : 'http:') + 
'//www.googletagservices.com/tag/js/gpt.js';
var node = document.getElementsByTagName('script')[0];
node.parentNode.insertBefore(gads, node);
})();
</script>

The ad unit inventory:

<script type='text/javascript'>
googletag.cmd.push(function() {
googletag.defineSlot('/107821268/sidebar_home_desktop', [260, 217], 'div-gpt-ad-1395263879880-0').addService(googletag.pubads());
googletag.defineSlot('/107821268/sidebar_home_large_desktop', [330, 275], 'div-gpt-ad-1395263879880-1').addService(googletag.pubads());
googletag.defineSlot('/107821268/sidebar_home_tablet', [188, 156], 'div-gpt-ad-1395263879880-2').addService(googletag.pubads());
googletag.defineSlot('/107821268/sidebar_post_desktop', [260, 217], 'div-gpt-ad-1395263879880-3').addService(googletag.pubads());
googletag.defineSlot('/107821268/sidebar_post_large_desktop', [330, 275], 'div-gpt-ad-1395263879880-4').addService(googletag.pubads());
googletag.defineSlot('/107821268/sidebar_post_tablet', [188, 156], 'div-gpt-ad-1395263879880-5').addService(googletag.pubads());
googletag.pubads().enableSingleRequest();
googletag.enableServices();
});
</script>

The specific div tags where your ads will be rendered.

<!-- sidebar_home_desktop -->
<div id='div-gpt-ad-1395263879880-0' style='width:260px; height:217px;'>
<script type='text/javascript'>
googletag.cmd.push(function() { googletag.display('div-gpt-ad-1395263879880-0'); });
</script>
</div>

<!-- sidebar_home_large_desktop -->
<div id='div-gpt-ad-1395263879880-1' style='width:330px; height:275px;'>
<script type='text/javascript'>
googletag.cmd.push(function() { googletag.display('div-gpt-ad-1395263879880-1'); });
</script>
</div>

<!-- sidebar_home_tablet -->
<div id='div-gpt-ad-1395263879880-2' style='width:188px; height:156px;'>
<script type='text/javascript'>
googletag.cmd.push(function() { googletag.display('div-gpt-ad-1395263879880-2'); });
</script>
</div>

<!-- sidebar_post_desktop -->
<div id='div-gpt-ad-1395263879880-3' style='width:260px; height:217px;'>
<script type='text/javascript'>
googletag.cmd.push(function() { googletag.display('div-gpt-ad-1395263879880-3'); });
</script>
</div>

<!-- sidebar_post_large_desktop -->
<div id='div-gpt-ad-1395263879880-4' style='width:330px; height:275px;'>
<script type='text/javascript'>
googletag.cmd.push(function() { googletag.display('div-gpt-ad-1395263879880-4'); });
</script>
</div>

<!-- sidebar_post_tablet -->
<div id='div-gpt-ad-1395263879880-5' style='width:188px; height:156px;'>
<script type='text/javascript'>
googletag.cmd.push(function() { googletag.display('div-gpt-ad-1395263879880-5'); });
</script>
</div>

Depending on your blog CMS, or plugins/themes etc. The next steps will vary. Also the included code is representative of our ad units, and will not work on your site. You will need to generate your own code from the Google DFP interface.

Our theme has a settings area where we are able to ad JavaScript to our Head tags. Most modern WordPress themes have a feature like this, and if not you can easily install a plugin that does so. Be sure to review if your theme recommends you including the <script></script> tags or not. In our case, we don't need to place the script tags.

Place both the tracking init and the ad unit inventory in this area.

Next you are going to want to place each ad unit where you want each ad to appear. For us, that's in the right-hand sidebars, in a text widget (that accepts html).

CSS adjustments

In order to show the right-sized ad for the right-sized viewport, we need to adjust our ad unit tags. Our blog loads bootstrap 2.3.2, so we are given a few helper classes that we can load. Unfortunatly one for the large-desktop is missing, so we will need to adjust for that. I'll cover that a bit further down.

Take a look at the first option. This is the snippet we will add in order to show our 260x217 desktop-sized advertisement. Notice how we added class="visible-desktop"?

<!-- sidebar_home_desktop -->
<div id='div-gpt-ad-1395263879880-0' style='width:260px; height:217px;' class="visible-desktop">
<script type='text/javascript'>
googletag.cmd.push(function() { googletag.display('div-gpt-ad-1395263879880-0'); });
</script>
</div>

We're gonna want to do that for each one of our ads. For more information on the Bootstrap 2 utility classes check out their documentation.

Here's all of our ad units with the appropriate utility classes added. Pay attention to the .visible-large-desktop. That doesn't exist in Bootstrap so we'll need to create it ourselves. Then just install each set of ad units on the page where they belong sidebar_home_* on the homepage sidebar text widget, sidebar_post_* on the sidebar text widgets. Also due to the ordering of our css files, we need to call 3 hidden viewport classes instead of one visible class on our largest size.

<!-- sidebar_home_desktop -->
<div id='div-gpt-ad-1395263879880-0' style='width:260px; height:217px;' class='hidden-desktop-large hidden-tablet hidden-phone'>
<script type='text/javascript'>
googletag.cmd.push(function() { googletag.display('div-gpt-ad-1395263879880-0'); });
</script>
</div>

<!-- sidebar_home_large_desktop -->
<div id='div-gpt-ad-1395263879880-1' style='width:330px; height:275px;' class='visible-desktop-large'>
<script type='text/javascript'>
googletag.cmd.push(function() { googletag.display('div-gpt-ad-1395263879880-1'); });
</script>
</div>

<!-- sidebar_home_tablet -->
<div id='div-gpt-ad-1395263879880-2' style='width:188px; height:156px;' class='visible-tablet'>
<script type='text/javascript'>
googletag.cmd.push(function() { googletag.display('div-gpt-ad-1395263879880-2'); });
</script>
</div>

<!-- sidebar_post_desktop -->
<div id='div-gpt-ad-1395263879880-3' style='width:260px; height:217px;' class='hidden-desktop-large hidden-tablet hidden-phone'>
<script type='text/javascript'>
googletag.cmd.push(function() { googletag.display('div-gpt-ad-1395263879880-3'); });
</script>
</div>

<!-- sidebar_post_large_desktop -->
<div id='div-gpt-ad-1395263879880-4' style='width:330px; height:275px;' class='visible-desktop-large'>
<script type='text/javascript'>
googletag.cmd.push(function() { googletag.display('div-gpt-ad-1395263879880-4'); });
</script>
</div>

<!-- sidebar_post_tablet -->
<div id='div-gpt-ad-1395263879880-5' style='width:188px; height:156px;' class='visible-tablet'>
<script type='text/javascript'>
googletag.cmd.push(function() { googletag.display('div-gpt-ad-1395263879880-5'); });
</script>
</div>

Adding some Bootstrap 2 helper classes to the css

As I previously mentioned, bootstrap doesn't include the css we need to hide our largest sidebar ad size. So we need to create our .visible-desktop-large helper class. If you are not using Bootstrap 2 you can ignore this section.

/* our largest viewport */
@media (min-width: 1200px) {
  .visible-desktop-large {
    display: inherit !important;
  }
  .hidden-desktop-large {
    display: none !important;
  }
  .visible-desktop {
    display: none !important;
  }
  .hidden-desktop {
    display: inherit !important;
  }
}

/* set up our viewport from desktop (980px) - large-desktop (1200px) */
@media (min-width: 980px) and (max-width: 1200px) {
  .visible-desktop-large {
    display: none !important;
  }
  .hidden-desktop-large {
    display: inherit !important;
  }
}

/* tablets */
@media (min-width:768px) and (max-width: 979px) {
  .visible-desktop-large {
    display: none !important;
  }
  .hidden-desktop-large {
    display: inherit !important;
  }
}

/* phones */
@media (max-width: 767px) {
  .visible-desktop-large {
    display: none !important;
  }
  .hidden-desktop-large {
    display: inherit !important;
  }
}

and minified

@media (min-width:1200px){.visible-desktop-large{display:inherit!important}.hidden-desktop-large,.visible-desktop{display:none!important}.hidden-desktop{display:inherit!important}}@media (min-width:980px) and (max-width:1200px){.visible-desktop-large{display:none!important}.hidden-desktop-large{display:inherit!important}}@media (min-width:768px) and (max-width:979px){.visible-desktop-large{display:none!important}.hidden-desktop-large{display:inherit!important}}@media (max-width:767px){.visible-desktop-large{display:none!important}.hidden-desktop-large{display:inherit!important}}

Creating Orders, Line Items, and Ads

Great! By now you should have created your ad units inside DFP and added them to the blog. If you did everything correctly you should be seeing big empty spaces inside your content where the ads should be showing. Investigate them with Chrome Developer Tools and you'll see that they are rendering your empty ads. If you did the responsive part correctly you should only see one ad for each viewport size. If you are seeing more than one add you did not configure your css correctly.

Everything kosher? Cool. Lets upload our creatives so that we can really put this thing to use. We'll be wearing out advertiser hat for this portion, so navigate over to the Orders tab and click on New order.

If you are used to working inside AdWords you can consider [Orders] analogous to an ad group. Orders are placed by advertisers, and contain many line items. When you create your first Order the DFP interface will present you with the option to create your first line item as well. Feel free to use this hierarchy the way you'd like to keep your ads organized.

If this is your first time creating an order you wont have any companies to assign the order to. Since we will only be running house ads, you will want to create an advertiser that is yourself. Make sure to save the type as a House Advertiser for your own company. Since we are only running house ads we can ignore all the optional order fields.

For your first line item its a good idea to use a generic set of creatives. We've seen that the empty ads don't look ideal, so set the start time to immediately and the end time to unlimited. This will ensure that at least some of our ads will always be filling our inventory.

One of the cool things we can do by using an ad server to power our creative assets is set a per-user frequency cap, ensuring that our frequent readers will be delivered a variety of creative assets and calls to action. We can also adjust the delivery of our ads to rotate them on an optimized basis, giving higher performing ads priority.

When you set your inventory sizes in the first section of your new line item DFP automatically filtered your library of ad units to only display those that fit your criteria. For our initial setup I have titled our line item "Single Post Ads" and intend on using this line item for displaying our single post ads. Therefor I will include our sidebar_post_desktop, sidebar_post_large_desktop and sidebar_post_tablet ad units.

Finally, click "Save and... Upload Creatives" to continue uploading our creative assets.

One of the powerful things about working with an ad server is the ability to upload much more than a static image file. You can upload many types of creative assets. Animated gifs, flash files, etc... For now though we will stick to our simple static image files.

For each ad, set a click-through URL. Be sure to include your utm_ tracking parameters so that you can measure each order (campaign) and line item (ad group) inside google analytics or other analytics tool.

Save your creatives.

Congratulations! You are almost ready to begin serving your house ads. The last step is to approve the order. Navigate to the order page and note the status of your line items.

Status Meaning
Delivering The line item is serving ad impressions.
Ready Activated but not yet delivering.
Paused Delivery has been paused. Resume the line item to continue ad delivery.
Needs Creatives Line item has been created but creatives need to be added.
Inventory Released Line item has been cancelled and inventory is now available to book.
Pending approval Requires approval from account administrator to deliver.
Completed Line item end date has been reached.
Disapproved Line item was disapproved by an account administrator.
Draft/Unreserved Line item is part of an order that has not been approved.
Canceled Line item is canceled.
Archived Line item is inactive and hidden from default views.

If you just created your line item, its status is probably draft. Go ahead and approve the order and activate the line item. The line item's status should now change to ready.

Continue adding line items until all of your ad units are serving ads.

GPS ring

/* css for gps_ring on cta */
.gps_ring {
    z-index: -100;
    border: 3px solid #7fc4e2;
    -webkit-border-radius: 30px;
    height: 28px;
    width: 28px;
    margin: -16px;
    -webkit-animation: pulsate 1s ease-out;
    -webkit-animation-iteration-count: infinite; 
    opacity: 0.0;
}
.gps_ring + img {
    opacity: .99;
}

@-webkit-keyframes pulsate {
    0% {-webkit-transform: scale(0.1, 0.1); opacity: 0.0;}
    50% {opacity: 1.0;}
    100% {-webkit-transform: scale(1.2, 1.2); opacity: 0.0;}
}
/* end gps_ring */

Glossary

  • Orders
  • Line Items
  • Inventory:
  • Placements:
  • Orders:
  • Line Items:
  • Custom Targeting: Read more.
  • House Ads: House ads are a special type of ad that are traditionally used for filling unused inventory on an advertising-monetized blog with in-house (get it) ads. They still get a lot of the same benefits of traditional ads (optimized for CTR, etc...) but are free, and remove some of the $ features.
  • Banner Blindness: Banner blindness is a phenomenon in web usability where visitors to a website consciously or subconsciously ignore banner-like information, which can also be called ad blindness or banner noise. Read more.