Editor’s note: We’d like to share this post from Mark Schaaf which announces v5.0.8 of the Google AdMob Ads SDK for iOS. -- Eric Leichtenschlag, Ads Developer Relations Team

For developers who want to run ads in iOS versions of their apps, we are releasing an update to our Google AdMob Ads SDK. This new version of the SDK is consistent with Apple’s reported decision regarding developer usage of the universal device identifier (UDID). Our goal is to help all developers and publishers continue to reach users on mobile, grow their businesses and make money, in accordance with the policies of the mobile platforms on which they build.

Developers and publishers building their businesses on the iOS platform can download the new SDK here. Stay tuned for more new SDK features and updates in the coming weeks.

Posted by: Mark Schaaf, Google Mobile Ads

With the addition of the new test networks to replace the sandbox environment networks, we’d like to do a review of how to test your forecasting on test networks. Since the test networks don’t serve ads, you have no traffic history to provide forecasting data. Instead, the API returns predictable results in the Forecast object so you can effectively test your application.

Forecast Service with Test Networks

The forecast service can be used by calling getForecast with a new line item or getForecastById with the ID of an existing line item. In production, these calls will tell you whether you can expect the line item to deliver the booked clicks/impressions based on how your network’s done in the past. In the test network, the only two parameters that affect the forecast results are the lineItemType and unitsBought fields on the line item. The expected responses are summarized below and in our documentation.

Input (Line Item Field) Output (Forecast Field)
lineItemType unitsBought availableUnits forecastUnits
Sponsorship 50 1,200,000 6,000,000 600,000
prospective: 0
Sponsorship != 20 and != 50 1,200,000 1,200,000 600,000
prospective: 0
Not Sponsorship <= 1,000,000 unitsBought * 2 availableUnits * 3 600,000
prospective: 0
Not Sponsorship > 1,000,000 unitsBought * 2 availableUnits * 3 600,000
prospective: 0

It is a good idea to include a test case where the forecasting service throws an exception so your application can handle error conditions correctly. You can trigger the service to throw a SERVER_NOT_AVAILABLE error by setting the line item type to sponsorship and the units bought to exactly 20.

Dealing with Production Quota

In addition, please be mindful that in production (as opposed to test networks), forecasting is a resource intensive process on the server and too many back-to-back requests may cause the API to throw an EXCEEDED_QUOTA error. When this occurs, we recommend backing off briefly before retrying to bring the requests per second down. Recall that the quotas are based on the number of requests per second rather than an absolute number of requests. You are less likely to get rate limited by the API with a steady stream of requests rather than with short bursts of many requests.

We appreciate any feedback from you regarding features you’d like us to highlight or about the API in general. Please don’t hesitate to leave us a suggestion on our forum or come chat with us at one of our DFP API Office Hours Hangouts.

The Ad Exchange Team is excited to make this set of resources available to our developer community. Below you’ll find new and better ways to work with the Ad Exchange. If you have any questions or feedback, please contact us via the forum.

New website
  • Built on top of Google’s new developers platform, we’ve created a new site for our community. There you’ll find docs for the real-time bidding (RTB) protocol, the REST API and the SOAP API. Plus, we’ve revamped the docs to make them easier to use and understand. 
Access to the Ad Exchange REST API
  • This API gives you the ability to manage your RTB account configurations, submit creatives and list direct deals. Contact your technical account representative to set up access to the API. Then, try it out before you write a line of code, using the API explorer
Client library support and code examples in major programming languages 
  • Trying out the client libraries first might save you a lot of time compared to coding directly against the APIs. Also, check out our code examples in your preferred programming language for both the SOAP and REST APIs. 
Access to the Ad Exchange Buyer API’s Forum 
  • The Ad Exchange Buyer APIs Forum is a Google-monitored environment for public discussions where you can ask - and, if you like, answer - questions regarding the REST and SOAP APIs.


If you are an advanced AdSense Management API user, your application may have run into one of the several different limits we have in place. We’ve created a new documentation page to keep track of system limits, but here’s a small description of what they are and what you can do to avoid them.

API Courtesy Limit

This limit refers to the number of requests your project can make via the API in a single day, across all of your users or AdSense accounts. This is set to 10,000 queries per day for all new projects.

If you’re running into the limit, feel free to request more from the “Quotas” page for your project, in the APIs Console. We’ll look at your request and project usage history, then decide an appropriate limit to set in place.

Page size for “list” calls

The various “list” methods in the AdSense Management API are paginated, with a default size of 10,000 entries per page. You can configure this limit yourself in your request with the maxResults parameter, but you can’t set it to any value greater than 10,000.


For regular, unpaginated reports, the maximum number of rows that the API will return is 50,000. If your report is larger than that, it will be truncated at 50,000 rows.

Pagination in reports should only be used when strictly necessary, as it’s generally only useful to applications running in devices with severe storage constraints. Because of this, paginated reports are limited to 5,000 rows and any attempt to obtain data beyond the 5000th row will return an error.

Let us know in our forum if you have any questions!

We are pleased to announce a better way to develop and test your code with the DFP API. In v201203 you now have the ability to create a test network through a few easy steps. As an added bonus, you can now access the new test and production networks via the normal login screen. Read below for more information on the new self-service way of creating a development test environment for the API.

Create a Google Account
You'll first need a new Google account since you are only allowed one test network per email address. You'll use this account to authenticate with the API when creating the test network. There is no need to worry about your other DFP accounts and whether they have been linked, you only need a valid Google account.

Setup Your Client Library
As stated earlier, this feature is only available in the API so you'll need to set up your preferred client library in your development environment.

Execute the Example Code
Each of the client libraries has an example that you can run with your Google account credentials. This sample code executes the NetworkService.makeTestNetwork() service to create the network. After running this, your network will be ready to use and you will get a printout similar to the message below.

If you instead receive an error with the message
you will need to create a new Google account and try again.

Differences for the Test Network
A test network differs from a production network; in particular, a test network does not serve ads and can not be used in conjunction with any ad tags. As a result, the ForecastService provides mock forecasting information as specified in the documentation. Lastly, a test network offers only small business account features. If you need access to DFP Premium features contact your account manager for assistance.

Client Libraries
Once you've made the transition to a new test network you will no longer need to use the sandbox options in the client libraries. The new test networks utilize the same API endpoint as your production network so you only have to change your credentials and network code when preparing your code for a production release.

Sandbox Deprecation
In the coming months we will be phasing out support for the sandbox networks. Please take the time to migrate to a test network to ensure your testing is not interrupted.

Stay tuned for more DFP API blog posts including one discussing forecasting in the test networks. As always, let us know if you want to see any new features or blog posts on our forum.


One of the less common management tasks in DoubleClick for Advertisers is setting up the sites that host the placements you wish to target. Some questions have come our way recently regarding how to manage sites and when you want to use getSitesByCriteria versus getDFASites. Let’s take a second to clear this up.

There are two types of sites you will deal with in DFA:

  • Site Directory sites are accessible to everyone who can view the Site Directory. These entries contain information about the site that all DFA users share, such as whether the site accepts mobile and/or interstitial placements. You cannot use these sites directly when creating placements.
  • DFA Sites are your own personal pointer to a Site Directory site. They contain settings for interacting with this site that are specific to your account. These are the sites with which you can associate placements.

An additional DFA site has to be mapped whenever you begin creating placements for a new website for the first time. So how do you go about setting these up?

Step 1: Locate the Site Directory Entry For This Site

The first step to creating a new DFA Site is to find the site you want in the Site Directory. You can use the getSitesByCriteria operation for this. Since you cannot use Site Directory sites without mapping them to a DFA Site first, the only time you should use the getSitesByCriteria operation is when you’re looking for additional sites to map into your account. In all other instances, getDfaSites is probably the operation you’re looking for.

// Get the site service using the Google Ads APIs Client Library.
DfaSession session = new DfaSession.Builder().fromFile().build();
SiteRemote siteService = new DfaServices().get(session, SiteRemote.class);

// Get sites which match the URL you are looking for.
String targetUrl = "";
SiteSearchCriteria searchCriteria = new SiteSearchCriteria();

SiteRecordSet siteRecordSet = 

// Find the site with the exact URL.
long directorySiteId = 0;
if (siteRecordSet.getRecords().length != 0) {
  for (Site result : siteRecordSet.getRecords()) {
    if (Arrays.asList(result.getUrls()).contains(searchString)) {
      directorySiteId = result.getId();
if (directorySiteId == 0) {
  System.out.println("No site with that exact URL was found!");

If the site you need doesn’t exist in the directory, you can add it through the website interface. The API does not support adding new sites to the site directory.

Step 2: Create A New DFA Site

Using the site ID you obtained in Step 1, you can create a DFA site in your account. This is also your first opportunity to modify your personal settings for this site.

// Create a DFA site.
DfaSite dfaSite = new DfaSite();
dfaSite.setName("DFA Site for Site " + directorySiteId);

// Set any other optional parameters you want.
SiteTagSettings tagSettings = new SiteTagSettings();

// Save DFA site.
DfaSiteSaveResult saveResult = siteService.saveDfaSite(dfaSite);
long dfaSiteId = saveResult.getId();
    "DFA site with ID \"%s\" was created.%n", dfaSiteId);

// Make as many placements as you need!
Placement placement = new Placement();


The site service contains methods that you won’t typically use during trafficking administration. Once your sites are set up, the operations to retrieve DFA sites are the only ones you’ll need. If you still have any questions about creating or managing sites with the API, please visit our forum.

The newest version of the API, v201203, is at your service. It includes a brand new testing environment, read-only access to video creatives, team level filtering, and more. A full list of features can be found on our release notes page.

Test networks

Starting in v201203, you’ll be able to create test networks, which offer a wider range of functionality than the existing sandbox networks. To create test networks, you'll need a new Google account. Once you’ve called NetworkService.makeTestNetwork() with that account, you’ll sign in to test networks the same way as production, without having to sign up for a DFP account. Additionally, all SOAP requests can now be sent to instead of; moving from test networks to production now will only require you to change your network code. Stay tuned for an upcoming blog post in which we will detail how to use these new networks and our plans for the legacy sandbox environment.

Network codes

In the previous versions, network codes were only required if you belonged to more than one network. Beginning in v201203, network codes will now be required for all requests except NetworkService.getAllNetworks() and NetworkService.makeTestNetwork(). This change will reduce latency for some requests and will make it easier for you to keep track of which requests are going to which networks, especially now that test and production networks have the same domain for requests.

Video creatives

Video creatives are now read-only accessible through the CreativeService. We plan to expose more functionality going forward, but we understand the current need of publishers and 3rd parties to report on and analyze what creatives exist in their network. Look out for more work coming in this area.


v201201 introduced teams and, as we mentioned, promised future functionality of filtering objects by those teams. In v201203, you’ll be able to set team IDs on inventory, orders, and company. Then, when calls are made with that user, only objects that belong to their team will be returned. You will also receive an error if you attempt to update an object that you don’t have access to.

Stay tuned for upcoming blog posts on the new test networks and network service best practices. As always, let us know if you want to see any new features or blog posts on our forum.

- , DFP API Team

On April 2, 2012, we’ll be rolling out a number of changes to the Ad Exchange real-time bidding protocol. Although we've distributed communication on each of these topics individually, we wanted to provide a final overview of the upcoming changes. And a reminder: Although some of these may require action on your part, we expect all of them to save you time and energy in the long run.

Trading Locations
As you may know, your bid requests have been coming from a variety of data centers throughout the world. Occasionally we change the set of data centers used, which can cause headaches for your bidder. To reduce complexity and increase predictability, we've announced a set of four new, fixed trading locations: West Coast U.S., East Coast U.S., Europe, and Asia. As of April 2, 2012, these locations will become the standard, and you should expect all callouts to come from these locations.

New Bid Response Deadline
Our current bid response deadline of 120ms is a combination of 40ms “network time” and 80ms “think time.” Because the new trading locations schema reduces network time by stabilizing the origin of callouts, we are lowering the bid response deadline from 120ms to 100ms beginning on April 2, 2012.

While this is a shorter time window, your 80ms think time should not be affected. In fact, you can actually increase your think time by strategically locating your data centers near the four fixed trading locations.

Buyer Creative ID Mandatory
Starting on April 2, 2012, we will require all real-time bid responses to contain a new field: buyer_creative_id, which lets you set a unique identifier for each new ad creative you submit. Moving forward, all reports on the status of your creatives will be based on this ID. The ID also enables us to investigate and troubleshoot issues much more quickly.

From April 2 onward, any bid responses without the buyer_creative_id field will be rejected. If you are ready to begin using this field prior to the deadline, contact your Technical Account Manager.

Deprecated/Renamed Fields
The following fields in the bid request have been deprecated and will no longer be filled starting April 2, 2012:
  • protocol_version
  • campaign_id
  • excluded_click_through_url
  • company_name
Please note that excluded URLs may still be accessed via publisher_settings files.

Additionally, the MobileApp submessage has been renamed to Mobile. The following fields that are part of the newly renamed Mobile submessage have been deprecated and will no longer be filled starting April 2, 2012:
  • app_name
  • company_name
Starting on April 2, 2012, we’ll no longer be sending whitelisted vendors or GDN-approved vendors in the bid request. Check out this post for more details.

If you have questions about any of these changes, please reach out to your Ad Exchange Technical Account Manager.


As you may have recently read on the Inside AdWords blog we’ve increased various limits for Google AdWords accounts. Most notably it’s now possible to have up to 10,000 campaigns and three million keywords in an account. These and other product limits are listed in the AdWords Help Center, with additional API technical limits available on the System Limits page.

As a reminder, when dealing with large numbers of API objects it’s best to utilize paging in your requests, which allows you to fetch the data in smaller batches. The example code in our client libraries demonstrates how to use paging effectively. However, paging alone is insufficient to retrieve data sets with over 10,000 items and in those situations we recommend you either use predicates to limit the size of the results or use report downloads to get the full set of data.

If you have questions about these new limits or how they affect your API development you can reach us on the forum or during our regular office hours.


Today we’ve published a new tutorial on scheduling AdSense reports with Google Apps Script.

By following the tutorial, you’ll learn how to create a script that’s executed every hour to retrieve data from the AdSense API and send a report of the evolution of several metrics over the current day. The report data will then be visualized using an area chart.

You’ll also learn how to add a user interface to let you configure the recipient of the report, the metrics included in the chart, the hours of the day and days of the week for the report sending, as shown in the image below.

The following is an example of chart that will be sent with the email.

This tutorial is an example of how Google Apps Script can provide easy ways to automate tasks across Google products and third party services. Check the tutorials page to learn the different things that you can do using this cloud scripting language.

For any additional questions, visit our AdSense API forum or the Google Apps Script forum. You can also check the schedule for our Office Hours Hangouts and join us for a chat on this and other topics -- visit the right column of this blog to find our schedule.

Starting on April 11, 2012 we will require the API version string to be included as part of the HTTP request when downloading the AdWords API AdHoc reports. If version is not provided, the RequestError.INVALID_INPUT error will be returned. The requests for downloading reports should be sent to the following URL,
If you are using the latest versions of our client libraries for downloading reports, this change will not affect you.

As always, please feel free to ask any questions regarding the AdWords API on our forum or during scheduled office hours.

Google+ Office Hour Hangouts continue to be a hit across all of the Ads products so we're announcing that we've scheduled new events for the spring season. You can view the newly scheduled hangouts on the Google Developers events page. Please RSVP by clicking the “I’ll be there” button if you plan on attending. You can also continue to follow our schedule by subscribing to the Google Ads Developer Office Hours calendar which is also linked on the sidebar to the right of this blog entry.
In case you haven’t joined us before, you will need 3 things to join the hangout:
These hangouts are informal and conversational, which make them a great place to ask questions or give us feedback. If you have questions about our office hours program, reach out to us on the forums.


We would like to announce the release of the DFP Showcase application for iOS and Android, as well as v2 of the Ad Catalog project for Android.

DFP Showcase

DFP Showcase is a sample project that features the various creative types you can display in mobile applications with DoubleClick for Publishers (DFP) Mobile. DFP Mobile provides publishers the ability to set up campaigns with different ad types, and uses the Google AdMob Ads SDK to display the ads in mobile applications.

The DFP Showcase application features expandable ads, image animation, click to map, and more!

You can download DFP Showcase directly or clone the source code from the dfpshowcase-android or dfpshowcase-ios repositories.

Ad Catalog v2

We are pleased to announce the release of Ad Catalog v2 for Android. This new version shows examples of best practices for ad placement in four different types of layouts - TabView, ListView, OpenGLView, and ScrollView.

Here are some details about the implementation of these examples:

  • The TabView example makes use of Android’s v4 support library to implement fragments for tabs while maintaining support for Android 1.5 and higher.
  • The ListView example adapter was written to accept any type of list items, and will embed ads every kth item in the list provided.
  • The OpenGLView and ScrollView examples show how to dock an ad to the top or bottom, but outside the content on the screen.

You can get v2 of the Ad Catalog by downloading a zip file from the google-mobile-dev download page or by cloning the source code.

Have any questions, comments, or feature requests for the DFP Showcase or Ad Catalog projects? Let us know on the forum, or join us during office hours! Also, stay tuned for the release of Ad Catalog v2 for iOS.

Today, in an ongoing effort to improve clarity, we have released an update to the Terms & Conditions for AdWords API Clients. As a reminder, per our terms and conditions, Google retains the right to modify the terms and conditions at any time. Note that continued use of the API means that you accept these terms. You can refuse to accept the terms by ceasing to use the API.

Below is an overview of what has changed:
  1. We’ve updated the definition of an AdWords API client. In addition, we’ve modified the definition of an “End-Advertiser-Only AdWords API Client” (section I).
  2. We clarify when we may terminate a token for non-use (section II.1).
  3. We’ve added a clause specifying that a token may only be used for the applications/tools that it was approved for in the application process, and that we need to be notified of any changes (section II.5).
  4. We’ve clarified the “Copying Data” section of the co-mingling clause to ensure that users manually import or export all campaigns (section III.2.c.ii).
  5. We will now require clients to contact Google within 15 days of a change of control via written notice and re-application for a token (section IV.16).
  6. We’ve added an "experimental program" clause and are deprecating our current 4-month deprecation clause (section IV.2.a). We are giving people 4 months notice before these changes take effect (section IV.17).
Please review the complete Terms & Conditions here.


We previously talked about docking AdMob ads to the bottom or top of a UITableView. In response to that post, we’ve had a lot of developers asking us about embedding AdMob ads within the UITableView cells, so we wanted to share how this can be best achieved.


Placing ads within a Table View in iOS as list items can bring up a number of issues:

  • Inflated impression numbers because tables in iOS refresh when the user scrolls.
  • The one-to-one mapping between data in the Table View and the application’s model will usually be lost.

Choosing A Solution

Table Views in iOS are populated by implementing the tableView:cellForRowAtIndexPath: method. Cell objects are often reused so that new ones aren’t instantiated each time the Table View is refreshed (by a scroll for example). There are two ways that ads can be implemented within Table View cells:

  1. Only use one GADBannerView throughout the table. This would mean that the same ad is displayed in different cells in the table (preferred).
  2. Leverage dequeueReusableCellWithIdentifier: so that GADBannerViews are created only when new cells are created.

Using one GADBannerView throughout the table does decrease ad diversity but generally increases the CTR for the ads that are shown because the user will more likely see the ads that are displayed. The example below will show how to implement this approach as it is the better practice.

Solution - Single GADBannerView Method

For the purposes of this example, let’s assume that every 10th element in the list is going to be an ad. This means tableView:cellForRowAtIndexPath: will be set up with a conditional that modifies the placement of the GADBannerView for every tenth cell:

- (UITableViewCell *)tableView:(UITableView *)tableView
         cellForRowAtIndexPath:(NSIndexPath *)indexPath {
  int row = [indexPath row];

  // Assume that kFrequencyAdsInCells is 10 so every 10th row is an ad
  // Don't want first item to be an ad so use 10-1=9 instead of 0
  if ((row % kFrequencyAdsInCells) == (kFrequencyAdsInCells)) {
    cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    //Need to create a new cell object
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero
    // If bannerView_ has a superview, then it has been added to a cell
    if (!bannerView_.superview) {
      // First ad request made, make the ad request and add it to this cell
      [self requestAd];     
    // The banner will be removed from the other cell and put into here
    [cell.contentView addSubview:bannerView_];


Since ads are being inserted into the Table View now, any previous mapping to data in the model will be lost. Some quick math is necessary here to figure out how the rows in the Table View line up.

  // Complete in cellForRowAtIndexPath: if not ad
  // Make sure we get all of the items from our model
  row = row - floor((float)row/kFrequencyAdsInCells);
  cell.textLabel.text = [dataController_ objectInListAtIndex:row];

The methods tableView:NumberOfRowsInSection: and tableView:heightForRowAtIndexPath: will need to be modified as well. The method tableView:NumberOfRowsInSection: would now return the number of elements (including ads in that number) and tableView:heightForRowAtIndexPath: would return the height of an ad for every tenth cell, respectively.

If you have any questions about embedding ads within a UITableView, or even any questions about the SDK in general, feel free to post them in our forum. Keep an eye out for AdCatalog v2 for all kinds of advanced layouts options integrated in the project.

Last week we sunset all versions of the AdWords API prior to v201109. If you have not yet migrated to v201109, you will now receive errors when making calls using previous versions.

For users still working on the transition from v13 to AdHoc reports, we want to remind you of resources available to help you out:
  • The report migration guide provides a side-by-side mapping between the fields available in the v13 ReportService and those available in v201109.
  • The mapping report to the UI guide maps the concepts and naming conventions used in the User Interface (UI) and the AdWords API reports.
  • Report basics covers how to structure and download reports.
  • This blogpost covers best practices for when to schedule reports, and this post covers how to download reports for multiple clients.
For additional resources visit the AdWords API documentation.

We also encourage you to submit questions to the forum or ask them during office hours.

In the newest version of the API, v201201, we’ve added a feature to streamline the syncing of information in your DFP network to another system. Previously, this was possible but required repeatedly downloading the same objects to see if they had been modified. Now, a new PQL field exists, lastModifiedDateTime, which can be used to return objects based on their modification dates. Below is a PHP example that uses the latest client library to display all line items modified in the past 30 days.
// Get the LineItemService.
$lineItemService = $user->GetService('LineItemService', 'v201201');

// Calculate time from thirty days ago.
$thirtyDaysAgo = date(DateTimeUtils::$DFP_DATE_TIME_STRING_FORMAT,
    strtotime('-30 day'));

// Create bind variables.
$vars = MapUtils::GetMapEntries(array(
    'thirtyDaysAgo' => new TextValue($thirtyDaysAgo)));

// Create statement object to only select line items that
// have been modified in the last 30 days.
$filterStatement = new Statement(
    "WHERE lastModifiedDateTime >= :thirtyDaysAgo "
    . "LIMIT 500", $vars);

// Get line items by statement.
$page = $lineItemService->getLineItemsByStatement($filterStatement);
You will notice that we utilized a constant, DFP_DATE_TIME_STRING_FORMAT ('Y-m-d\TH:i:s'), from the library to easily format the date/time string. Also, keep in mind that the date and time specified should be in terms of the time zone that is configured for the network and any timezone specified in the string will be ignored by the server.

We hope you'll use this new feature to help save bandwidth and processing time. You can check out a full working example in PHP or other languages in our client libraries.

Feel free to leave us a comment on the forum with any feedback you have for the API or topics you would like to see in the discover series.


Since launching the AdSense Management API in October last year, we’ve received a number of questions and feedback from you while coding your applications. Today, we’ll address the most frequently asked questions and share some best practices.

How do I authenticate? Do I need to use OAuth?

Right now, the only authentication method we support is OAuth, but don’t let that intimidate you; OAuth 2.0 supports several authentication methods, for web server, client-side and installed applications and devices, which together cover all use cases.

You can find more information on how to authenticate in your favourite client library language in our client library guide or the more generic OAuth 2.0 documentation.

How do I stop my users from having to authorize my application every time they use it?

If you don’t take steps to store your users’ authentication data or set the appropriate flags on your request, the authentication process will run them through a permission-granting dialog similar to the one below every time:

In order to avoid this and improve the experience for users of your web or installed application, you should store their authentication data.

There are two types of token that we need to know about here: access tokens and refresh tokens. Access tokens give you immediate access to a user’s data, and are short-lived, whereas refresh tokens are long-lived, allowing you to generate new access tokens when you need them, even if the user isn’t present.

For installed or web applications we recommend storing both, and using the refresh token to generate a new access token whenever the one you stored expires.

For client-side applications, things should be a little easier, as all it should take is a redirect. The OAuth 2.0 documentation for client-side applications has all the information you need.

For more information on request tokens, you can check the relevant section in the OAuth 2.0 documentation, or the “Persisting authentication data” section in our client library guide if you’re using one of the client libraries.

How often can I run my report queries?

Every application has different needs, so the answer to this question will no doubt depend on what you’re doing. There are, however, a few guidelines we can give you.

First of all, try to collect data on the same frequency that you analyze it. That is, if you’re interested in daily performance, there’s no need for you to collect data more often than once a day, as our reporting can compile that data for you.

On the other hand, if you’re trying to get data as frequently as possible, bear in mind that we cache our report data for 60 seconds. There’s thus no point in running the same report more often than once a minute; the data you get won’t be any fresher, and you’ll just be wasting your request quota.

How do I get my performance data per country / domain?

Most reports are based on a time dimension such as DATE, WEEK or MONTH, which is to say that they’re grouped by that particular dimension.

Not all reports need to be based on a time dimension, however. In fact, a very useful report for those of you with many international visitors is to get a breakdown of visitors per country. In order to get that, just set your start and end dates and choose COUNTRY_CODE or COUNTRY_NAME as the dimension.

You can combine both approaches as well, to get a breakdown per country for every month, for example.

To get some more background on reports and the concepts behind them, check out our Diving into Reports blog post.

What should I do if my question isn’t answered here?

We’ve got a whole bunch of resources for you, from the reference documentation to our client library guide and code examples for several programming languages.

If that doesn’t help, take a look in our forum, and you might find a similar question or get a chance to post your own. You can also join us in a Hangout during our regular office hours. We’ll be around to give you a hand in either case!


We’ve received questions asking us what happens new ad networks are added to an existing AdWhirl application. In this post we’ll explain how older versions of your apps will handle a new ad network configuration.

Say you published an application using AdWhirl, configured to use two ad networks. Now it’s time to release the next version, and you’d like to add a third ad network while you’re at it. But how will that affect the ad network request distribution for users running an older version of your application, which doesn’t have the new ad network SDK bundled? Older versions will request the updated configuration for both iOS and Android, but the two SDKs will process the configuration differently.

How the iOS SDK Distributes Ad Network Requests

When the iOS SDK parses the new configuration, it will only consider an ad network valid if it meets certain conditions, including having the corresponding network adapter. If the adapter doesn’t exist, then that network will be ignored. Your ad network percentages will then be normalized based on the total valid percentage of allocations.

Let’s demonstrate this with the above example. Say your original app had two ad networks, Network 1 and Network 2; now you’re adding Network 3 to the next version of your app. If your new ad network configuration sends 30% of requests to Network 1, 10% to Network 2, and 60% to Network 3, users running an app version without Network 3 will send 75% of the total ad requests to Network 1 and 25% of requests to Network 2. Backfill priority will be the same as specified on the server, but it will not include network 3.

How the Android SDK Distributes Ad Network Requests

When the Android SDK parses the new configuration, it will blindly add all networks as valid choices. When it tries to make a request to an ad network whose SDK is not available, the request will fail gracefully. However, AdWhirl will then rollover to your backfill priority. What does this mean for the ad network percentage distribution?

Using the same example configuration, the 60% of requests to Network 3 will fail for users with an older version, and AdWhirl will rollover to your top backfill option. If your top backfill option is Network 2, then Network 2 will consume the Network 3 traffic - you will have 30% of all requests going to Network 1, and 70% to Network 2. This is likely not what you would expect, so be careful when adding new networks to an existing Android application.

In summary, the iOS SDK will respect the percentages given to the valid ad networks (expected), but the Android SDK will send the invalid ad network traffic to the top backfill option (unexpected).

We value your feedback, so please post to our developer forum if you have any questions about AdWhirl.