Lessons Learned In Using Microsoft Ads
Yesterday ended my first month of being an active Windows 8 app publisher. The way I define “active” is that I have been consistently working to improve it since its launch. There are many apps that are thrown into any marketplace, never to see an update of any kind. In the first month, I shipped EIGHT updates.
Mind you, the first couple of updates were meant to solve two specific problems:
1) Address a couple of small bugs I had identified.
2) Get the Microsoft Advertising Control to actually work in my app.
Every app is going to have a bug or two, and there’s nothing terribly interesting about those, but the ads WERE tricky. I created my ad units at PubCenter (which as it turns out, is not a place to find a frosty pint.) I added an AdControl to the pages of my app using the identifiers from my ad units. But they didn’t show up in my app when I published it. In fact, after I published the first time, they didn’t show up in my development environment anymore either.
Being Lazy Was a Problem
One of the consistent pieces of feedback I had given developers was to uncheck the “Internet” option in the app capabilities if you weren’t using it. Having that box checked also requires you to publish and include a privacy policy, and being lazy and averse to legalese, I decided my poker app, which didn’t have any need to connect to the internet, would not get this box checked. (Of course, you do this right before you publish, not realizing you’re breaking everything.)
I opened a support ticket with PubCenter, and after a couple of days of trading emails and eliminating the obvious problems, they simply asked to see my code, if possible. I pointed them to my github repository, where they identified that I had turned off “Internet” capabilities, and the AdControl needs this to serve ads.
Looking back, this is one of the most obvious statements I have ever written.
At the time, however, I seemed to me that the AdControl would probably have its own mechanisms for serving ads, and that they weren’t dependent on my app’s settings. WRONG.
Anyways, once I flipped that switch on March 8th, the ads started showing up, and much to my surprise, I started making a little money.
Let’s Define “Making Money”
In the first few days after the ads started working, I averaged about $1.30 a day. Not retirement money by any means, but my expectations were in the pennies a day range. A dollar or more seemed HUGE. Here’s a chart of my first month:
As you can see, March 18th was a huge day, grabbing me $4.55 that day. I thought this thing was just going to take off. As it turns out, that was my first day in the “New & Rising” category, and the shine slowly faded on that $4+ day. Regardless, I’ve been consistently averaging more than $2 a day, which would be over $700 annually. Not a fortune, but now I’ve got a baseline to start from, and I’ve got big plans to elevate that number over time.
What About eCPM?
The important number in the mobile app game is something called eCPM. If you haven’t seen this term before, everyone uses is, but nobody really seems to define it. eCPM means “effective cost per thousand impressions.”
In simpler terms, this breaks down to the amount of money you made for every 1,000 times an ad was shown. For the month of March 2013, my eCPM fluctuated as I was adding users, and ended up at an average of $0.73. This number seemed a little low, until I looked at where I’m hovering each day lately:
Day to day, I’m averaging about $2.30 for my eCPM. Since I’m averaging around 1,000 impressions per day, it makes sense that I’d be making about $2.00 a day. (I’ve had peaks of 5,000+ impressions in a day, but lately it’s been more in-line with 1,000 per day.
So What’s Next?
My plans for the future are pretty simple: drive more impressions per day. One idea I have for this is to offer a prize to users who hit a royal flush in the game. This should incentivize people to play more, in the hopes they’ll win the prize. I need to determine whether or not this is really legal, as well as whether or not it’s permitted in the Windows Store.
Another one is to make it more simple, and just reward those players that play more than a specific number of video poker hands each month. Something like 10,000 hands.
In either case, I’m looking for ways to get more players to play more often, to drive up the number of impressions I’m getting each day, which should also drive up the amount of money I’m making each day.
I’ll keep you posted on how this all works out.
Lessons Learned From Rushing To Market
I’m still working on my Windows 8 application, King Poker, and have I learned some things this week. (It’s also available for Windows Phone, btw.)
In general, my app is pretty straightforward. It’s a video poker application designed to look as similar to the real video poker machines in casinos as it can. Last week, I got ambitious, and decided to add some functionality that goes above and beyond the core functionality you’d expect.
I added Azure Mobile Services, and if the user was online, every single hand was recorded to my cloud storage database. In the 10 days it’s been live, I’ve recorded over 45,000 random hands of video poker to my database.
In addition, I added Microsoft Account authentication, which means that if you log in with your Microsoft credentials, I could persist your credit count and hand history across all of your devices. This is where the story gets ugly.
I spent HOURS writing and testing this functionality. Log in on my Surface RT. Play some hands of Deuces Wild. Log out. Keep playing. Log in. Play some more. Cut the wi-fi connection. Play some more. Reconnect. Sync the hands that were played when disconnected. Log in to the Windows Phone 8 version. See the identical credit count. If you were logged in to these apps, everything worked marvelously.
When you weren’t logged in, it still worked marvelously. It still logged your hands in my cloud database. My mistake was that I didn’t notice that even when you were logged out, it was trying to sync your credits. Anonymously.
So I pushed this new update chock full of new features to the store. And it passed. I was so excited! And then the negative reviews started flowing in.
“Used to work well on RT. Last update broke it. Lost all my money, well pretend money anyway. Please fix it”
“This is a great poker game. Play it all the time. However installed update yesterday and now it crashes all the time.”
“Credit counter still going crazy...Change the word HELD...back to HOLD, like in Vegas and Atlantic city...”
As it turns out, everyone that wasn’t logged in was synching their credits with everyone else that wasn’t logged in. Ouch.
I’ve been really careful about thorough manual testing, as well as running a full suite of unit tests, but this one got by me. I was so focused on what the experience was like for authenticated users, I didn’t give enough to time to think through all of the scenarios for those people that chose not to authenticate.
I fixed it immediately, but it was Friday night, and the Windows Store team doesn’t approve apps on the weekends. It wasn’t until Monday afternoon that my new patch was finally released, and almost immediately, I found yet another issue. (It’s funny how much more obvious bugs are when they’re in production vs. development.) I now have to wait at least another day before this issue will finally be solved.
Take Your Time
My point in all of this is to take your time. I was so anxious to get my new set of features into the hands of my users, I completely neglected to remember that apps that have to go through stores are SIGNIFICANTLY harder to fix than a simple website. If I find an issue on my website, I can fix it instantly. In your app, your users may have to suffer through days or bugs before you’re able to fix an issue. Take your time, get it right, and give your users the experience they deserve. It’s the only way you’re going to get MORE users.
In short, no matter how great your set of features is, a little extra diligence to think through ALL of the user scenarios will benefit everyone in the long run. That’s how you build a great app. Keep your users’ confidence high, and give them a reason to tell their friends about it.
If you’d like to
Lessons Learned About Capturing Keystrokes in Windows 8
It would appear I’m going to start pumping out little “lessons learned” articles over the next few weeks, as I’ve learned an absolute TON from building my King Poker app. Today’s lesson is about capturing keystrokes.
Many of you have probably done this before: you want to recognize a specific key that has been pressed when a user is entering something into a TextBox. Maybe you want to take action when they press the Enter key, for example. This is generally simple enough, you just set up a KeyDown (or KeyUp, depending on your needs) event on the TextBox in question, and then just check every time the event fires until you find the key you’re looking for.
That’s not what I wanted to do.
To give you some context, here’s a screenshot of my app:
For the cards in question, I want to hold the three Queens, and then re-deal, hoping to get the 4th Queen, or maybe one of the Wild Deuces. (If I’m very lucky, BOTH!)
As the game currently stands, it is designed for use on a touch screen or with a mouse. Clicking/tapping on a card will mark it as “HELD,” and won’t replace it when you click the “DEAL” button. But you have to actually move your fingers or mouse to each card to mark them. For speed players, they’d prefer physical buttons that can be pressed over having to touch a screen.
This is where my key capture needs come in.
I don’t have a control that I can just drop a KeyDown event on. I want to be able to monitor keystrokes at all times. For this, we can simply wire up an event in the code-behind file, and capture it there. Here’s what it looks like:
protected override void OnNavigatedTo(NavigationEventArgs e)
{
Window.Current.CoreWindow.KeyDown += CoreWindow_KeyDown;
}
void CoreWindow_KeyDown(Windows.UI.Core.CoreWindow sender, Windows.UI.Core.KeyEventArgs args)
{
switch (args.VirtualKey)
{
case Windows.System.VirtualKey.Number1:
if (HoldRound) HoldCard(Card0);
else SetBet(1);
break;
case Windows.System.VirtualKey.Number2:
HoldCard(Card1);
break;
case Windows.System.VirtualKey.Number3:
HoldCard(Card2);
break;
case Windows.System.VirtualKey.Number4:
HoldCard(Card3);
break;
case Windows.System.VirtualKey.Number5:
if (HoldRound) HoldCard(Card4);
else SetBet(5);
break;
case Windows.System.VirtualKey.Space:
Deal();
break;
}
}
protected override void OnNavigatingFrom(NavigatingCancelEventArgs e)
{
Window.Current.CoreWindow.KeyDown -= CoreWindow_KeyDown;
}
As you can see above, I subscribe to the Window.Current.CoreWindow.KeyDown event, which fires before anything else gets access to the key event. This is also a great way to capture keystrokes before they get to your TextBox controls, etc.
Once I’ve got this event rigged up (and un-rigged it with my OnNavigatingFrom event), I can now easily provide physical keys for my power users by enabling the #1 - #5 keys to hold the cards rather than having to move their mouse all over the screen. In addition, I’ve also set the Spacebar up to provide “Deal” functionality, which means they never need the mouse once they start playing the game. Here’s a look at the cards held:

And finally, in case you were wondering, here’s what I drew (I got that wild 2) to get my four of a kind!

Summary
So there you have it. A simple way to capture keystrokes in C# and XAML applications for Windows 8/Windows RT applications. Many apps have a need for this in some way (even if it’s to provide a shortcut or even an Easter Egg), so consider this in your applications as well.
What I Learned In WP7 – Issue 17
Man, things have been crazy. I’ve got six apps in the marketplace right now, and going strong on about 7 more ideas.
I was asked today if there is an official “Download My App From the Marketplace” icon that we should use when linking to our applications from the web. Turns out, there IS! You can download the whole series here, but I’ve included a few examples below for you to check out.
What I Learned In WP7 – Issue 16
Yesterday, I had a developer reach out to me about a seemingly simple problem, but it wasn’t until I looked at it in a greenfield project that I could solve it quickly. In the XAML below, I have a ListBox that I bind a List of objects to. What the developer was trying to do was get the text in the “AlternateText” TextBox for the item clicked.
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"> <ListBox x:Name="masterList" SelectionChanged="masterList_SelectionChanged"> <ListBox.ItemTemplate> <DataTemplate> <StackPanel Orientation="Horizontal"> <Image x:Name="ActionImage" Source="{Binding ActionImage}" Width="100" Height="100"/> <StackPanel> <TextBlock x:Name="ActionText" Text="{Binding ActionText}" FontSize="40" Width="300" /> <TextBlock x:Name="AlternateText" Text="{Binding ActionDescription}" /> </StackPanel> </StackPanel> </DataTemplate> </ListBox.ItemTemplate> </ListBox> </Grid>
The important thing to remember here is that when you call the SelectionChanged event on a ListBox, the ListBox still recognizes each item as its original object. Therefore, you should actually be trying to access the specific object that was selected, and then access the properties of that object, instead of the XAML elements that make up the ListBox’s layout.
Here’s the solution we implemented, where TestClass is the object type we’re using:
private void masterList_SelectionChanged(object sender, SelectionChangedEventArgs e) { ListBox testList = sender as ListBox; TestClass testText = (TestClass)testList.SelectedItem; string whatImLookingFor = testText.AlternateText; }
What I Learned In WP7 – Issue 15
I learned something about pricing your applications in the Windows Phone Marketplace today that I never expected. (Keep in mind this entire article is based on my sample size of ONE, but it’s an interesting thought exercise.)
Trial Mode might actually HURT your sales.
Let me explain: I have been very diligent with my applications in the marketplace to make sure that they offer a compelling Trial mode to my users. I want them to download it, and try it, so that they will ultimately buy it. None of my applications are crazy addictive, or something that I thought would sell millions of copies. Not by a long shot. But I did think that I would sell SOME.
In fact, I am selling some. Maybe 5 copies a day across all three of my paid applications (5 total, not 15). Probably right in line with what I expected for the time/effort I put into some of these applications. But I tried an experiment recently, and it had interesting results.
I am speaking at the CodeMash conference this week, and in one of my sessions, I am building a simple Twitter app alongside an iPhone developer and an Android developer. We each get 15 minutes to build the same application. (In other words, it’s incredibly simple.)
I decided it would be cool to have the application I was building for the session be available for download after the session, so I submitted it to the Marketplace over the holidays. I had no trouble getting it submitted, but I decided to price it at 99 cents, with no trial mode (conversely, the rest of my applications offer limited functionality in Trial mode.)
Twitter Stalker (the app I’m talking about) sold 5 copies on New Year’s Day. And has continued to sell at a higher rate than my other applications. It’s description even says that “This is an application that was built as a demonstration at the CodeMash conference in Sandusky, OH on January 13, 2011.”
Conclusion
Now, I know that there are numerous factors that go into something like this, and one anomaly does not mean correlation. For example, people might just be looking for a new Twitter client, and willing to spend the 99 cents to find out if it’s good. On the other hand, if I had offered a trial mode, then they certainly would NOT have spent the 99 cents afterwards. The app is really nothing special.
So, here’s your food for thought:
When building a simple application, is it more important for your users to LOVE your application? Or is it more important to you that they BUY it?
I propose that if you’re building something simple, that can easily be explained in your description, perhaps a Trial mode isn’t something you should offer. Perhaps people would be willing to pay 99 cents to find out if your application is what they’re looking for. By offering a trial, you’re actually giving them the chance to NOT like it.
What do you think?
What I Learned In WP7 – Issue 14
I’ve been working on some dynamic Panorama designs, but there were a couple of things I was finding tricky:
1) Loading a Panorama control at a specific position. (also just navigating to a different place in one.)
2) Preventing a Panorama from wrapping around from the last to the first element.
In the first case, I just wasn’t looking in the right place. To change which panel of a Panorama you are viewing, you can use:
Panorama.DefaultItem = Panorama.Items[index];
For the second case, you might be asking WHY I would want to prevent the Panorama from wrapping around, which is the default behavior. In my application, when you first come to the Panorama control, you only have ONE PanoramaItem. So scrolling is more confusing than anything else. As you continue to enter data into the app, however, the Panorama can grow to as many as 10 Panorama items.
The short story on this, however, is that it’s not really possible. If you need to change the Panorama’s behavior that drastically, you might want to look at using a different control.
What I Learned In WP7 – Issue 13
I had intended to do a whole year-end wrap-up, but just never got around to it. Expect something like that in January sometime. In the meantime, the folks over at Technobolt put together a neat little infographic about all of the Windows Phones that are currently (or anticipated to be) available.
Have a great New Year, and let’s kick 2011 off strong. What are you planning to build in 2011?
What I Learned In WP7 – Issue 12
Someone asked a question on StackOverflow today about the RGB colors for each of the default colors on Windows Phone. I’ve answered it there, but I’m also publishing it here (along with the Hex values), so you have it for reference.
| Color Name | Hex Value | RGB Value (R,G,B) | Visual |
| Magenta | #FF0097 | 255,0,151 | |
| Purple | #A200FF | 162,0,255 | |
| Teal | #00ABA9 | 0,171,169 | |
| Lime | #8CBF26 | 140,191,38 | |
| Brown | #A05000 | 160,80,0 | |
| Pink | #E671B8 | 230,113,184 | |
| Orange | #F09609 | 240,150,9 | |
| Blue | #1BA1E2 | 27,161,226 | |
| Red | #E51400 | 229,20,0 | |
| Green | #339933 | 51,153,51 |
What I Learned In WP7 – Issue 11
I am currently learning a ton about MVVM and testing on Windows Phone. If you are just starting to build an application, I highly recommend checking out Jeff Wilcox’s post about his Silverlight Unit Test Framework. (jeffwilcox.com)
You’ve certainly used a ListBox control before, but you’ve likely been pining for a ListBox that allows drag-and-drop re-ordering. Jason Ginchereau has created one, and made it available. Check it out on his blog. )(Jason Ginchereau’s blog)









