Preface: on Twitter, Peter Baily @peterbailey encouraged us to write about marketing and developing apps, so from Peter’s encouragement here is the first of a series of blog posts on those topics.
Recently I’ve been reading several business books and one book in particular has given me several nuggets of wisdom. Founders at Work is comprised of a series of interviews with founders during their startup years. In the first two chapters, Max Levchin (Paypal founder) and Sabeer Bhatia (Hotmail Founder) talk about how their businesses had built in virality. In the case of Hotmail, when someone sends you an email from Hotmail at the bottom of the email is a little advertisement letting you know that the email came from Hotmail and you can get a free account there too. From a business standpoint that is absolutely brilliant. Free advertising built into every single email sent. That little link was a huge contributing factor of why Hotmail went viral and it turned into the success it has become.
So here are some questions I’ve been wrestling with lately—How do we make our games more viral? How do we reward people for telling their friends about our game? How do we build a fan base/community around our games? If you’re a game developer I’m sure you have asked yourself the same questions. As I look around our social media landscape, its obvious that Facebook is the big player. And whether you like it or not—their “Like Button” has become a very powerful tool to spread the word about something cool or believe in. With that in mind, I’ve spent the last few days diving into the Facebook Api trying to understand all the ways we can use Facebook to encourage virality and setting up a system which we could use in all our games going forward.
Right now we have decided there are four actions we want to encourage users to take within our games. That is to say, we want to encourage four other actions in addition to the standard post your score to Open Feint and Facebook, which are standard fare. We want to encourage players to Like Crawl Space on Facebook, Like Our Game, Rate the Game, and Tell a Friend About the Game.
Lets jump into some code. In our main.lua file we define some variables. The code below shows our default variables being defined using the CrawlSpace Library.
Defaults{rateGame=false, likeUs=false, likeGame=false, tellFriend=false}
These variables come into use during our game through two classes. The first class is adBar.lua. The adBar class allows us to place an ad bar wherever we like on the screen. You can define if you want to show external ads like AdMob or “house” ads which in this case is what we want to do. If you understand how to make text or graphic with a listener then you understand the adBar class. I’m not going to go into all the code, but I will show you one of the listener functions in the class.
openLikeGame = function(event)
if event.phase == "began" then
local url = websiteUrl.."likegame.php"
easyFB:showLikeBox(url)
end
end
As you can see its a pretty standard listener function. We are listening for a touch phase. The if statement is looking specifically for the beginning of the touch phase, so the function isn’t called multiple times. After declaring our variable, url, we pass it into the work horse class “easyFB” where we call the showLikeBox function.
All Facebook interaction is handled in our easyFB.lua file. The easyFB class stands for “easy Facebook”. We took the Facebook example code included with the Corona SDk files and made a class that we reuse across our games—which I’m giving away today to all our lucky readers. Easy FB handles logging in and out, posting to wall, showing leaderboards, checking likes, and show like boxes. We will only touch on a few of these functions for this article, but feel free to post any questions you have or send me an email.
The first function, easyFB.login(), does what is says…it logs you into Facebook. You pass in your Facebook App Id and an optional callback function. The callback function will fire after you are logged into Facebook. The important part to highlight in this function is that we are requesting a few permissions from the user when they connect. They are giving us permission to see their likes and publish to their stream. We obviously don’t want to abuse these permissions, but they are needed to be able to post high scores to their wall and to check if they like our company and our game.
easyFB.login = function ( event, facebookAppId, cb )
callback = cb
facebook.login(facebookAppId, fbListener, {"user_likes", "publish_stream"} )
end
When logging into Facebook we attached a listener called “fbListener”. This function handles all the event login for the communication between facebook and the game. I apologize that the function is a little long and complex. The listener is the listener in the Facebook example code, bundle with corona, with a few additions.
fbListener = function( event )
if ( "session" == event.type ) then
-- event.phase is one of: "login", "loginFailed", "loginCancelled", "logout"
if ( "login" == event.phase ) then
setVar{"fbLoggedIn", true}
facebook.request( "me/likes")
if fbCommand == SHOW_DIALOG then
facebook.showDialog( {action = "stream.publish"} )
end
if fbCommand == POST_PHOTO then
facebook.request( "me/feed", "POST", attachment )
Achieve("share")
end
elseif "logout" == event.phase then
setVar{"fbLoggedIn", false}
elseif "loginCancelled" == event.phase then
callback = nil
native.cancelWebPopup()
end
-- if there is a requested callback function, execute it
if callback then callback() end
elseif ( "request" == event.type ) then
-- event.response is a JSON object from the FB server
local response = event.response
-- if request succeeds, create a scrolling list of friend names
if ( not event.isError ) then
response = json.decode( event.response )
local data = response.data
for i=1,#data do
local name = data[i].name
if name == company then
setVar{"likeUs", true}
elseif name == game then
setVar{"likeGame", true}
else
end
end
elseif ( "dialog" == event.type ) then
end
end
end
When someone successfully logs in to Facebook the login event.phase runs and we first set a variable to let the game know that the user is logged into Facebook then we request the users likes. Within this same listener, at the bottom half of the code, we see a check for “request”. This code receives the json data, decodes it then we loop through the users likes and check if they like our company or our game. We set respective variables to true accordingly.
elseif ( "request" == event.type ) then
-- event.response is a JSON object from the FB server
local response = event.response
-- if request succeeds, create a scrolling list of friend names
if ( not event.isError ) then
response = json.decode( event.response )
local data = response.data
for i=1,#data do
local name = data[i].name
if name == company then
setVar{"likeUs", true}
elseif name == game then
setVar{"likeGame", true}
else
end
end
At this point we have determined if the player likes our company and if he/she likes our game. For illustration lets assume they have not liked either our game or company on Facebook. At this point we would provide the player with an enticing offer to like us, such as unlocking extra content if they like us on Facebook. The player clicks on the ad and it calls this function:
easyFB.showLikeBox = function(self, url)
local urlPath = url
local showLike = function()
callback = nil
native.cancelWebPopup()
native.showWebPopup(centerX - 150, centerY - 200, 300, 400, urlPath, {urlRequest=webListener})
end
callback = showLike
if retrieveVar("fbLoggedIn") == true then
showLike()
else
facebook.login( facebookAppId, fbListener, {"user_likes", "publish_stream"} )
end
end
The showLikeBox accepts a url parameter, which is the url for the web page that we will popup. That web page contains a title, Facebook Like Button, and a close button. You can load all the code at the bottom of the post.
Anytime we call a web popup in the easyFb class we attach the same listener called “webListener”. This listener listens for three events, “corona:close”, “corona:likeUs”, and “corona:likeGame”. If a user clicks like in the popup, we have a javascript listener that will hide all content except for a thank you message a link to return to the game, which our webListener in the game listens for.
webListener = function( event )
local shouldLoad = true
local url = event.url
if 1 == string.find( url, "corona:close" ) then
-- Close the web popup
if externalAds == true then
adBar:openAds()
end
shouldLoad = false
elseif 1 == string.find(url, "corona:likeUs") then
setVar{"likeUs", true}
shouldLoad = false
elseif 1 == string.find(url, "corona:likeGame") then
setVar{"likeGame", true}
shouldLoad = false
end
return shouldLoad
end
We will be rolling out this system in all our games going forward starting with Globs and Bounce to Win both coming out in June. If you have any questions about the code let me know and I’ll be glad to assist.
Download Source Code