Adding ads to my first game

Hello everybody!

So, i finished my first game and run into the issue of implementing ads… such a complex matter.

For some reason you have to pay to use admob, so ill skip that since im not willing to invest $200 on my first game.

I found the most popular free alternative was Inmobi.

I created my Inmobi account, created an app, selected the ads, chose none for my mediation platform and none for dev platform.

So, i read up on the corona documentation. I copied this to my build.settings(yes, I copied this under the plug in section)

  ["plugin.inMobi"] =         {             publisherId = "com.coronalabs"         },

and I have this on my main.lua file:

local inMobi = require( "plugin.inMobi" ) -- Pre-declare a placement ID local placementID = "HereAreNumbers" -- This was changed for this post local function adListener( event )     if ( event.phase == "init" ) then  -- Successful initialization         -- Load a banner ad         inMobi.load( "interstitial", placementID )     elseif ( event.phase == "failed" ) then  -- The ad failed to load         print( event.type )         print( event.placementId )         print( event.isError )         print( event.response )     end end -- Initialize the InMobi plugin inMobi.init( adListener, { accountId="numbersAndLetters" } ) -- changed for this post -- Sometime later, check if the ad is loaded if ( inMobi.isLoaded( placementID ) ) then     -- Show the ad   inMobi.show( placementID, { yAlign="bottom" } ) end

And… nothing really works.

In the simulator, it says that I have to test it on an actual device, but it doesn’t work on my phone.

So… what am I doing wrong?

adListener is an asynchronous function. That means that it doesn’t necessarily execute by the time the program moves on to the next line of code.

In your case, you are trying to see if an ad can be shown only a few lines after you’ve initialised the plugin. This happens in an instant and the plugin has not had the time to initialise itself. In your adListener’s “init” phase, you load the first ad, however, this occurs much later than your “inMobi.isLoaded( placementID )” check.

So, simply put, you just need to do is to wait for the plugin to be initialised first. One easy way of testing this on a device would be to create a white rectangle on the screen. Once the “init” phase is done, you can set the rectangle’s fill color to something else. Then, add a touch listener to the rect and check if an ad is available by pressing that.

You really should read this tutorial:

http://docs.coronalabs.com/tutorial/basics/ads/index.html

While its code is for AdMob, the discussion is general to all ad networks and for the most part the code is general enough, concept wise for any ad plugin.

This should be required reading for anyone who wants to add ads to their apps.  There is a companion blog post that covers monetization in general. You should read and understand this too:

https://coronalabs.com/blog/2018/10/02/monetization-best-practices-and-a-new-ad-tutorial/

Rob

Thanks for the help, didn’t know that about the adListener.

I did what you said, but still doesn’t work. Its as if the ad never gets initialized.  inMobi.isLoaded(placementID) is always false, even when I click on something to check if its true.

When you have problems such as this, the first step should always be to consult the documentation (which Rob has linked). If that doesn’t work, then you should post code of what you’ve done, like you originally did. Now I can only guess and say that “you did it wrong”. Have you setup the plugin properly in your build settings? How do you check if the ad is loaded and when, does your device has Internet connection, etc.?

all right, heres what ive got on my main.lua:

local inMobi = require( "plugin.inMobi" ) -- Pre-declare a placement ID local placementID = "1569390117164" local function adListener( event ) &nbsp;&nbsp;&nbsp; if ( event.phase == "init" ) then&nbsp; -- Successful initialization &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -- Load a banner ad &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; inMobi.load( "banner", placementID ) &nbsp;&nbsp;&nbsp; elseif ( event.phase == "failed" ) then&nbsp; -- The ad failed to load &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; print( event.type ) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; print( event.placementId ) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; print( event.isError ) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; print( event.response ) &nbsp;&nbsp;&nbsp; end end -- Initialize the InMobi plugin inMobi.init( adListener, { accountId="f834a961c20f49a08d042b66a42e3939 " } ) -- Modules physics = require("physics") physics.start() local obstacleRate = 10 display.setDefault("background", 0, 0, 0) --trail color local trailColor = {173, 255, 254} --tap and hold var local tap = false local holdTap = false local speed = 20 --Show text local speedText = display.newText(speed, 132, 0) -- Define Player local slowdown = 0.99 local sheetData = {width=40, height=40, numFrames=3, sheetContentWidth=120, sheetContentHeight=40} local playerSheet = graphics.newImageSheet("player.png", sheetData) local playerSequenceData = { &nbsp;&nbsp;&nbsp; {name = "idle", frames={1}, time = 250}, &nbsp;&nbsp;&nbsp; {name = "left", frames={2}, time = 250}, &nbsp;&nbsp;&nbsp; {name = "right", frames={3}, time = 250} } local player = display.newSprite(playerSheet, playerSequenceData) player.timeScale = 0.5 player:setSequence("idle") player:play() player.x = 0 player.y = 200 player.dir = "right" physics.addBody(player, "dynamic", {density = 5, bounce=0.3, friction = 2}) --Move Player function movePlayer(self, event) &nbsp; &nbsp;&nbsp;&nbsp; if self.dir == "right" then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self:applyForce(60, 0, self.x, self.y) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if ( inMobi.isLoaded( placementID ) ) then------------------------Here I test the add(this function is called when clicked) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -- inMobi.show( placementID, { yAlign="bottom" } ) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; speed = 30 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp; else &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self:applyForce(-60, 0, self.x, self.y) &nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; end -- Touch Controls function onTouch(event) &nbsp;&nbsp;&nbsp; if event.phase == "began" then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if tap == false then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; local vx, vy= player:getLinearVelocity() &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; player:setLinearVelocity(vx \* 0.4, vy) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; tap = true &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if player.dir == "right" then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; player:setSequence("right") &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; player:setSequence("left") &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; player.enterFrame = movePlayer &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Runtime:addEventListener("enterFrame", player) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; print("began") &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; trailColor = {173, 255, 254} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; holdTap = true &nbsp;&nbsp;&nbsp; elseif event.phase == "ended" then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Runtime:removeEventListener("enterFrame", player) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if player.dir == "right" then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; player.dir = "left" &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; player.dir = "right" &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; print("ended") &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; player:setSequence("idle") &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; trailColor = {173, 255, 254} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; tap = false &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; holdTap = false &nbsp;&nbsp;&nbsp; end end -- Player Trail function particleEffect() &nbsp;&nbsp;&nbsp; local chance = math.random(1, 1) &nbsp;&nbsp;&nbsp; if chance == 1 then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; local pX = math.random(player.x - 5, player.x + 5) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; local yOffset = 20 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if holdTap then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; yOffset = 20 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; yOffset = 20 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; local pY = player.y - yOffset &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; local particle = display.newCircle(pX, pY, 3) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; particle.x, particle.y = pX, pY &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; physics.addBody(particle, "dynamic") &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; particle.isSensor = true &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; particle:applyForce(0, -(speed/100), particle.x, particle.y) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; particle.gravityScale = 0 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if holdTap then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; particle:setFillColor(0.5, 0.9999, 0.9999) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; particle:setFillColor(0.8, 0.999, 0.999) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; timer.performWithDelay(1200, function() &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; particle:removeSelf() &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; particle=nil &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; transition.fadeOut(particle, {time=1300}) &nbsp;&nbsp;&nbsp; end end -- Obstacle Spawner function IncomingObstacles() &nbsp;&nbsp;&nbsp; local chance = math.random(1, obstacleRate) &nbsp;&nbsp;&nbsp; if chance == 1 then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; local oX = math.random(0, 300) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; local oY = 550 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; local obstacle = display.newImage("1.png") &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; obstacle.x, obstacle.y = oX, oY &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; physics.addBody(obstacle, "dynamic") &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; obstacle.isSensor = true &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; obstacle:applyForce(0, -speed, obstacle.x, obstacle.y) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; obstacle.gravityScale = 0 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; timer.performWithDelay(4500, function() &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; obstacle:removeSelf() &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; obstacle=nil &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end) &nbsp;&nbsp;&nbsp; end end -- EnterFrame Function---------------------------------------------------- function enterFrame(event) &nbsp;&nbsp;&nbsp; --Keep Player height &nbsp;&nbsp;&nbsp; player.y = 200 &nbsp;&nbsp;&nbsp; particleEffect() &nbsp;&nbsp;&nbsp; IncomingObstacles() &nbsp;&nbsp;&nbsp; --Warp &nbsp;&nbsp;&nbsp; if player.x \> 350 then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; player. x = 0 &nbsp;&nbsp;&nbsp; elseif player.x \< -50 then &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; player.x = 345 &nbsp;&nbsp;&nbsp; end end ------------------------------------------------------------- -- Listeners Runtime:addEventListener("enterFrame", enterFrame) Runtime:addEventListener("touch", onTouch)

this is my build.settings:

-- -- For more information on build.settings, see the Project Build Settings guide at: -- https://docs.coronalabs.com/guide/distribution/buildSettings -- settings = { &nbsp;orientation = &nbsp;{ &nbsp;&nbsp;-- Supported values for orientation: &nbsp;&nbsp;-- portrait, portraitUpsideDown, landscapeLeft, landscapeRight &nbsp;&nbsp;default = "portrait", &nbsp;&nbsp;supported = { "portrait", }, &nbsp;}, &nbsp;-- &nbsp;-- Android section &nbsp;-- &nbsp;android = &nbsp;{ &nbsp;&nbsp;usesPermissions = &nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;"android.permission.INTERNET", &nbsp;&nbsp;&nbsp;"android.permission.ACCESS\_WIFI\_STATE", &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "android.permission.READ\_PHONE\_STATE", &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "android.permission.ACCESS\_NETWORK\_STATE", &nbsp;&nbsp;}, &nbsp;}, &nbsp;-- &nbsp;-- iOS section &nbsp;-- &nbsp;iphone = &nbsp;{ &nbsp;&nbsp;xcassets = "Images.xcassets", &nbsp;&nbsp;plist = &nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;UIStatusBarHidden = false, &nbsp;&nbsp;&nbsp;UILaunchStoryboardName = "LaunchScreen", &nbsp;&nbsp;}, &nbsp;}, &nbsp;-- &nbsp;-- Plugins section &nbsp;-- &nbsp;plugins = &nbsp;{ &nbsp;&nbsp;["plugin.inMobi"] = &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; { &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; publisherId = "com.coronalabs" &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }, &nbsp;}, &nbsp;-- &nbsp;-- Project section &nbsp;-- &nbsp;excludeFiles = &nbsp;{ &nbsp;&nbsp;-- Exclude unnecessary files for each platform &nbsp;&nbsp;all = { "Icon.png", "Icon-\*dpi.png", "Images.xcassets", }, &nbsp;&nbsp;android = { "LaunchScreen.storyboardc", }, &nbsp;}, }

and just in case the config file(the only thing I edited was the xalign and yalign:

-- -- For more information on config.lua see the Project Configuration Guide at: -- https://docs.coronalabs.com/guide/basics/configSettings -- application = { &nbsp;&nbsp;&nbsp;&nbsp;content = &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;width = 320, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;height = 480, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;scale = "letterbox", &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fps = 60, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;xAlign = "center", &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;yAlign = "center", &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;--[[&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;imageSuffix = &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ["@2x"] = 2, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ["@4x"] = 4, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;--]] &nbsp;&nbsp;&nbsp;&nbsp;}, }

These are all the files in the game(mind you this isn’t the actual game I mentioned earlier, its a small prototype I used to test the ads)

Showing banner ads during game play isn’t a good idea. Players are focused on game play and you’re just wasting your ad provider’s inventory. You’re attempting to show an add every time you move your player.

You should, on success of the ad loading, get an event that trigger’s your adListener function and maybe there you might want to consider showing the ad and let it auto refresh.

Look at this adListener…

local json = require("json") local function adListener( event ) print( json.prettify( event ) ) if ( event.phase == "init" ) then -- Successful initialization -- Load a banner ad inMobi.load( "banner", placementID ) elseif ( event.phase == "loaded" ) then inMobie.show( placementID ) elseif ( event.phase == "failed" ) then -- The ad failed to load print( event.type ) print( event.placementId ) print( event.isError ) print( event.response ) end end

the big thing here is that you need to print the event table when you enter the adListener function so that you can see the flow of what’s going on. I normally don’t like to show ads after the loading event. But you don’t seem to be using scene management which is a more logical place to manage showing ads. You can show banners on your menu screens, or game over screens etc.

But still we need to know why you’re not getting the ads and the only way to do that is to add the prints that I did and use “adb logcat” to look at an Android device’s console log.  If you’re building for iOS, let me know we will need a different way to print the table since apple now combines that print into a useless single line.

Rob

Thanks a ton rob!

Yeah, im not gonna have the banner every time someone touches the screen, I was just testing. Im gonna use the interstitial ad when the player dies or finishes a level (50% chance for each)

Anyhow I checked the log and it didnt recognize the placementID, probably because I didnt enter the app URL on inmobis dashboard ( its mandatory) .

stupid mistake, I know.