Sunday, August 29, 2010

Show Custom In-House Ads in Win Phone 7 with MoAds

One of the problems I've been running into is a lack of ad service providers to get ads from. After putting together a previous post showing the MoAds control using the AdMob Ad Adapter I decided someone might get some use out of creating a custom ad service to serve their own "In House" Ads in their Win Phone 7 application.

Just want the code? Get it here



There is also the sort of unsettling issue of Microsoft's Developer agreement being sort of fuzzy on advertising services (as pointed out by this MobileTechWorld article about MoAds).

At any rate, here's a brief run down of creating your own custom ad service using a new MVC 2 Website and some JSON services.

The Web Services Site - .Net MVC 2

In the example provided, I've created a new .Net MVC 2 website and added an AdController. The AdController is responsible for handling our AdRequests. In this case, we add two methods; Fetch and Click. The Fetch will be responsible for returning the Ad information (ImageUrl, AdText and ClickUrl) and the Click will redirect to the actual Ad Url after recording the client click.

public ActionResult Fetch(string pubId, string clientId = "")
{
    // TODO: You'd probably want to keep track of fetches by PubId for analytics, but this is just a demo.

    var ad = AdRepository.GetRandomAd();
    Impression impression;
    var clickUrl = GenerateClickUrl(ad, out impression);

    ImpressionRepository.Impressions.Add(impression);

    return new JsonResult()
    {
        JsonRequestBehavior = JsonRequestBehavior.AllowGet,
        Data = new FetchResponse()
        {
            ClickUrl = clickUrl,
            AdText = ad.AdText,
            ImageUrl = ad.ImageUrl
        }
    };
}

public ActionResult Click(string id)
{
    // TODO: Track the click for analytics and what-not.

    var impression = ImpressionRepository.Impressions.FirstOrDefault(x => x.Token == id);
    if (impression == null)
        return View(); // TODO: return not found result.

    var ad = AdRepository.GetAdById(impression.AdId);
    return new RedirectResult(ad.AdUrl);
}

Creating a Custom Ad Adapter


The Custom Ad Adapter generally has an underlying service component (in our example it's called CustomAdService) that calls out to some service and gets some ad information, massages the response and fires our GotAdResponse event. Here's a brief run down of what our CustomAdAdapter class looks like.

public class CustomAdAdapter : IAdAdapter
{
    private CustomAdService adService = new CustomAdService();

    /// <summary>
    /// Gets or sets the publisher id.
    /// </summary>
    /// <value>The publisher id.</value>
    public string PublisherId { get; set; }

    /// <summary>
    /// Gets or sets the client id.
    /// </summary>
    /// <value>The client id.</value>
    public string ClientId { get; set; }

    public CustomAdAdapter()
    {
        adService.GotResult += new EventHandler<Service4u2.Common.EventArgs<CustomAdFetchResponse>>(adService_GotResult);
        adService.GotError += new EventHandler<Service4u2.Common.EventArgs<Exception>>(adService_GotError);
    }

    void adService_GotError(object sender, Service4u2.Common.EventArgs<Exception> e)
    {
        if (GotError != null)
            GotError(this, e);
    }

    void adService_GotResult(object sender, Service4u2.Common.EventArgs<CustomAdFetchResponse> e)
    {
        var adResponse = new AdResponse()
        {
            AdText = e.Argument.AdText,
            ImageUrl = e.Argument.ImageUrl,
            ClickUrl = e.Argument.ClickUrl
        };

        if (GotAdResponse != null)
            GotAdResponse(this, new Service4u2.Common.EventArgs<AdResponse>() { Argument = adResponse });
    }

    #region IAdAdapter Members

    public event EventHandler<Service4u2.Common.EventArgs<AdResponse>> GotAdResponse;

    public event EventHandler<Service4u2.Common.EventArgs<Exception>> GotError;

    public void GetAdResponseAsync()
    {
        adService.FetchAdAsync(this.PublisherId, this.ClientId);
    }

    #endregion
}

Hooking up our Custom Ad Adapter in XAML


Once we have our Custom Ad Adapter in place we can plug it in to our AdDisplay control and start serving ads.

<!-- Custom Ad Service example -->
<moad:AdDisplay
    Style="{StaticResource AnimationAdMobStyle}"                
    VerticalAlignment="Bottom"
    Foreground="White"
    RefreshSeconds="30">
    <moad:AdDisplay.AdAdapter>
        <local:CustomAdAdapter
            PublisherId="SomePubId"
            ClientId="SomeClientId"/>
    </moad:AdDisplay.AdAdapter>
</moad:AdDisplay>

And that's about it. Hopefully I'll find some other ad service providers to implement soon. If anyone has any recommendations I'd be happy to hear them.

Grab the updated example source from here or the Project Page at BitBucket (Codeplex is still Garbage).

Now Playing - Notorious B.I.G - Mo Money Mo Problems

4 comments:

  1. hey nice job,
    I have a small problem, when i try to bind some data inside the customAdapter I get an xaml error for bad parsing.

    ReplyDelete
  2. Gonna need to see some code to help you out with that.

    ReplyDelete
  3. I just do a binding in publisherId field in xaml:
    PublisherId="{Binding MyId}"

    ReplyDelete
  4. The PublisherId on the CustomAdAdapter is not a dependency property, so it doesn't support data binding. Is your publisher id something that would change frequently and need to be data bound? If it absolutely must be data bound, I'd suggest modifying the CustomAdAdapter class to inherit from DependencyObject and change the two properties to be dependency properties (the propdp code snippet will help with that)

    ReplyDelete