Share Your Code

Ad Manager for Corona

Posted by deniz, Posted on January 26, 2012, Last updated February 16, 2012

********************************************************************************************************
This module is obsolete. Please use Ad Mediator for Corona instead. It is an ad mediation module very much like Adwhirl.

Ad Mediator for Corona: http://developer.anscamobile.com/code/ad-mediator-corona
********************************************************************************************************

version 1.1 is out! New Feature: ad rotation!

By using this simple module, you can configure ad network parameters on the fly. You can switch ad networks without updating your apps, change all supported ad network variables, display your own ads with house ads functionality, and even rotate your own ad stream without a hassle. All you need is a simple ad configuration text file sitting on your web space.

Example Usage

1) require ad manager source code first:

1
require("admanager.lua")

2) initialize ad manager with the url of configuration file:

1
initAds("http://myserver.com/ads_config.txt")

3) start displaying ads:

1
showAds()

4) you can also hide ads whenever you wish:

1
hideAds()

Here is a sample ads_config.txt file:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
{
   "ads" : {
      "enabled"  : true,
      "network"  : "inmobi",
      "id"       : "4028cba631d63df10131e1d4650600cd",
      "format"   : "banner320x48",
      "x"        : 0,
      "y"        : 430,
      "interval" : 60,
      "test"     : true
   },
   "houseads" : {
      "enabled"   : true,
      "x"         : 160,
      "y"         : 455,
      "scale"     : 1.0,
      "rotation" : true,
      "duration" : 60,
      "banners"   : [
         {
            "imageUrl"  : "http://yourserver.com/housead1.jpg",
            "targetUrl" : "http://bit.ly/campaign-housead1"
         },
         {
            "imageUrl"  : "http://yourserver.com/housead2.jpg",
            "targetUrl" : "http://bit.ly/campaign-housead2"
         },
         {
            "imageUrl"  : "http://yourserver.com/housead3.jpg",
            "targetUrl" : "http://bit.ly/campaign-housead3"
         }
      ]
   }
}

Configuration file is a simple json encoded text file. It has 2 sections; ads and houseads.

ads section:
In this section you configure ad network parameters. network is the name of your ad network ie: inmobi or inneractive, id is the key given by your ad network after registering a new application, format is the ad format strings specific to your ad provider. Setting "enabled" to false will also disable this section. x,y are coordinates of your ad placement, interval is ad refresh interval in seconds. Please check Ansca's banner ad guide for indepth explanation of all the parameters.

houseads section:
In this section you configure house ads parameters. Instead of using some sort of ad network, you can show your own banners with house ads functionality. x,y are house ad banner placement coordinates, scale is display object scaling factor (use 1.0 for all practical purposes), set rotation parameter true to enable banner rotation functionality. Duration is banner rotation interval in seconds. You should fill banners array with your house ad banner image and click target urls. In the example above, I defined 3 house ads, and enabled ad rotation functionality with 60 seconds interval. So; each of my banners will be shown for 60 seconds.

If you plan to use both ads and houseads please keep in mind that; ads from networks always show in front of your house ads. And remember; if you enable ads section, your house ads will not be clickable, even there are no network ads are visible. sorry for that :/

(*) A Note about touch events: Event the latest daily build of Corona (731) has a bug which prevents touch events on background banner objects when you place ads on top of those objects even ads are empty. In some rare cases your users can click those banners, but most of the time this function is broken. But still you can show your banners :)

Some Final Notes on Usage

+ You can call initAds() function multiple times. Every call re-initializes ad manager with latest fresh parameters from your ad configuration script. I personally call this function at the startup and also from an "applicationSuspend" event listener. This way; your users always get the ad parameters you updated recently.
+ You can do some fancy things by using a programmable configuration file. For example; one of my projects uses a php script as the configuration url. I also have my own configuration web panel which uses mysql to store ad configuration parameters. A fully configurable, database backed ad management system, yay! :)
+ I recommend using some sort of url tracking service to count clicks on your house ads. I prefer bit.ly, but you can also use goo.gl or something.

I am using this little library in my 2 app store titles, and as far as i know its working as expected. But always keep in mind that; use this code at your own risk :)

All bug fixes and recommendations are welcome. Thank you.

deniz of He2 Apps
http://he2apps.com

Ad Manager for Corona v1.0

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
---------------------------------------------------------------------
---------------------------------------------------------------------
-- Ad Manager for Corona
-- version: 1.1
--
-- Change Log:
-- 1.1
-- + new feature: multiple houseads and ad rotation
-- + background ads feature removed (obsolete, use house ads instead)
--
-- 1.0
-- first public release
--
-- 2011-2012 deniz of he2apps
---------------------------------------------------------------------
---------------------------------------------------------------------
 
local ads = require("ads")
require("json")
 
local adNetworkParameters = nil
 
local adsReady, showAdsAfterInit, adsVisible = false, false, false, false
local houseAdsEnabled = false
local houseAdsObjects = nil
local currentHouseAd = 1
local houseAdsTargetUrl = nil
local houseAdsPosX, houseAdsPosY, houseAdsScale
local houseAdsDuration, houseAdsRotation, houseAdsBanners
local currentHouseAdIdx
 
local function resetSystem()
 
    if houseAdsObjects then
        for i=1,#houseAdsObjects do
            houseAdsObjects[i]:removeSelf()
        end
    end
    
    adNetworkParameters = nil
    
    adsReady, showAdsAfterInit, adsVisible = false, false, false
    houseAdsEnabled = false
    houseAdsObjects = nil
    houseAdsTargetUrl = nil
    currentHouseAdIdx = 1
    
end
 
local function rotateHouseAds()
 
    if not adsVisible then
        return
    end
    
    houseAdsObjects[currentHouseAdIdx].isVisible = false
    currentHouseAdIdx = currentHouseAdIdx + 1
    if currentHouseAdIdx > #houseAdsObjects then
        currentHouseAdIdx = 1
    end
    
    houseAdsObjects[currentHouseAdIdx].isVisible = true
 
end
 
function showAds()
    
    if adsVisible then
        return
    end
    
    if houseAdsEnabled then
    
        if adsReady then
            houseAdsObjects[currentHouseAd].isVisible = true
            houseAdsObjects[currentHouseAd]:toFront()
        end
        
    else
    
        if adsVisible == false and adsReady then        
            ads.show( adNetworkParameters.bannerFormat,
                { x=adNetworkParameters.posx, y=adNetworkParameters.posy, interval=adNetworkParameters.interval, testMode=adNetworkParameters.testMode }
            )
        end
        
    end
    
    adsVisible = true
    showAdsAfterInit = true
    
end
 
function hideAds()
 
    if houseAdsEnabled then
    
        if houseAdsObjects then
            houseAdsObjects[currentHouseAd].isVisible = false
        end
    
    else
        ads.hide()
    end
    
    adsVisible = false
    showAdsAfterInit = false
    
end
 
local function loadHouseAds(params)
 
    local function houseAdsDownloadListener(event)
        
        if not event.isError then
        
            local currentIdx = #houseAdsObjects + 1
            local houseAdsObject = event.target
            houseAdsObjects[currentIdx] = houseAdsObject
            houseAdsObject.x = houseAdsPosX
            houseAdsObject.y = houseAdsPosY
            houseAdsObject:addEventListener("tap",function() system.openURL(houseAdsBanners[currentIdx].targetUrl) return true end)                                                
            houseAdsObject:scale(houseAdsScale,houseAdsScale)
            houseAdsObject.isVisible = false
            
            if currentIdx < #houseAdsBanners then 
                display.loadRemoteImage( houseAdsBanners[currentIdx+1].imageUrl, "GET", houseAdsDownloadListener, "housead_tmp"..tostring(currentIdx+1) )
            else
                adsReady = true
                houseAdsObjects[1].isVisible = showAdsAfterInit
                if houseAdsRotation then
                    timer.performWithDelay( houseAdsDuration * 1000, rotateHouseAds, 0 )
                end
            end
            
            
        else
            adsReady = false
        end
    end
    
    houseAdsEnabled = true
    houseAdsTargetUrl = params.targetUrl
    houseAdsPosX = params.x
    houseAdsPosY = params.y
    houseAdsScale = params.scale
    houseAdsRotation = params.rotation
    houseAdsDuration = params.duration
    houseAdsBanners = params.banners
    houseAdsObjects = {}
    
    display.loadRemoteImage( houseAdsBanners[1].imageUrl, "GET", houseAdsDownloadListener, "housead_tmp_1" )
    
end
 
function initAds(initUrl)
    
    local function adNetworkListener( event )
        
        if ( event.isError ) then
            print( "initAds() : Network error!")
            adsReady = false
        else
            local params = json.decode(event.response)
               
            if params.houseads.enabled then
                loadHouseAds(params.houseads)
            end
            
            if params.ads.enabled then
                
                adNetworkParameters = { networkName=params.ads.network, networkId=params.ads.id, bannerFormat=params.ads.format,
                    posx=params.ads.x, posy=params.ads.y, interval=params.ads.interval, testMode=params.ads.test,
                }
                
                ads.init(params.ads.network,params.ads.id)
                adsReady = true
                
                if showAdsAfterInit then
                    ads.show( adNetworkParameters.bannerFormat, { x=adNetworkParameters.posx, y=adNetworkParameters.posy,
                        interval=adNetworkParameters.interval, testMode=adNetworkParameters.testMode })
                end                
                
            end                        
            
        end
    end
    
    resetSystem()
    
    local adNetworkInitRndUri = initUrl .. "?" .. math.random(1000000)
    network.request( adNetworkInitRndUri, "GET", adNetworkListener )        
 
end


Replies

@RSCdev
User offline. Last seen 1 year 29 weeks ago. Offline
Joined: 6 Sep 2011

First, Thank you for sharing!

But how would I setup more than 1 ads network? for example inMobi and Inneractive?

Is it possible to get the 2 setup?

Cheers,
Rodrigo.

deniz
User offline. Last seen 15 hours 52 min ago. Offline
Joined: 22 Nov 2010

Just prepare 2 config files for each network, and use that file whenever you wish to enable particular ad network.

or create a new "ads" section, name it as "ads2" for example. There should be only one "ads" section, so manually changing "ads2" to "ads" (and of course dont forget to chage "ads" to "ads-disabled" or something) will enable your new ad network

You could also use some sort of programmable configuration url, a php script for example, then get configuration parameters from a database and you got a fully programmable ad configuration without changing config file manually.

naveen_pcs
User offline. Last seen 17 hours 49 min ago. Offline
Joined: 9 Apr 2011

So If I'm getting this right, I cannot set background and ads to true?

How would I do a fallback if I don't receive an ad then?

Awesome code though! Really useful to run specific campaigns and swap them out instantly.

deniz
User offline. Last seen 15 hours 52 min ago. Offline
Joined: 22 Nov 2010

@003naveen

You can enable both "ads" and "background". Background banners always put below banner ads, and house ads. You should not use "ads" and "houseads" together.

If ansca provide us an event handler to tell whether ads loaded from the network, I can implement a more robust, real world house ads mechanism. So there will be no need of such a thing like background ads, and we can show house ads if there is no ads from the network.

MBD
User offline. Last seen 4 days 10 hours ago. Offline
Joined: 14 Sep 2010

You can create your own ad networks and cross-promote your apps with other developer apps here http://lunarads.com/signup/

We just opened this up to other developers!

Best,
Richard

prodesuka
User offline. Last seen 11 hours 29 min ago. Offline
Joined: 20 Nov 2011

Thanks for this, it's very handy.

There is one thing I'd like to note after testing it though.
I use the latest daily builds of Corona, and something seems to go wrong in the loadHouseAds() function:

local util = require("okey_util")

Is the okey_util file some kind of custom file of yours? Seems to run OK after removing:

local util = require("okey_util")
util.table_print(event)

Other functionality works nicely, thanks again for the contribution.

deniz
User offline. Last seen 15 hours 52 min ago. Offline
Joined: 22 Nov 2010

@prodesuka

yeah, i forgot to remove some debugging code. now its fixed. thank you :)

Harm
User offline. Last seen 30 weeks 4 days ago. Offline
Joined: 21 Oct 2010

Have you tried this on Android phones?
It works like a charm on iOS but with Android it doesn't load adds at all.
I'm trying to figure out why..

Edit: the house adds display correctly, just the add networks won't give anything out. I have tried Inneractive and inMobi.

deniz
User offline. Last seen 15 hours 52 min ago. Offline
Joined: 22 Nov 2010

@Harm

If you managed to run ansca's inmobi and inneractive samples correctly, there should not be a problem using Ad Manager.

Sample ads_config.txt file configures inmobi network to serve demo ads. You should see those ads anyway.

I can not try this on an Android device, but as it uses native ads functionality, which is platform independent, it ought to work i guess.

Harm
User offline. Last seen 30 weeks 4 days ago. Offline
Joined: 21 Oct 2010

Hmh.. strange thing is that the same version built for iPhone displays the adds correctly.

I'm using build 730, just in case I'll update to the newest and try with it..

deniz
User offline. Last seen 15 hours 52 min ago. Offline
Joined: 22 Nov 2010

hey, this module is obsolete. Please use Ad Mediator for Corona instead. It is an ad mediation module very much like Adwhirl.

Ad Mediator for Corona: http://developer.anscamobile.com/code/ad-mediator-corona