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.
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/.