Posted:

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:

  • Less time is spent on the main thread while loading ads
  • Smart Banner ads are displayed correctly in landscape

New Framework Dependencies

Version 6.12.0 also requires that your app link to two additional frameworks:

  • EventKit
  • EventKitUI

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.

Posted:
As announced in February, flexible conversion counting in AdWords now lets you decide how you want to count conversions for each of your accounts. As a follow up to this new feature, when new AdWords accounts are created through the UI or the API after October 1st, 2014, the default conversionOptimizerMode will be MANY_PER_CLICK instead of ONE_PER_CLICK. In addition, we'll change the conversionOptimizerMode to MANY_PER_CLICK on any existing account that is not using bidding strategies impacted by conversions.

Action required
Since the new default of MANY_PER_CLICK lets your conversion-based bidding strategies take full advantage of flexible conversion counting, we recommend keeping the default setting on new accounts. However, if you still want to use ONE_PER_CLICK for new accounts created via ManagedCustomerService, then add a second step in your account creation process that issues a CustomerService.mutate call that sets the conversionOptimizerMode on the Customer.

In addition, if you decide to utilize one of the conversion-based bidding strategies, you'll want to make sure that the conversionOptimizerMode is set to the value you'd prefer. The conversion-based bidding strategies affected by conversionOptimizerMode are: Additional information
If you'd like to learn more about conversion tracking in AdWords, check out the Help Center article on counting conversions. In addition, the remarketing examples folder in each client library contains an AddConversionTracker example that shows how to create an AdWordsConversionTracker via the API.

Still have questions? Feel free to visit us on the AdWords API Forum or our Google+ page.

Posted:

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?".

Addressing these errors using decorators

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:

  • Your application will be less flaky and less affected by intermittent application issues.
  • You’re less likely to run into quota errors.
  • This would prevent overwriting other changes (in the case of retrying failed calls on concurrent modification errors).
  • You could also use something like this to log errors on your end, which could help reveal poor code health or inefficient processes.

Make use of decorators in your code, and you'll soon be sitting pretty.

Posted:
Today we launch the v2.0 release of the DoubleClick Ad Exchange Seller REST API. This release adds support for associating a single user to more than one account.

If your user ID is associated with only one account, you can continue to use v1.1 of the API as you have previously, although we recommend you always use v2.0 of the API. If your user ID is associated with more than one account, you must use the v2.0 API and supply the accountId of the appropriate customer account with each request.

For example, resource requests in v1.1 like this:
https://www.googleapis.com/adexchangeseller/v1.1/{resourceType}/{resourceId}

Will become this in v2.0:
https://www.googleapis.com/adexchangeseller/v2.0/accounts/{accountId}/{resourceType}/{resourceId}

Follow our Google+ page for other announcements and updates.

Posted:
On September 3rd, 2014, we introduced callouts extensions: additional text you can include with your Google search ads that provide detailed information about your business, and products and services you offer. Starting today, all AdWords API versions can now manage callouts using the existing Feed API, similar to other feeds.

Feeds for callouts are mapped to feed placeholder type 17, with only one string field. See the feed placeholder documentation for more information.

Posted:

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.

Why should I use service accounts?

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.

How do I use service accounts?

  1. Generate a service account key from the Google Developers Console.
  2. Add the service account to your DFP network by going to the Admin tab and clicking the Add a service account user button.
  3. Fill in the form with your Name, Email, Teams (if applicable), and Role. Then, click Save.
  4. View existing service account users by going to the Users tab and then clicking the Service Account filter.

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.

Posted:

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.

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.