Multiple Ad provider's best practices

I’m thinking about a Tuesday blog post on Ad best practices in particular using multiple providers for increasing fill rates etc.

For those who have implemented this, would you mind telling your story here and I’ll try to build what I can into the post.  Code samples of how you chain your vendors would be helpful too?

How do you handle Airplane mode?

Thanks

Rob

Oops wrong topic, I’m terribly sorry. I don’t even know how I got here…

I’m planning on having multiple ad networks (mainly to increase fill rate). I haven’t done it yet, but I came across this post just in time. Are you still planning something for tomorrow?

A better question is, how do you have more than advert per page?

@naveen_pcs, I’ve not gathered any best practice responses to this post yet, so no, it won’t be for tomorrow.  This is not something that I should make up from my limited experience with ads.

@MatthewCharlesHarrop, I would think that most mobile ad providers would not want more than one ad showing at a time.  On phones, you don’t really have the real-estate for it.   I know a lot of web sites run multiple ads, but mobile is a different beast and different expectations.   Now tablets are somewhere in between, and I could see a tablet app maybe offering a couple of different ad spots.  I’ve not tried it, but I suppose you could have ads from different vendors that support positioning banners.  Call ad.show(), call the setProvider() function; call ad.show().  

Hi Rob,

I see you’re no longer planning to write about this for a blog post tomorrow, but I thought I’d share a bit about what I do if you’re thinking about it for the future, or just because it’s an interesting topic to chat about.

The question of how to deal with multiple ad networks is something I batted around for a while before deciding to go “all out” and create a module that gave me maximum flexibility and ease of use going forward.  I’m glad I went in that direction, because the module I ended up writing has been very helpful (now that it’s done).  It lets me remotely enable, disable, and reweight the networks my apps use, and it lets me add new networks in a completely plug-and-play manner.  I’m able to include ad networks through Corona plugins, third-party modules, and REST APIs, all co-existing happily together.  As you said, by integrating with multiple networks, I can ensure high fill rates and also shift among the networks depending on how they’re performing.

The module itself basically consists of: a public interface not unlike the Corona API (straightforward public functions like displayAd, loadAd, isAdLoaded, isAdDisplayed, and closeAd), a mediator whose job it is to take requests from the public interface and try to fulfill them by trying different ad networks one-at-a-time, and mini-modules for each ad network (the plug-and-play part) that present a standard interface to the mediator.

When the module is requested to displayAd or loadAd, the mediator one-at-a-time asks an ad network to fulfill the request (picking the network randomly based on the weighting configuration).  If the first attempt fails, the mediator picks another one based on the remaining networks.  Naturally, to make this cascade work, the implementation for each network has certain callback obligations to the mediator about the status of its attempt to fulfill the request (e.g., if it fails, it needs to callback to the mediator so that the mediator can try another network, and if it succeeds, it needs to callback to the mediator so that the mediator can end the cascade and callback the details to the original caller).

I created the module to behave nicely both on the device and in the simulator.  For each network’s mini-module implementation, I specify certain properties such as what method(s) it can use to render an ad (webView, display object, or other).  When the mediator is picking an ad network to try to fulfill a request, it only picks from among those that can render the ad on the platform the app is running on.  Thus, on the (Windows) Simulator, the only ad networks that the mediator considers are those that can render their ad via a display object, whereas on the device, all networks are considered.

Some of the ad network REST APIs require explicitly specifying the device’s user agent.  There’s no Corona API to get the user agent string, so the module uses a fun little workaround: it loads a simple HTML file in an off-screen webView, and the HTML file runs a Javascript function that gets the user agent string and passes it back in such a way that the webView listener can intercept it.

The module itself is, obviously, not trivial, and it would be difficult to provide code samples.  It’s about 2,500 lines in total, of which about 500 are for the mediator and the public interface and 2,000 are for the mini-modules for each network (12 networks at the moment averaging 200 lines each).  I should mention that it was done entirely in Corona Pro, not Enterprise.

I’m happy to chat in more detail if it’s a topic you’re looking to dive deeper into.  Bottom line, there may be simpler ways of approaching integrating and mediating between multiple ad networks, but I found the approach I took was well worth it in the end for the flexibility it provides.

  • Andrew

PS: You asked about Airplane mode.  I don’t show ads if there is no network connection, either because the device is in Airplane mode or because there’s just no connection.  My view is, if a user wants to avoid seeing ads by putting their device in Airplane mode, and thereby also run the risk of not getting an important text, email, or phone call, that’s they’re prerogative.  To detect if a network connection is available, I use the network status listener when available (iOS) and the approach I described here in other cases: http://forums.coronalabs.com/topic/33356-check-for-internet-connection/.

Just as an FYI, I don’t know when I’ll write this blog post, I’m just gathering info, so it’s by no  means too late to contribute to this discussion.  

Keep it coming!

Andrew that was a fascinating piece.  Looks like you’ve put considerable effort into it.   Are you using the ads.show() to show the ads or are you using the ad providers REST protocols to get them?   How many networks to do you try before giving up?

As for airplane mode, I’ve got a solitare game that I play way too much that seems to be pulling ads from at least 5 different networks, but when you click airplane mode one, you get one ad network and they would somehow have to be local ads since you can’t get them from the server and I’m not sure how they would really work since you can’t click in them to do anything.   I would love to here more from others on this and other topics.

Thanks

Rob

Hi Rob,

Yes, I do use ads.show() for the providers that are integrated with Corona as plugins (e.g., iAds, Vungle, etc.).  But for other networks that I’ve integrated myself using their REST APIs, I call my own custom code to display the ad – which essentially just takes the ad HTML retrieved from the API, saves it to a temporary file, and then displays it in a webView (or on the Simulator, parses the ad HTML to retrieve the image and click URL and displays it using a display object).

As for how many networks the mediator tries before giving up, the basic answer is that it tries all of them, subject to a few constraints.  First, it only tries networks that are enabled in the remote weighting configuration file (i.e., a weight of zero effectively turns off a network).  Second, it only tries networks that meet the parameters of the ad request, i.e., the network can show the type of ad that was requested (banner, rectangle, interstitial, etc.), and the network supports pre-loading the ad before displaying it (if requested).  Third, the mediator stops trying after a timeout specified in the remote weighting configuration.

That’s interesting about what the solitaire game does in airplane mode.  I wonder if the ads you see in airplane mode are house ads for other games by the same developer?  In any case, I agree that it’s a bit strange, since actually tapping the ad wouldn’t go anywhere, since there’s no network connection.

  • Andrew

Oops wrong topic, I’m terribly sorry. I don’t even know how I got here…

I’m planning on having multiple ad networks (mainly to increase fill rate). I haven’t done it yet, but I came across this post just in time. Are you still planning something for tomorrow?

A better question is, how do you have more than advert per page?

@naveen_pcs, I’ve not gathered any best practice responses to this post yet, so no, it won’t be for tomorrow.  This is not something that I should make up from my limited experience with ads.

@MatthewCharlesHarrop, I would think that most mobile ad providers would not want more than one ad showing at a time.  On phones, you don’t really have the real-estate for it.   I know a lot of web sites run multiple ads, but mobile is a different beast and different expectations.   Now tablets are somewhere in between, and I could see a tablet app maybe offering a couple of different ad spots.  I’ve not tried it, but I suppose you could have ads from different vendors that support positioning banners.  Call ad.show(), call the setProvider() function; call ad.show().  

Hi Rob,

I see you’re no longer planning to write about this for a blog post tomorrow, but I thought I’d share a bit about what I do if you’re thinking about it for the future, or just because it’s an interesting topic to chat about.

The question of how to deal with multiple ad networks is something I batted around for a while before deciding to go “all out” and create a module that gave me maximum flexibility and ease of use going forward.  I’m glad I went in that direction, because the module I ended up writing has been very helpful (now that it’s done).  It lets me remotely enable, disable, and reweight the networks my apps use, and it lets me add new networks in a completely plug-and-play manner.  I’m able to include ad networks through Corona plugins, third-party modules, and REST APIs, all co-existing happily together.  As you said, by integrating with multiple networks, I can ensure high fill rates and also shift among the networks depending on how they’re performing.

The module itself basically consists of: a public interface not unlike the Corona API (straightforward public functions like displayAd, loadAd, isAdLoaded, isAdDisplayed, and closeAd), a mediator whose job it is to take requests from the public interface and try to fulfill them by trying different ad networks one-at-a-time, and mini-modules for each ad network (the plug-and-play part) that present a standard interface to the mediator.

When the module is requested to displayAd or loadAd, the mediator one-at-a-time asks an ad network to fulfill the request (picking the network randomly based on the weighting configuration).  If the first attempt fails, the mediator picks another one based on the remaining networks.  Naturally, to make this cascade work, the implementation for each network has certain callback obligations to the mediator about the status of its attempt to fulfill the request (e.g., if it fails, it needs to callback to the mediator so that the mediator can try another network, and if it succeeds, it needs to callback to the mediator so that the mediator can end the cascade and callback the details to the original caller).

I created the module to behave nicely both on the device and in the simulator.  For each network’s mini-module implementation, I specify certain properties such as what method(s) it can use to render an ad (webView, display object, or other).  When the mediator is picking an ad network to try to fulfill a request, it only picks from among those that can render the ad on the platform the app is running on.  Thus, on the (Windows) Simulator, the only ad networks that the mediator considers are those that can render their ad via a display object, whereas on the device, all networks are considered.

Some of the ad network REST APIs require explicitly specifying the device’s user agent.  There’s no Corona API to get the user agent string, so the module uses a fun little workaround: it loads a simple HTML file in an off-screen webView, and the HTML file runs a Javascript function that gets the user agent string and passes it back in such a way that the webView listener can intercept it.

The module itself is, obviously, not trivial, and it would be difficult to provide code samples.  It’s about 2,500 lines in total, of which about 500 are for the mediator and the public interface and 2,000 are for the mini-modules for each network (12 networks at the moment averaging 200 lines each).  I should mention that it was done entirely in Corona Pro, not Enterprise.

I’m happy to chat in more detail if it’s a topic you’re looking to dive deeper into.  Bottom line, there may be simpler ways of approaching integrating and mediating between multiple ad networks, but I found the approach I took was well worth it in the end for the flexibility it provides.

  • Andrew

PS: You asked about Airplane mode.  I don’t show ads if there is no network connection, either because the device is in Airplane mode or because there’s just no connection.  My view is, if a user wants to avoid seeing ads by putting their device in Airplane mode, and thereby also run the risk of not getting an important text, email, or phone call, that’s they’re prerogative.  To detect if a network connection is available, I use the network status listener when available (iOS) and the approach I described here in other cases: http://forums.coronalabs.com/topic/33356-check-for-internet-connection/.

Just as an FYI, I don’t know when I’ll write this blog post, I’m just gathering info, so it’s by no  means too late to contribute to this discussion.  

Keep it coming!

Andrew that was a fascinating piece.  Looks like you’ve put considerable effort into it.   Are you using the ads.show() to show the ads or are you using the ad providers REST protocols to get them?   How many networks to do you try before giving up?

As for airplane mode, I’ve got a solitare game that I play way too much that seems to be pulling ads from at least 5 different networks, but when you click airplane mode one, you get one ad network and they would somehow have to be local ads since you can’t get them from the server and I’m not sure how they would really work since you can’t click in them to do anything.   I would love to here more from others on this and other topics.

Thanks

Rob

Hi Rob,

Yes, I do use ads.show() for the providers that are integrated with Corona as plugins (e.g., iAds, Vungle, etc.).  But for other networks that I’ve integrated myself using their REST APIs, I call my own custom code to display the ad – which essentially just takes the ad HTML retrieved from the API, saves it to a temporary file, and then displays it in a webView (or on the Simulator, parses the ad HTML to retrieve the image and click URL and displays it using a display object).

As for how many networks the mediator tries before giving up, the basic answer is that it tries all of them, subject to a few constraints.  First, it only tries networks that are enabled in the remote weighting configuration file (i.e., a weight of zero effectively turns off a network).  Second, it only tries networks that meet the parameters of the ad request, i.e., the network can show the type of ad that was requested (banner, rectangle, interstitial, etc.), and the network supports pre-loading the ad before displaying it (if requested).  Third, the mediator stops trying after a timeout specified in the remote weighting configuration.

That’s interesting about what the solitaire game does in airplane mode.  I wonder if the ads you see in airplane mode are house ads for other games by the same developer?  In any case, I agree that it’s a bit strange, since actually tapping the ad wouldn’t go anywhere, since there’s no network connection.

  • Andrew