Location aware ads?

Jun 17, 2011 at 6:48 PM

back in adMob i used to grap user location and pass it to add control to push more relevant ads. is there a way to do something like that with Ad Rotator?

Jun 19, 2011 at 11:02 PM

That's something that's really down to the 3rd party ad controls that AdRotator uses. As far as I know there's no way to pass this information on to AdMob and the other providers: some will actually do it themselves, e.g. the PubCenter control does it (thus when adding AdRotator to a project it will ask the user to enable location).

Currently the 3rd party ad providers that AdRotator utilizes don't really have much configuration that can be passed on, except probably for InnerActive (but you can't even pass location data to them directly).

Jun 23, 2011 at 1:35 AM

Having the PubCenter control (dll) as part of a WP7 app/game does not by default ask the user to enable location data collection, I have 3 games and none of them prompt the user.  The user is only prompted for such info if you explicitly set the control to collect location data.

Jun 23, 2011 at 9:41 PM

I've just had an app fail in the marketplace certification using this control based on 2.10.5 and 2.10.7 - I've done nothing unique to the control other than using the sample - customizing for a few locals - and plug in PubCenter/AdMob/AdDuplex values. Are any of these enabling location services by default? I could not find that value I've run CapDetect on it and it is returning ID_CAP_LOCATION. Does anyone know how to disable all location services for this control - or are using cultures considered location services?

Jun 23, 2011 at 10:04 PM
Edited Jun 23, 2011 at 10:10 PM

Im not using this, but, I do have the following line in my code (which gives me one of the same 5 codes listed on this rotators documentation page.

var phoneLocation = System.Threading.Thread.CurrentThread.CurrentCulture.Name;

 

I ran CapDetect and the output was the following (I use the pubCenter SDK and AdDuplex SDK.....both XNA)

ID_CAP_NETWORKING
ID_CAP_MEDIALIB
ID_CAP_IDENTITY_DEVICE
ID_CAP_IDENTITY_USER
ID_CAP_PHONEDIALER

I rolled my own version of this tool, mainly because I wanted to and there are no XNA dll's from AdMob or MobFox....so its PubCenter or AdDuplex.  I simply return a string from a php file on my server telling my app which ad server to use based on the culture name passed to the php script.  My app handles exceptions and timeouts and can scale to include other ad providers when they become available, of course with an app update.

 

PHP

 

<?php
session_start();
//sleep ( 15 );
$q_version=$_GET['v'];
$q_region=$_GET['r'];


if ($q_version == "1")
{
	if ($q_region == "en-GB")
		echo "PubCenter";
	else
		echo "AdDuplex";
}
else
	echo "AdDuplex";
	

session_destroy();
?>

 

C# App, web request specific (doing manual rotation, you need to check the "adType" during your Update method...

void WebRequestAdManager(string culture, string version)
        {
            var url = @"http://YOUR-WEB-SITE.com/services/ads/adManager.php?v={0}&r={1}";
            string webServiceAddress = String.Format(url, version, culture);
            HttpWebRequest httpWebRequest = (HttpWebRequest)HttpWebRequest.Create(webServiceAddress);
            httpWebRequest.Method = "POST";
            Utils.Trace("GAME Ad Manager REQUEST");
            httpWebRequest.BeginGetResponse(WebRequestAdManager_Completed, httpWebRequest);
        }
        void WebRequestAdManager_Completed(IAsyncResult result)
        {
            Utils.Trace("GAME Ad Manager RESPONSE");
            try
            {
                HttpWebRequest request = (HttpWebRequest)result.AsyncState;
                HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(result);
                using (StreamReader streamReader = new StreamReader(response.GetResponseStream()))
                {
                    string adResponse = streamReader.ReadToEnd();
                    if (adResponse == "AdDuplex")
                        adType = Enums.AdControlType.AdDuplex;
                    else if (adResponse == "PubCenter")
                        adType = Enums.AdControlType.PubCenter;
                    else
                        adType = Enums.AdControlType.AdDuplex;
                }
            }
            catch (Exception ex)
            {
                adType = Enums.AdControlType.PubCenter;
            }

        }

C# - this should be called after you app is done loading and during your game loop so the sdk doesnt slow down the loading.  Also, I do late binding hence the full namespace that way the sdk dll's dont load until well after the app/game becomes usable (really only a second or 2, but every second counts with load times).

private void GetNewAd(GameTime gameTime)
        {
            //get new ad
            if (showAds)
            {                
                if (adType == Enums.AdControlType.Unknown)
                {
                    var phoneLocation = System.Threading.Thread.CurrentThread.CurrentCulture.Name;

                    if (phoneLocation == "en-US")
                        adType = Enums.AdControlType.PubCenter;
                    else
                    {
                        //call web service and find out what ad to get
                        //takes culture as a parameter, version as parameter
                        var version = GameConstants.APP_ADSDK_VERSION;
                        adType = Enums.AdControlType.Fetching;
                        adManagerReqeustedElapsed = new TimeSpan();
                        WebRequestAdManager(phoneLocation, version.ToString());
                        Utils.Trace("GAME Ad Manager REQUESTED");
                    }
                }

                if (adType == Enums.AdControlType.Fetching)
                {
                    adManagerReqeustedElapsed += gameTime.ElapsedGameTime;

                    if (adManagerReqeustedElapsed.TotalSeconds >= 10)
                    {
                        Utils.Trace("GAME Ad Manager TIMED OUT");
                        adType = Enums.AdControlType.AdDuplex;
                    }
                }

                if (adType == Enums.AdControlType.AdDuplex)
                {
                    if (!adDuplexAddedToApp)
                    {
                        adManagerAdDuplex = (AdDuplex.Xna.AdManager)(new AdDuplex.Xna.AdManager(this, GameConstants.ADDUPLEXAPPID));
                        ((AdDuplex.Xna.AdManager)adManagerAdDuplex).LoadContent();
                        ((AdDuplex.Xna.AdManager)adManagerAdDuplex).Visible = false;
                        ((AdDuplex.Xna.AdManager)adManagerAdDuplex).Enabled = false;
                        adDuplexAddedToApp = true;
                    }

                    ((AdDuplex.Xna.AdManager)adManagerAdDuplex).Visible = true;
                    ((AdDuplex.Xna.AdManager)adManagerAdDuplex).Enabled = true;
                }
                else if (adType == Enums.AdControlType.PubCenter)
                {
                    if (!pubCenterAddedToApp)
                    {
                        // Create an ad manager for this game
                        //full namespace reference to make it's dll load after or during the loading screen and not before it
                        adManagerPubCenter = new Microsoft.Advertising.Mobile.Xna.AdManager(this, GameConstants.PUBCENTERAPPID);
                        ((Microsoft.Advertising.Mobile.Xna.AdManager)adManagerPubCenter).TestMode = false;
                        bannerAd = ((Microsoft.Advertising.Mobile.Xna.AdManager)adManagerPubCenter).CreateAd(GameConstants.PUBCENTERAD, new Rectangle(0, 0, 480, 80), Microsoft.Advertising.Mobile.Xna.RotationMode.Manual, false);
                        ((Microsoft.Advertising.Mobile.Xna.Ad)bannerAd).ErrorOccurred += new EventHandler<Microsoft.Advertising.Mobile.Xna.ErrorEventArgs>(bannerAd_ErrorOccurred);
                        ((Microsoft.Advertising.Mobile.Xna.Ad)bannerAd).NewAdAcquired += new EventHandler(bannerAd_NewAdAcquired);                        
                        Components.Add((Microsoft.Advertising.Mobile.Xna.AdManager)adManagerPubCenter);
                        
                        lastAdCall = DateTime.Now;
                        adIsFetching = true;
                        pubCenterAddedToApp = true;
                    }
                    var lastAdSpan = DateTime.Now - lastAdCall;
                    if (lastAdSpan.TotalSeconds >= 40 && adManagerPubCenter != null && bannerAd != null && !adIsFetching)
                    {
                        adIsFetching = true;
                        ((Microsoft.Advertising.Mobile.Xna.Ad)bannerAd).RequestNextAd();
                    }
                }
                else if (adType == Enums.AdControlType.AdMob)
                {

                }
            }
        }

Jun 23, 2011 at 11:53 PM

I've just looked into this - looks like the reference to the InnerActive ad SDK and creating ads triggers the location capability. I'm looking into how to address this - I might temporarily remove InnerActive from the project until this is resolved. Sorry about the inconvenience, didn't realize this was the case!

 

Cheers,

 Gergely

Jun 23, 2011 at 11:53 PM

Hmm...XNA must be different. Running CapDetect on the sample project from this site also gives an ID_CAPS_LOCATION. So does a brand new SL project with nothing but the AdRotator control. I'm trying to determine which DLL it is coming from.

Jun 24, 2011 at 12:10 AM

Yeah, had the same issue... don't forget to build the project in Debug. If the Bin/Debug folder is empty all capabilities are returned and the capability detector only seems to care about contents in the Debug folder otherwise. (At least this was the case for me!)

Jun 24, 2011 at 12:25 AM

CapDetect from both Debug and Release folder are reporting the same thing (again, with a template project with nothing done with it other than adding AdRotator - procedurally if that matters). Capabilities reported are:

  • ID_CAP_NETWORKING
  • ID_CAP_IDENTITY_DEVICE
  • ID_CAP_IDENTITY_USER
  • ID_CAP_WEBBROWSERCOMPONENT
  • ID_CAP_PHONEDIALER
  • ID_CAP_LOCATION
Jun 24, 2011 at 12:27 AM

@gergelyorosz: Just saw your note above about InnerActive SDK - how hard would it be to remove that myself? I'm going through the code now to see if it can just done by commenting stuff out. 

Jun 24, 2011 at 12:30 AM

No, not hard work. However, I've just created a new release that removes the reference to this, you can grab it now.

Jun 24, 2011 at 12:42 AM

Perfect, thank you!!