Prompting a Windows Phone 8.1 user for a review
While writing MiniReader for Instapaper (the introduction blogpost I wrote), I decided I wanted to display a popup to ask the user to review the app after some time (for instance after starting it 15 times). I searched a bit how to do this and since I could not find a "key in hand" solution, I decided to extend the closest one I could find, to work out of the box (e.g. that I can reuse as is in other app - I did already in AShortNotification and PicsSort). This is all for Windows Phone 8.1.
The way it works
It basically tracks down the number of times the app is started (more exactly the number of times you called the ReviewMe()
function, wherever you call it). There are two options:
- "Yes, let me give you some feedback"
- "Sure, but not now"
The popup will be shown every times this number hits a multiple of 15. There is currently no way to check if the user already posted a review. I consider hitting "yes" (and thus going to the store once) enough to stop bothering the user.
Some notes
Beware, the settings are stored in "local-storage", so deploying your app from VisualStudio will reset the counter.
The following code is definietely not the most beautiful code I have written, but I wanted everything to be nicely encapsulated in very few functions that are easy to understand. Thus the lack of flexibility and limited extensiveness.
If you decide to use it, I would start with the Broker as is, then remove the hardcoded strings and magic numbers and add them to a resource and settings file for better localization and control over the strings displayed.
To the code
In order to use it, copy the ReviewBroker
class below in your project, modify the "Static Settings" at the top and call the ReviewMe()
method somewhere in your code... and you are done.
public static class ReviewBroker
{
// Static Settings
private const int reviewMeShowCounter = 15;
private const string reviewDialogTitle = "Review";
private const string reviewDialogContent = "Review me, maybe?";
private const string yes = "absolutely";
private const string no = "not now";
// Settings Keys
private const string askForReview = "askforreview";
private const string reviewed = "reviewed";
private const string startCount = "started";
public static async Task ReviewMe()
{
var settings = ApplicationData.Current.LocalSettings;
//In case the value does not exist yet in the settings store
if (!settings.Values.ContainsKey(reviewed))
settings.Values[reviewed] = false;
//If the user clicked "YES" once already
if ((bool)settings.Values[reviewed])
return;
//Check the number of starts
settings.Values[askForReview] = false;
int started = 0;
if (settings.Values.ContainsKey(startCount))
started = (int)settings.Values[startCount];
started++;
settings.Values[startCount] = started;
if (started % reviewMeShowCounter == 0)
{
settings.Values[askForReview] = true;
await ShowReviewMePopup();
}
}
public static async Task ShowReviewMePopup()
{
settings.Values[askForReview] = false;
var messageDialog = new MessageDialog(reviewDialogContent, reviewDialogTitle);
messageDialog.Commands.Add(new UICommand(yes, null, "YES"));
messageDialog.Commands.Add(new UICommand(no, null, "NO"));
IUICommand op = await messageDialog.ShowAsync();
if (op != null && op.Id.ToString() == "YES")
{
settings.Values[reviewed] = true;
string familyName = Package.Current.Id.FamilyName;
await Windows.System.Launcher.LaunchUriAsync(new Uri("ms-windows-store:reviewapp));
}
}
}
In MiniReader for Instapaper, I call the ReviewMe()
function in the OnLaunched() function of my App.xaml.cs file as follows:
await ReviewBroker.ReviewMe();
The LaunchUriAsync()
function should be called with a simple new Uri("ms-windows-store:reviewapp)
parameter. Unfortunately, this doesn't work when testing from your machine (the app gets a temporary APP-ID when working locally). So for testing purpose you have to use the long form ms-windows-store:reviewapp?appid=[app ID]
. Note that you can also deploy this hardcoded version to the store.
The ShowReviewMePopup()
function is publicly accessible so you can call it directly from a button or so...
I hope this helps, any comments about this, let me know!