Remote Game Editing

I’ve long been a fan of minimal game runtimes. Anything that can be done offline or in a separate tool, should be out of the runtime. That leaves the game architecture and code very lean and simple.

One of the things you potentially give up by keeping the game runtime to a minimum is an editor built in the game itself. But that’s one of those things that sounds a lot better than it really is. From a technical point of view, having an editor in the game usually complicates the code a huge amount. All of a sudden you need to deal with objects being created and destroyed randomly (instead of through clearly defined events in the game), and you have to deal with all sorts of crazy inputs and configurations.

The worse part though, is having to implement some sort of GUI editing system in every platform. Creating the GUI to run on top of the game is not easy, requiring that you create custom GUI code or try to use some of the OpenGL/DirectX libraries available. And even then, a complex in-game GUI might not be a big deal on a PC, but wait and try to use that interface on a PS3 or iPhone. After all, making games is already complicated and time-consuming enough to waste more time reinventing the widget wheel.

Remote game editing manages to keep a minimal runtime and allow you to quickly create native GUIs that run on a PC. It’s the best of both worlds, and although it’s not quite a perfect solution, it’s the best approach I know.

Debug Server

Miguel Ángel Friginal already covered the basics of the debug server, so I’m not going to get in details there.

The idea is that you run a very simple socket server on the game, listening in a particular port. This server implements the basic telnet protocol, which pretty much means that it’s a line-based, plain-text communication.

The main difference between my debug server and Miguel’s (other than mine is written in cross-platform C/C++ instead of ObjC), is that I’m not using Lua to execute commands. Using Lua for that purpose is a pretty great idea, but goes against the philosophy of keeping the runtime as lean and mean as possible.

Instead, I register variables with the server by hand. For each variable, I specify its memory address, it’s type, any restrictions (such as minimum and maximum values), and a “pretty name” to display in the client. Sounds like a lot of work, but it’s just one line with the help of a template:

registry.Add(Tweak(&plantOptions.renderGloss, "render/gloss", "Render gloss"));
registry.Add(Tweak(&BouquetParams::FovY, "bouquet/fov", "FOV", Pi/32, Pi/3))

And yes, if I were to implement this today, I would probably get rid of the templates and make it all explicit instead (ah, the follies of youth 🙂

TweakUtils::AddBool(registry, &plantOptions.renderGloss, "render/gloss", "Render gloss");
TweakUtils::AddFloat(registry, &BouquetParams::FovY, "bouquet/fov", "FOV", Pi/32, Pi/3);

The debug server itself responds to three simple commands:

  • list. Lists all the variables registered in the server.
  • set varname value. Sets a value.
  • print varname. Gets the value for that variable.

For example, whenever the server receives a set command, it parses the value, verifies that it’s within the acceptable range, and applies it to the variable at the given memory location.

Telnet Clients

telnet.pngBecause we used the standard telnet protocol, we can start playing with it right away. Launch the game, telnet into the right port, and you can start typing away.

However, most telnet clients leave much to be desired for this. They all rely on the history and cursor manipulation being handled by the shell they assume you’re connected to. Here we aren’t connected to much of anything, but I’d like to be able to push up arrow and get my last command, and be able to move to the beginning of the line or the previous word like I would do in any text editor. The easiest solution I found for that was to use a telnet client prepared for that kind of thing: A MUD client! Just about any will do, but one that works well for me is Atlantis.

So far, we’ve implemented the equivalent of a FPS console, but working remotely. And because the code is fully portable, our game can be in just about any platform and we can always access it from our PC. Not just that, but we can even open multiple simultaneous connections to various development devices if you need to run them all at once.

Custom Clients

Game parameter tweaking is something that is OK through a text-based console, but really comes into its own when you add a GUI. That’s exactly what we did at Power of Two Games. We created a generic GUI tool (based on WinForms since we were on Windows at the time), that would connect to the server, ask for a list of variables, and generate a GUI on the fly to represent those variables. Since we knew type and name of each variable, it was really easy to construct the GUI elements on the fly: A slider with a text field for floats and ints, a checkbox for bools, four text fields for vectors, and even a color picker for variables of the type color.

It worked beautifully, and adjusting different values by moving sliders around was fantastic. We quickly ran into two problems through.

The first one is that we added so many different tweaks to the game, that it quickly became unmanageable to find each one we wanted to tweak. So, in the spirit of keeping things as simple as possible (and pushing the complexity onto the client), we decided that the / symbol in a name would separate group name and variable name. That way we could group all related variables together and make everything usable again.

The second problem was realizing that some variables were changing on the runtime without us knowing it on the client. That created weird situations when moving sliders around. We decided that any time a registed variable changes on the server, it should notify any connected clients. That worked fine, but, as you can imagine, it became prohibitively expensive very quickly. To get around that, we added a fourth command: monitor varname. This way clients need to explicitly register themselves to receive notifications whenever a variable changes, and the GUI client only did it for the variables currently displayed on the screen.

tweaker.png

During this process, it was extremely useful to be able to display a log console to see what kind of traffic there was going back and forth. It helped me track down a few instances of bugs where changing a variable in the client would update it in the server, sending an update back to the client, which would send it again back to the server, getting stuck in an infinite loop.

You don’t need to stop at a totally generic tool like this either. You could create a more custom tool, like a level editor, that still communicates with the runtime through this channel.

Flower Garden Example

For Flower Garden, I knew I was going to need a lot of knobs to tweak all those plant DNA parameters, so I initially looked into more traditional GUI libraries that worked on OpenGL. The sad truth is that they all fell way short, even for development purposes. So I decided to grab what I had at hand: My trusty tweaking system from Power of Two Games.

I’m glad I did. It saved a lot of time and scaled pretty well to deal with the hundreds of parameters in an individual flower, as well as the miscellaneous tweaks for the game itself (rendering settings, infinite fertilizer, fast-forwarding time, etc).

Unfortunately, there was one very annoying thing: The tweaker GUI was written in .Net. Sure, it would take me a couple of days to re-write it in Cocoa (faster if I actually knew any Cocoa), but as an indie, I never feel I can take two days to do something tangential like that. So instead, I just launched it from VMWare Fusion running Windows XP and… it worked. Amazingly enough, I’m able to connect from the tweaker running in VMWare Fusion to the iPhone running in the simulator. Kind of mind boggling when you stop and think about it. It also connects directly to the iPhone hardware without a problem.

VMWare Fusion uses up a lot of memory, so I briefly looked into running the tweaker client in Mono. Unfortunately Mono for the Mac didn’t seem mature enough to handle it, and not only was the rendering of the GUI not refreshing correctly, but events were triggered in a slightly different order than in Windows, causing even more chaos with the variable updates.

Here’s a time-lapse video of the creation of a Flower Garden seed from the tweaker:

Drawbacks

As I mentioned earlier, I love this system and it’s better than anything else I’ve tried, but it’s not without its share of problems.

Tweaking data is great, but once you find that set of values that balances the level to perfection… then what? You write those numbers down and enter them in code or in the level data file? That gets old fast. Ideally you want a way to automatically write those values back. That’s easy if the tool itself is the editor, but if it’s just a generic tweaker, it’s a bit more difficult.

One thing that helped was adding a Save/Load feature to the tweaker GUI. It would simply write out a large text-based file with all the variables and their current values. Whenever you load one of those, it would attempt to apply those same values to the current registered variables. In the end, I ended up making the Flower Garden offline seed file format match with what the tweaker saved out, so that process went pretty smoothly.

Another problem is if you want lots of real-time (or close to real time) updates from the server. For example, you might want to monitor a bunch of data points and plot them on the client (fps, memory usage, number of collisions per frame, etc). Since those values change every frame, it can quickly overwhelm the simple text channel. For those cases, I created side binary socket channels that can simply send real-time data without any overhead.

Finally, the last drawback is that this tweaking system makes editing variables very easy, but calling functions is not quite as simple. For the most part, I’ve learned to live without function calls, but sometimes you really want to do it. You can extend the server to register function pointers and map those to buttons in the client GUI, but that will only work for functions without any parameters. What if you wanted to call any arbitrary function? At that point you might be better off integrating Lua in your server.

Future Directions

This is a topic I’ve been interested in for a long time, but the current implementation of the system I’m using was written 3-4 years ago. As you all know by now, my coding style and programming philosophy changes quite a bit over time. If I were to implement a system like this today, I would do it quite differently.

For all I said about keeping the server lean and minimal, it could be even more minimal. Right now the server is receiving text commands, parsing them, validating them, and interpreting them. Instead, I would push all that work on the client, and all the server would receive would be a memory address, and some data to blast at that location. All of that information would be sent in binary (not text) format over a socket channel, so it would be much more efficient too. The only drawback is that we would lose the ability to connect with a simple telnet client, but it would probably be worth it in the long run.

This post is part of iDevBlogADay, a group of indie iPhone development blogs featuring two posts per day. You can keep up with iDevBlogADay through the web site, RSS feed, or Twitter.

The Power of Free (aka The Numbers Post #3)

It has been two months since the last “numbers post”. It covered the Valentine’s Day promotion, spike in sales, and subsequent settling out at a very nice level. Here’s a recap of what things looked like at the beginning of May (revenue was about $1500 per week):

fg_before.png

The Plan

Mother’s Day happens at the beginning of May (in the US and Canada anyway, I’m afraid I was too busy in April and I missed Mother’s Day in a lot of European countries). I figured it would be the perfect time to do another push.

If there’s something I learned from past experience, is that the more you manage to concentrate any kind of promotion, the more effective it will be. So in preparation for Mother’s Day, I created a new update (with iPad support), a couple of new in-app purchase items (new set of seeds and some fertilizer bundles), and sent out the usual announcement on the Flower Garden mailing list, Facebook page, and Twitter.

But in addition to all of that, I tried a new strategy: I gave Flower Garden away for free. Yes, completely for free.

The idea sounded really scary at first. After all, I would be giving away my baby for free. Would I lose a lot of money doing that? Would it depreciate the perceived value of Flower Garden? Would it annoy loyal users seeing an app they paid for given away? Fortunately it appears that the answer to those questions was no.

The reason I decided to give Flower Garden away for free was mostly to get it into more people’s hands. I was thinking I would lose some money initially, but then more than make up for it when I turned it back to paid because of all the extra users and word of mouth. There is already a free version with a limited number of pots and seeds, but people are hungry to download paid apps for free.

To add extra impact to this price change, I had Flower Garden featured as the free app for Mother’s Day weekend in Free App Calendar. Unlike other free app web sites, the folks at Free App Calendar are very developer friendly and are not out to take a cut of your profits or charge outrageous fees. It was an absolute pleasure dealing with them.

Mother’s Day

On Saturday May 8th, a few minutes past midnight the day before Mother’s Day, I switched Flower Garden over to free. Now I was committed!

Right away there was a lot of positive reaction around the announcement. Everybody on Twitter and Facebook were responding really well and spreading the word. Major sites like Touch Arcade and 148Apps covered the Mother’s Day promotion and got lots of extra eyeballs on the sale.

After the first day, the data was in: Flower Garden had been downloaded 12,500 times. That was great! As a reference, Flower Garden Free was usually downloaded between 800 and 1,000 times per day, so that was a 10x improvement.

On Sunday, Mother’s Day, things got even better. News had time to propagate more, and people were sending bouquets like crazy, so by the end of the day there had been an additional 26,000 downloads. That’s exactly what I was hoping for!

As a matter of fact, it was doing so great, that I decided to leave it for free as long as the number of downloads was significantly higher than what the free version was normally getting. After Mother’s Day downloads started going down, but they were still pretty strong the following Sunday. Here’s what the download numbers looked like for those 9 days:

fg_week_downloads.png

The important question is how much revenue was there during that time? I was giving the app away for free but it had in-app purchases. Would they make up for it? The answer was a resounding yes!

fg_week_revenue.png

Mother’s Day went on to become the biggest day in terms of revenue since Flower Garden was launched. Bigger even than Christmas or Valentine’s Day! Things started going down after that, but still at a very high level. The little bump towards the end of the week is a combination of the weekend (which always results in more sales), and the feature of Flower Garden on the App Store across most of Europe.

These numbers took a bit to sink in. It really shows that in-app purchases are definitely tied to the number of downloads. If you manage to give away twice as many copies, you’ll probably get close to twice as many in-app purchases. That effect is amplified if you have multiple in-app purchase items available.

It’s also interesting to notice that revenue didn’t follow the same drop-off curve as downloads. It wasn’t nearly as sharp. I suspect two things are going on in there:

  • Some users downloaded Flower Garden during the sale weekend and weren’t interested in it at all. Downloading it was a knee-jerk reaction to any app that goes free, so that never translated into an in-app purchase. Users later in the week however, probably downloaded it because they received a bouquet or were interested in it, so they had a much higher likelihood of buying something through the Flower Shop.
  • Fertilizer. Fertilizer is the only consumable item available for purchase in Flower Garden. Unlike a non-consumable item, the number of sales is not tied to the number of new users, but to the number of current, daily users. The more users launch your app every day, the higher the sales of consumable items. Some of the new users of Flower Garden went on to buy fertilizer later in the week, making revenue higher than you would expect from the download curve.

Flipping The Switch

The number of downloads on Sunday May 16th was slightly over 2,000. At that point I decided that it was close enough to the number of downloads Flower Garden Free was normally getting, so I flipped the switch back to paid. Things were going great, so messing with it was a pretty scary thing to do. Even scarier than it had been setting it free in the first place.

During that week, Flower Garden rose up on the charts. It reached #73 in the top games in the US and was charting very high in all the subcategories and on the iPad charts. As soon as I flipped the switch back to paid, it dropped out of sight from the charts. Fortunately, within a couple of days it came back to its position before that crazy week.

Most importantly, Flower Garden Free, which had dropped quite a bit during that promotion, immediately went back up to the top 100 in the Kids and Family subcategories like before.

As you can expect, as a result of giving it away for free, the ratings on the App Store went down quite a bit. While it was a paid application, the ratings were around 4 stars, but they dropped down to 2.5 stars after that week. It seems people love a free app, but are very quick to criticize it and give it a low rating (especially if it has in-app purchases).

Fortunately bad ratings can be easily fixed with a new update, and some encouragement to users to leave positive rating on the App Store. Now it’s back up to over 4.5 stars.

Aftermath

Now it’s two months later and the dust has had a chance to settle down. Apart from the very nice sales spike during the sale, was it worth it? Again, the answer is a definite yes.

Here’s the revenue since the start of the promotion:

fg_two_months.png

As you can see, it quickly went down, but it settled at a reasonably high level. In fact, compare this two-month period (highlighted in blue) with the previous sales:

fg_after2.png

Before the promotion revenue was hovering around $1,500 per week, now it settled down to about $2,400 per week. An average day today is bigger than Christmas day! Very nice change!

I think the reason why it settled at a higher revenue level than before is because it got more exposure during that week. Lots of people sent bouquets, which introduced new users to Flower Garden. It’s the viral effect I was hoping for from the start, and although it never reached epidemic proportions, it has been enough to keep Flower Garden alive and well.

Adding iPad support as part of the latest update probably helped too. The iPad market is smaller than the iPhone one, but a lot of early adopters are eager to find good apps for their new toys. The smaller market size also allowed Flower Garden to appear in the iPad charts more easily, increasing exposure that way.

Here’s a breakdown of where revenue came from in the last month (I’m excluding the period where Flower Garden was free to get a more accurate view):

sales_breakdown.png

As you can see, consumable items (fertilizer) account for almost half the revenue. Consumable items are a factor of your current userbase, so getting a large influx of new users can result in a permanent revenue increase instead of just a sales spike. It also shows what a small percentage actual app sales are, which explains why even while Flower Garden was free, revenue was still up.

Conclusion

This was a wild ride again! It was definitely worth doing the promotion and it definitely brought home how powerful free can be. However, I’m trying to decide the pricing scheme for my next game, and even though free plus in-app purchases is very tempting, I’m not sure it’s the way to go.

What do you think? Are new games better off being free with in-app purchases, or can indie games be successful being paid (and still having in-app purchases)?

This post is part of iDevBlogADay, a group of indie iPhone development blogs featuring two posts per day. You can keep up with iDevBlogADay through the web site, RSS feed, or Twitter.

Paying Off: The Story Behind Unearthed

Today I have the pleasure to introduce the first-ever guest post in Games From Within, Joey Chang. Like me, Joey worked for many years in the game industry, and finally took the plunge last October to become an independent game developer. Unearthed is his first iPhone project and it’s a very unique free to play, augmented reality (AR) game with an X-Files-like theme.

Joey was kind enough to share the story behind Unearthed, some of the decisions leading up to the final game, and the initial reception and sales numbers. Thanks Joey!

Inspiration

Nine months ago, without warning, a gnome crept into my head. It was an idea inspired from a friend’s chance mention of an activity called geocaching, where participants use a GPS to hide and seek containers across the world. Within hours, I had envisioned a global cross between geocaching, the Amazing Race, and online travel agency representatives. The idea didn’t look much like the resultant product nine months later, but it formed the most critical ingredient to any venture: the obsession to see it completed.

I spent my evenings for a few short weeks hammering out a design, scoping and cutting features, and beginning a prototype, but it didn’t take long for me to admit to the unavoidable truth that such a project would take months working full time or probably 3 to 4 times as many months working nights and weekends. I had to sit and carefully consider the pros and cons of leaving my job to pursue something I desperately wanted to create.

Half-Hearted Dissent

UnearthedPoster.jpgFor two weeks, I debated with my wife and close friends with startup experience. I drafted a list of pros and cons to quitting my job to pursue an iphone project and stared at it for hours. Those of you who have made the leap or considered it may recognize some of the points or have more of your own to add:

Advantages of quitting to work full time on an iphone idea

  • Focus effort, complete project 3-4 times faster
  • Gain valuable unique experience of running solo
  • Avoid coding burnout, alienating loved ones, loss of sanity
  • Resume padding

Advantages of keeping day job while working on iphone idea

  • Steady income in a scary economy
  • Not having to job search in a scary economy
  • Peace of mind (in a scary economy)

You can see where a large portion of the dissenting argument forms its basis. After two weeks of listening to unanimous encouragement (bordering on persistent nagging) to quit my job, two weeks of trying my best to convince myself why I should not quit my job, I did what my gut knew from day one was going to be best for me. I marched to my boss’s room and quit my job. Ok, I had maybe two false starts where I turned around and went back to my seat.

The Project Unearthed

Over the next 8 months, scoping and an inclination to appeal to a casual segment evolved the project into a global paranormal investigation titled Unearthed. I tried my best to figure how to maximize the success of the product, and compiled a list of all the ways I could imagine increasing the product’s exposure:

  • Banner ads
  • Spamming blogs and websites to review my product
  • Spamming friends on facebook
  • Writing a blog
  • Viral app features

I had trouble justifying the cost to pay for banner ads, and I had too much urgency to implement the product to devote time to a blog, so I focused on occasionally talking about the app on facebook, compiling a list of potential blog candidates for the day the app released, and devising viral features.

Screen1.jpgApart from typical facebook posting and email-a-friend features, I decided to employ a “refer-an-agent” feature which would enable users to invite others to join their network, essentially a grouping of users that correlated with how effectively their app could process scanned creature data. The larger the network, the more credit users would receive for uploading data, and the better they would perform in leaderboards and achievements. The approach was an “everybody wins” style where anytime any user in the network gained a referral, every single person in the network would benefit from the growth of the network. The hope was that this feature would gain a viral quality.

Friends placed immense pressure to release the product as soon as humanly possible under the theory that doing so would reveal the 70% of my design that was wrong, so I divided Unearthed into three releases. The app itself has three game modes, each incrementally accessible as a given region “levels up” from users’ data uploads. I would have time to release the latter modes while the first mode of the game, the most casual mode where users look around where they stand and scan for anomalies, was being played.

In App Purchases and Ads

Screen0.jpgConsidering the App Store was flooded with free apps and that I had no name in the industry to immediately convince users to immediately pay for my app, I concluded that the most likely approach for success was to release a free app with In App Purchases. This appeared to be the best way to get as many users to at least try the app and decide how much they wanted to spend to access more functionality. Initially, I offered the following items:

  • All content, present and future ($5.99)
  • Scanner upgrades level 2-3 ($1.99)
  • Scanner upgrades level 4-5 ($1.99)
  • Bounty Mode (coming soon) ($1.99)
  • Blitz Mode (coming soon) ($1.99)

However, I hit a snag with Apple’s terms which did not permit me to even mention any features that were not yet implemented. The first item was intended to be a bulk pricing investment in the forthcoming completion of the app, and the ‘coming soon’ items were just client-side displays to tease of the future modes (not actually registered products in the IAP servers). Because I had to remove them, I revised my IAP content to the following:

  • Scanner upgrades level 2 ($.99)
  • Scanner upgrades level 3 ($.99)
  • Scanner upgrades level 4 ($.99)
  • Scanner upgrades level 5 ($.99)
  • Scanner upgrades 2-5 ($2.99)

The app essentially gives users access to all features of the game, but with a lowly basic scanner that doesn’t boast the speed, range, and creature clearance levels of a fully boosted scanner.

I added Greystripe’s ad system as a means to offset the cost I might incur from using Google App Engine as my server solution. Considering the large amount of rank tracking required by my app, I estimated the revenue from ads to break even with the cost of using App Engine.

Release and Reception

The app was approved in the early afternoon of June 21st, a Monday. Excited, I quickly moved up the release date and it hit the stores later that afternoon. One week later, the sales are dismal, with about 400 total downloads and only a handful of purchases.

UnearthedWeek1.jpg

I considered possible contributors to this could be the following (in order of impact):

  • Requiring 3GS
  • Releasing 4 days before the iPhone 4 (dropping off New Releases)
  • Requiring OS 3.1.3 (instead of 3.1)
  • Releasing the app in the late afternoon (dropping off New Releases faster)

Without knowing the specifics on the sales of the 3GS versus the 3G and the iPod Touch, the fraction of 3GS users able to even see my app in the store might be a small fraction. Unnecessarily releasing under an OS that prevented users from installing unless they went back to iTunes to update their OS was likely a dealbreaker for browsing users (quickly remedied but days later). And considering how many of the 1.5 million users would be browsing the App Store for free apps Thursday, releasing a few days too early may have been the biggest avoidable mistake yet.

Moving Forward

As uninspiring as it was getting only a few hundred downloads and enough revenue for lunch, I had heard that word of mouth was a powerful vehicle, possibly the best vehicle, for an unknown developer, so my plan is to continue giving it more time and implement the GPS-enabled Bounty Mode which will take considerably less time, possibly a short 1-2 months. One week is certainly not a large enough measure of success, and already I’ve received a few responses from blogs willing to write reviews, so I’m hopeful of seeing the userbase grow and eagerly anticipating the next big server issue. In the coming weeks, there will definitely be no “sitting back while the cash rolls in”, as I recently had the blessing/curse of another inspiring must-create iPad app revelation and am sweating bullets designing and scoping while scheduling in work on Unearthed, all the while keeping a grave eye on the lifeline of my business.

Looking back at the struggling decision I made to quit my job, I’m reminded of some advice that was given to me beforehand. “Quitting your job will be the hardest decision, but it will make you feel great.” And like an enormous burden lifted from me, it did. And to this day, with earned lunch money in hand, it continues to.

Increase Your App Ratings On The App Store

Every iPhone developer fears the one-star-on-uninstall rating. I understand Apple’s reasoning for adding the prompt for rating on uninstall, but since that’s the only time users are prompted, it becomes a very biased, negative rating. There may be hundreds of users happy with your app who never rate it on iTunes, but everybody who uninstalls it gets asked to give it a review. That’s quite unfair from the developer point of view.

First one bit of good news: That prompt-on-delete feature seems to be gone on iOS 4.0. That should make everybody happy. Even so, taking a pro-active position on this can only benefit developers.

Next a personal opinion without any real hard data to back it up: I don’t think App Store ratings matter very much. I see plenty of quality, 5-star apps that never go anywhere, as well as horrible apps with close to 1-star rating on the top 10. I’m sure good ratings help a bit, but not as much as some people may think.

One of the little features I snuck in the latest update of Flower Garden, was a prompt to rate (or re-rate) the app. This idea isn’t new, and I’ve seen quite a few apps doing it already. I think it makes a lot of sense and provides rating that is much more balanced and representative of how users feel about the app.

You have to be careful about how you prompt users though. This are the priorities I had in mind when I implemented the rating prompt in Flower Garden, roughly in order of importance:

  1. Don’t be annoying!
  2. Disrupt the user as little as possible
  3. Make rating the app as easy as possible.
  4. Prompt at every update.

fg_prompt.jpg

Don’t be annoying

This is by far the most important priority. If your prompt for review is annoying, you might get more angry users and one-star reviews than you would have without it. Be respectful of the user and don’t nag.

For quite a few versions, I’ve had a review button in the “Feedback” tab in the settings screen. Not many people use it or even know about it because it was several taps away from the normal flow of Flower Garden. That’s an example of a feedback prompt that is too unobtrusive. Clearly, I needed something a bit more noticeable.

What I did was to add an actual alert view with the prompt. That alert comes up very infrequently, and gives users the option to either rate it right away, be reminded later, or just stop asking altogether. Many more users rated the app through this mechanism (and I haven’t gotten a single complaint about it being annoyed yet–keeping my fingers crossed).

Disrupt the user as little as possible

First of all, you should never ask the user to rate the first time they launch it. They haven’t had a chance to check it out yet! Give them a few days (or a few launches of the app). That will benefit you in two ways: users will have a better chance to give an honest rating, and users who didn’t like your app probably won’t be around in two days, so they’ll never see the prompt.

Second, choose a good time to ask. Please, don’t ask me as soon as I launch the app! Chances are I want to do something with it, so being pestered with a review prompt is disruptive, especially because adding a rating involves leaving the app and going to iTunes. At the same time, don’t ask me in the middle of a level or when I’m engrossed in game. A good moment to ask for a rating would be after completing a level or two, or, in the case of Flower Garden, after sending a bouquet.

For extra bonus points, catch the user on a “good” moment. Maybe only ask them to rate the app if they actually beat the level. They’ll probably leave a better review than if they just lost and are in a bad mood.

The exception I made was if a certain amount of time went by and the user never got to the point of being prompted (some people just don’t send bouquets in Flower Garden). In that case, I will ask at startup or at some other, non-ideal point.

Make rating the app as easy as possible

This is the funnel principle at work. For every action the user has to do in order to leave a review, the fewer users will actually do it. It would be ideal if users could rate the app directly from the alert box. That would involve no extra actions (or leaving the app) and would result in the maximum number of ratings [1]. Unfortunately, that’s not the case, so we have to do the best we can with what we have.

So we want to minimize the amount of actions from the moment the user taps “Rate now” until they can enter the rating. We could send them to the product page on the App Store, but that would still involve them scrolling around, finding the rating button, tapping it, and entering the rating. We can do better than that: We can send them directly to the rating screen. Check out this great post for a dissection of iTunes links and how to create one to the review page. Make sure the technique you choose works on an iPhone (not all of them do!).

Prompt at every update

This one is easy: Just store the number of the last version the user wrote a review for, and if it changes, start from scratch again. That way you don’t have to write any custom code at every release. Also, make sure to respect the “Don’t ask anymore” option if the user selected that in a previous update.

Source code

Here’s the review request source code (released under the MIT license). It consists of only two standalone files, and all the review state is kept in the default, global settings. There are only three functions and it should be very self-explanatory:

	bool ShouldAskForReview();
	bool ShouldAskForReviewAtLaunch();
	void AskForReview();

The ShouldAskForReviewAtLaunch() function simply adds an extra condition of launching it X number of times before asking for review (this is in case the user never triggers the review condition).

Results

Does this prompt for ratings work? This is a screen grab from iTunes 5 days after Flower Garden 2.4 was released:

fg_itunes_ratings.png

A few interesting observations:

  • Ratings are higher than they were before. Before the free day, Flower Garden had an average of 3.5 to 4 stars.
  • Reviews are often shorter and less useful than unprompted reviews. There are a lot of 5-star “I love this app!” reviews without much more substance. (I’m not complaining, really).
  • Still a huge number of users chose not to leave a review. There are only 148 ratings, but there have been 30,000 upgrades to the latest version. A lot of people might have upgraded and not launched it, but even so, it’s a very small percentage.

Overall, it was a very small time investment and the results show it was definitely worth it. I’ll be using this approach in my future projects (unless future iOS versions take care of it automatically somehow).

[1] Apple, can we fix that? How about a REST API for leaving ratings and reviews? Pretty please?

Making A Living (Comfortably) On The App Store (aka The Numbers Post #2)

A few months ago, I wrote a post analyzing how Flower Garden had done since it was released. It was a story with lots of ups and downs, tales of trials and failure, but ending on a positive, optimistic note. It went on to become one of the most read posts in this blog, and the comments were all very encouraging. Clearly, people, and especially other developers, are hungry for this kind of data.

So here we go with the second part. How did Flower Garden fare after the new year? Was it just the Christmas purchasing frenzy that had a momentary effect on sales, or was there something more to it?

Recap and Overview

Here’s where we left off last time. The unusual part was how profits increased as soon as I added in-app purchases to Flower Garden in early December. It made for a very atypical sales plot.

Full

And here is how things look now. This plot includes the previous data so it’s easier to contrast before and after. The area in blue is the new data since the last post.

fg_total.png

Just glancing at that chart makes it clear that that the increase around Christmas wasn’t a fluke. It actually wasn’t even done going up. After all the spikes, and the weekly ups and downs, Flower Garden ended up settling to about $1,500/week. And that, even in California, I would consider it to be a comfortable living. What a different from the $50/day it was making last year!

So what exactly happened there? Let’s look at the new data in more detail.

fg_recent.png

At a glance, there are three, very different sections.

The Feature

The first one starts with a significant increase in sales (A), and is in large part due to being featured on the App Store worldwide as a Staff Favorite. It’s a nice spike, but it’s nothing like the x10 spikes other developers have seen with App Store features. That’s because the Staff Favorite slot, even though it’s a very prestigious one, it does not appear on the iPhone, only on iTunes. I do all my browsing and shopping through iTunes, but apparently I’m in the minority, so the effect on sales is greatly reduced.

That spike is also in part due to my last “numbers post”, which happened right at the same time (not completely accidentally). The page attracted about 15,000 views in a few days, so I’m sure a few of them translated in people checking out Flower Garden out of curiosity.

Valentine’s Day

The second spike isn’t hard to guess: It’s the weekend of February 14th, Valentine’s Day. The more things happen at once and the more something is in the public eye, the more of an impact it has. PR people have known that for a long time, and it was really brought home for me back in December.

Fortunately, I managed to make quite a few things happen in the days leading to Valentine’s Day weekend:

  • I released an update with couple new in-app purchases: A new set of seeds (Seeds of Love), and a greenhouse garden, for $0.99 each.
  • I sent out a newsletter to the 25,000 subscribers to the mailing list announcing the new items.
  • I put Flower Garden on sale for $0.99 (down from the regular price of $2.99).
  • Several web sites, including TouchArcade, covered the sale and the new update, giving it lots of visibility.
  • Flower Garden Free was the free app for February 14th on the Valentine’s Day Calendar.

All of that combined to cause the big spike in profits (B). You really need to look at the first plot to put it in perspective. Two days in around Valentine’s Day had higher profit than the initial release spike back in April of last year!

Winding Down

Of course, everything that goes up, must eventually come down. So the weeks following Valentine’s Day profits went rapidly down. It was at the very end of April that I started working on Lorax Garden, so for that period of time I wasn’t able to do anything related to Flower Garden. For a while sales were dropping quite rapidly, but they eventually flattened out to about $1,500/week (C).

The good thing about having consumable items as in-app purchases (fertilizer in this case), is that profits are related to active user base, not just initial sales. So even though the amount of downloads decreased significantly during this time, the user base had grown a large amount, and with it, the daily profits.

Flower Garden Free

Back in December, there seemed to be a connection between the amount of downloads of the free version of Flower Garden and profits. They both picked up right around the time I added in-app purchases, although I was never able to tell if it was cause or consequence.

This is the amount of downloads of the free version for this period of time.

fg_free.png

It stays pretty regularly at about 800 downloads per day (which is not much compared to a lot of free versions out there), and has a massive spike on Valentine’s Day (caused by word of mouth, lots of sent bouquets, and the Valentine’s Day Calendar).

Notice that the App Store feature for Flower Garden (full version) in January had virtually no effect on downloads of the free version. It seems that people are willing to buy something full price without trying the free version first if Apple features it.

Both versions of Flower Garden (free and full) have in-app purchases in them. Even though there’s a higher percentage of users with the full version that buy in-app purchases, the free version is much more popular and the majority of the revenue comes from the free version (orange). This is a tren that was already noticable around the holidays, but now is much more clear, with over 50% of the revenue coming from in-app purchases in the free version.

iap_profit.png

The Future

The data for this post stops at May 5th. That’s because on May 6th I released a new set of seeds and gave Flower Garden away for free as part of the Mother’s Day promotion. As soon as the dust settles from that, I’ll write a third post detailing how it turned out.