Encouraging Windows Phone Marketplace Reviews

After a Windows Phone application has been in the marketplace for sometime there will invariably be several reviews of the application, ranging from one to five stars with optional remarks associated with the review.

While there are users who will write a positive review of an application more often than not the users who take the time to write a review may be those users who dislike something about an application.

It really shouldn’t be surprising given this is essentially the same human reaction to the request for a survey you might have from your car dealership, if you’re happy with the service are you going to take the time to complete their online survey? What about if the experience with the service department wasn’t what you would have come to expect?

What we need are tools to help us encourage as many of our users to write reviews within the marketplace as possible, or more accurately, tools to encourage the silent majority of those users that enjoy using the application and would therefore give positive reviews.

Since integrating the MarketplaceReviewRequestor class (see below) into the Windows Phone Stopwatch 4.4 there have been several new reviews posted to the marketplace that are very positive giving the application either four or five stars.

MarketPlaceReviewRequestor Message

Windows Phone Stopwatch 4.4 using the MarketplaceReviewRequestor class.

It is for this reason that I wrote the MarketplaceReviewRequestor class, using this class the user is prompted to write a review for the application after the application has been used at least seven times beginning the following day after it was installed.  If the user decides not to write the review at that time they will be asked one last time after the application has been used 14 times. We don’t want to continue to ask the user again after they have declined a few times as that is likely to encourage the user to write a negative review.

MarketPlaceReviewRequestor

Visual Studio 2010 class diagram showing the MarketplaceReviewRequestor class.

Integrating the MarketplaceReviewRequestor class into a Windows Phone application is as easy as creating an instance of the MartketplaceReviewRequestor within the OnLoaded event handler as shown here:

/// <summary>
/// Handles the <see cref="E:Microsoft.Phone.Controls.PhoneApplicationPage.Loaded"/> event.
/// </summary>
/// <param name="sender">The sender.</param>
/// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
public void OnLoaded(object sender, RoutedEventArgs e)
{
// determine whether to ask the user to review the application.
MarketplaceReviewRequestor requestor = new MarketplaceReviewRequestor();
}

Listing 1 – MainPage.xaml.cs – OnLoaded Event Handler

The full source code for the MarketplaceReviewRequestor class is shown here and will hopefully lead to many more reviews for your Windows Phone applications in the marketplace. The MarketplaceReviewRequestor can also be downloaded from the Windows Phone Marketplace Review Requestor project on CodePlex.

//-----------------------------------------------------------------------
// <copyright file="MarketplaceReviewRequestor.cs" company="Microsoft Corporation">
// Copyright (c) Doug Holland, Microsoft Corporation. All rights reserved.
// </copyright>
//-----------------------------------------------------------------------
namespace CodePlex.WindowsPhone
{
using System;
using System.IO.IsolatedStorage;
using System.Windows;

    using Microsoft.Phone.Tasks;

    /// <summary>
/// Requests that the user review the application within the marketplace after an appropriate level of usage.
/// </summary>
public sealed class MarketplaceReviewRequestor
{
/// <summary>
/// Provides access to settings stored within isolated storage.
/// </summary>
private IsolatedStorageSettings settings = IsolatedStorageSettings.ApplicationSettings;

        /// <summary>
/// Defines a private thread synchronization object for the <see cref="T:MarketplaceReviewRequestor"/> class.
/// </summary>
private object synchronizationObject = new object();

        /// <summary>
/// Initializes a new instance of the <see cref="T:MarketplaceReviewRequestor"/> class.
/// </summary>
public MarketplaceReviewRequestor()
{
if (!this.ApplicationReviewed)
{
this.RequestReview();
}
}

        /// <summary>
/// Gets the <see cref="T:System.DateTime"/> when the application was first launched.
/// </summary>
/// <value>The <see cref="T:System.DateTime"/> when the application was first launched.</value>
private DateTime ApplicationFirstLaunched
{
get
{
if (!this.settings.Contains("ApplicationFirstLaunched"))
{
this.settings.Add("ApplicationFirstLaunched", DateTime.Today);
}

                return (DateTime)this.settings["ApplicationFirstLaunched"];
}
}

        /// <summary>
/// Gets the application usage count.
/// </summary>
/// <value>The application usage count.</value>        
private int ApplicationUsageCount
{
get
{
if (!this.settings.Contains("ApplicationUsageCounter"))
{
this.settings.Add("ApplicationUsageCounter", 1);
}
else
{
int count = (int)this.settings["ApplicationUsageCounter"];

                    this.settings.Remove("ApplicationUsageCounter");

                    this.settings.Add("ApplicationUsageCounter", ++count);
}

                return (int)this.settings["ApplicationUsageCounter"];
}
}

        /// <summary>
/// Gets or sets the number of times the review has been requested.
/// </summary>
/// <value>The number of times the review has been requested.</value>
private int ReviewRequestCount
{
get
{
if (!this.settings.Contains("ReviewRequestCount"))
{
this.settings.Add("ReviewRequestCount", 1);
}

                return (int)this.settings["ReviewRequestCount"];
}

            set
{
this.settings.Remove("ReviewRequestCount");

                this.settings.Add("ReviewRequestCount", value);
}
}

        /// <summary>
/// Gets or sets a value indicating whether the application has been reviewed.
/// </summary>
/// <value><c>true</c> if the application has been reviewed; otherwise, <c>false</c>.</value>
private bool ApplicationReviewed
{
get
{
if (!this.settings.Contains("ApplicationReviewed"))
{
this.settings.Add("ApplicationReviewed", false);
}

                return (bool)this.settings["ApplicationReviewed"];
}

set
{
this.settings.Remove("ApplicationReviewed");

                this.settings.Add("ApplicationReviewed", value);
}
}

        /// <summary>
/// Requests the user review the application.
/// </summary>
public void RequestReview()
{
lock (this.synchronizationObject)
{
// only request the review twice, if the user doesn't want to review don't force a negative review.
if (this.ReviewRequestCount < 3)
{
int threshold = this.ReviewRequestCount * 7;

                    if (this.ApplicationFirstLaunched != DateTime.Today && this.ApplicationUsageCount > threshold)
{
this.ReviewRequestCount++;

                        MessageBoxResult result = MessageBox.Show("would you like to write a review of this application in the Windows Phone marketplace?", "marketplace review", MessageBoxButton.OKCancel);

                        if (result == MessageBoxResult.OK)
{
MarketplaceReviewTask task = new MarketplaceReviewTask();

                            this.ApplicationReviewed = true;

                            task.Show();
}
}
}
}
}
}
}

Listing 2 – MarketplaceReviewRequestor.cs