Starting October 8th, 2014, if you're using the AdWords API without a Standard Access developer token, you will be limited to 1,000 report downloads per day. Previously, there were no daily operational limits applied to report downloads for the Basic Access level. The new limit is being introduced to ensure consistency and high-quality AdWords API platforms for advertisers.
If your developer token already has the Standard Access level, then this limit will not be applied.
If your developer token has the Basic Access level and you currently download more than 1,000 reports per day, then you'll be impacted. To minimize the impact:
Important: The AdWords API compliance team will contact you using the developer contact email on file in your MCC's API Center. It's important to ensure the email is up-to-date.
If you currently have Basic Access, but at a later time feel you will need more than 1,000 report downloads per day, feel free to apply for Standard access.
- Ray Tsang, AdWords API Team
On November 5, 2014, we'll be sunsetting the login field in the ManagedCustomer class. We understand this may impact your applications and are recommending the following options to account for this change:
You should not use the login field to manage your clients' contacts and email addresses. You should always maintain your own client contacts. If your application currently relies on the login field, you can use ManagedCustomerService.get() to create a mapping between customer IDs and login emails before November 5, 2014.
CustomerId should be used instead of the login field to uniquely identify an account. To provide a friendly name for an account, you can use the name field. You may set the name field when creating a new account using the ManagedCustomerServer.mutate() method.
AdWords allows users to invite multiple users to manage their applications as well as change their AdWords sign-in information. However, the login field is not updated to reflect changes in AdWords sign-in information. So relying on the login field makes your application error prone if a user changes their AdWords sign-in information.
Your application runs with the same access levels as the user whose OAuth2 access token you send in your API calls. To determine if a user is authorized to make a particular change, you can make API calls with the validateOnly header set to true. If the user isn’t authorized to make changes, the call will fail with an AuthorizationError.
true
Login field information doesn't convey the access level the user has within AdWords. If you rely on a user’s login email to determine their access level, your application may run into errors if the user’s account access levels change.
If you have questions or feedback about this change, or encounter a use case we’ve missed, let us know on our developer forum or Google+ page.
- Anash P. Oommen, AdWords API Team
We're pleased to announce that the IMA HTML5 SDK now supports VPAID 2 JavaScript creatives. Enabling support is as easy as including the following line before initializing your AdDisplayContainer:
google.ima.settings.setVpaidAllowed(true); ... var adDisplayContainer = new google.ima.AdDisplayContainer(adContainerElement); var adsLoader = new google.ima.AdsLoader(adDisplayContainer);
There are two differences to be aware of between the VPAID 2 spec and the way the IMA SDK supports VPAID 2. These differences do not impact player or SDK implementation code, but they are important for VPAID 2 JavaScript creative authors, as creatives may throw errors or not work as expected when rendered by the IMA HTML5 SDK.
For more information, including a listing of what API methods are supported in the video player proxy element, check out our guide to VPAID 2 creatives.
As always, if you have any questions, feel free to contact us via the support forum.
- Bret McGowen, IMA SDK Team
Greetings developers!
We're happy to launch a new version of our Google Mobile Ads SDK for Android. You should see Google Play Services 6.1 (rev 20) available for download in your SDK manager.
This version includes the following changes:
getLocation
com.google.android.gms.ads.MediationAdRequest
getMediationAdapterClassName
AdView
You can read the Google Play Services Announcement on the Android Developers Blog for a summary of what’s new with this release. For a full list of SDK changes, check out our release notes. For technical questions, post them on our forum.
- Amy Quispe, Mobile Ads Developer Relations
We're taking VAST 3 support out of beta and launching it as a supported feature of the IMA SDKs for Flash, HTML5, iOS, and Android. VAST 3 adds support for a host of new features, including:
There are still a few features of VAST 3 that we will continue to add over time. Those include:
Your IMA SDK integration already supports VAST 3 without any code changes on your end, but you will need to adjust your serving settings. To start serving VAST 3 check out the DFP help center articles for Small Business or Premium, depending on your account type.
For more information on the features and benefits of VAST 3, check out the IAB documentation. As always, if you have any questions feel free to contact us via the support forum.
- Shawn Busolits, IMA SDK Team
By now you're probably familiar with using PQL in the DFP API. The SQL-like filtering provides an expressive way of working with DFP, but occasionally you'll want to filter on a field that isn't supported by PQL. Luckily, if you're using the .NET library, you can utilize LINQ to augment your filtering capabilities.
Similar to PQL, LINQ provides a friendly syntax for filtering iterables. As you page through entities from DFP, you can leverage LINQ to add that extra filtering with just a few lines of code.
This example finds all ImageCreatives that are missing altText - a field specific to the subclass and not filterable with PQL.
CreativePage page = new CreativePage(); var creativesMissingAltText = new List(); // Create statement to select image creatives. StatementBuilder statementBuilder = new StatementBuilder() .Where("creativeType = :creativeType") .OrderBy("id ASC") .Limit(StatementBuilder.SUGGESTED_PAGE_LIMIT) .WithBindVartiableValue("creativeType", "ImageCreative"); // Page through all creatives and select those that are missing the // altText property with LINQ. do { page = creativeService.getCreativesByStatement(statementBuilder.ToStatement()); creativesMissingAltText.AddRange( from ImageCreative creative in page.results where creative.altText == "" select creative); statementBuilder.IncreaseOffsetBy(StatementBuilder.SUGGESTED_PAGE_LIMIT); } while (statementBuilder.GetOffset() < page.totalResultSetSize); Console.WriteLine("Found {0} ImageCreatives missing altText", creativesMissingAltText.Count);
While LINQ offers a way to extend filtering, it's important not to ignore PQL. You'll notice this example used PQL to pre-filter on the creative type. Working with smaller result sets will save you network overhead and processing cycles.
Now let's take a look at a more complex example. In this scenario, your application needs to validate the htmlSnippet of CustomCreatives. LINQ allows you to use regular expressions while filtering to extract the matches. Here we'll use a regular expression to make sure URLs in the htmlSnippet point to a certain subdomain.
// Make sure any URLs to mydomain go through the CDN. Regex subdomainRegex = new Regex(@"https?://(?!cdn\.).*?mydomain.com"); var errors = from CustomCreative creative in creativesToValidate let matches = subdomainRegex.Matches(creative.htmlSnippet) where matches.Count > 0 select new { creativeId = creative.id, matchedUrls = from Match match in matches select match.Value }; foreach (var error in errors) { Console.WriteLine("Invalid urls found in creative {0}: {1}", error.creativeId, error.matchedUrls.Join(",")); }
- Chris Seeley, DFP API Team
Today, we’re happy to announce the launch of Google Mobile Ads SDK v6.12.0 with support for iOS 8. Specifically, it includes the following iOS 8 updates:
Version 6.12.0 also requires that your app link to two additional frameworks:
If you’re using CocoaPods, simply run pod update to grab the update, and these new frameworks will be automatically linked for you. If you’re not using Cocoapods, the getting started guide has the full list of required frameworks.
See the release notes for a full list of updates. You can grab the latest SDK from the downloads page. If you have any technical questions about the new release, post them on the developer forum. Also follow our Google+ page to keep abreast of the latest developments for the Mobile Ads SDK.
- Eric Leichtenschlag, Mobile Ads Developer Relations
conversionOptimizerMode
MANY_PER_CLICK
ONE_PER_CLICK
Customer
remarketing
Python has tons of cool idioms and features that are often overlooked or underutilized. List comprehensions to cut back on the use of unnecessary loops, decorators to wrap functions with annotations, and generator functions are just some that can be applied to working with the DFP API.
In this post, we'll tackle one of our most asked questions using decorators: "Why am I running into CONCURRENT_MODIFICATION or QUOTA_EXCEEDED errors, and how do I avoid this?".
CONCURRENT_MODIFICATION and QUOTA_EXCEEDED errors are similar in nature - the requests you’re making are failing, but not necessarily because the data you’re sending over is bad. In the first case, one of the objects you’re trying to modify is being updated elsewhere, but you likely want to try again after pulling down the same set of objects. You could certainly write code that retries your operations in all of your services for each object, but it may get a bit hard to maintain (especially with duplicated code). A much cleaner implementation would be to use a decorator!
The Python wiki has an entry under the decorators section that shows how a generic decorator might work for retrying a call. With a few modifications, we can tailor this to capture the two types of errors that might arise:
import time from functools import wraps RESPONSES_TO_RETRY = ['CONCURRENT_MODIFICATION', 'QUOTA_EXCEEDED'] def retry(tries=4, delay=3, backoff=2): ''' Decorator that implements an exponential backoff for retrying on errors. Args: tries: int number of times to execute the wrapped function before failing delay: int time to delay in seconds before the FIRST retry backoff: int multiplier to extend the initial delay by for each retry ''' def decorated_function_with_retry(func): @wraps(func) def function_to_retry(*args, **kwargs): local_tries, local_delay = tries, delay while local_tries > 1: try: return func(*args, **kwargs) except Exception, e: if [response for response in RESPONSES_TO_RETRY if response in e.fault['faultstring']]: print '%s, Retrying in %d seconds...' % (str(e), local_delay) time.sleep(local_delay) local_tries -= 1 local_delay *= backoff return func(*args, **kwargs) return function_to_retry return decorated_function_with_retry
Say you were making a call to update line items - with large networks, it’s not unlikely that someone might be editing the line item at the same time. Since you’d want to pull down the most recent copy of the line item any time the update fails, you would want to abstract out the update method to include the getLineItemsByStatement call, e.g.,
@retry() def fetch_and_update_line_item(statement): # call to get the line item in question response = line_item_service.getLineItemsByStatement( statement.ToStatement()) updated_line_items = [] if 'results' in response: for line_item in response['results']: # Do something with your line items here and add them to # updated_line_items. line_item_service.updateLineItems(updated_line_items)
This would effectively allow you to, in the event of the update failing due to concurrent modification, pull down and update a new copy of the line item. Using the default constructor will retry 4 times with 3, 6, and 12 second delays in between.
To wrap things up, decorators are incredibly useful constructs in Python and are useful for the DFP API for several reasons:
Make use of decorators in your code, and you'll soon be sitting pretty.
- Nicholas Chen, DFP API Team
Until now, the DFP API only supported the OAuth 2.0 native/installed application flow. The OAuth 2.0 service account flow was only supported it you had a Google Apps for Business Account. Today, we’re unveiling the new OAuth 2.0 service account flow for DFP. This authorization flow has been simplified to no longer require a Google Apps domain. We’ve also updated the DFP web UI to allow service accounts to be added to be a DFP network.
Service accounts allow access to Google APIs without the need for user interaction by authenticating solely with server-to-server interactions. Other OAuth 2.0 flows require user interaction or having an application cache a refresh token.
With the *.p12 key generated from the Google Developers Console and the service account added to the DFP network, you can now generate an OAuth 2.0 token. For example, using the Java client library:
GoogleCredential credential = new GoogleCredential.Builder() .setTransport(new NetHttpTransport()) .setJsonFactory(new GsonFactory()) .setServiceAccountId("****@developer.gserviceaccount.com") .setServiceAccountScopes("https://www.googleapis.com/auth/dfp") .setServiceAccountPrivateKeyFromP12File(new File("/path/to/key.p12")) .build();
For more information, see our updated guide on using service accounts with DFP.
- Vincent Tsao, DFP API Team
Over the coming months we’re adding better controls for Local Inventory Ads to support more advanced use cases for targeting store products. To prepare for these changes, we are removing the existing ProductSalesChannel from AdWords API v201409 and will add new controls to a subsequent AdWords API release next year.
Starting October 15th, 2014, using ProductSalesChannel to select the Local channel settings (CriterionId - 201) will return the CriterionError.CANNOT_ADD_CRITERIA_TYPE error for all AdWords API versions.
CriterionError.CANNOT_ADD_CRITERIA_TYPE
For most Shopping campaigns, you don't need to add this criterion, and should simply omit it from your AdWords API request. We recommend that you use the AdWords interface to make any changes to your Local Inventory Ads campaigns.