Posted:
On May 5, 2014, in the spirit of spring cleaning, the IMA Flash SDK will be dropping support for several rarely-used formats and SDKs:

  • VAST 1 XML format. The IMA Flash SDK will continue to support VAST 2 and will continue to improve on its existing beta support for VAST 3. For more information about what versions of VAST, VPAID and VMAP the IMA Flash SDK supports, visit the Video Features and SDK Compatibility page.
  • Flash-in-Flash (F2F) creatives. VPAID, the industry standard for interactive video ads, is the recommended alternative for replacing F2F creatives. The IMA Flash SDK currently supports VPAID 1 and has beta support for VPAID 2. 
  • IMA Flash SDK v1. This version of the SDK will no longer be guaranteed to work and won't receive bug fixes, updates, or responses to support issues. V3 of the IMA Flash SDK will be the only fully supported version of the SDK.
  • Dart Shell SDK. This DoubleClick SDK will no longer be guaranteed to work and won't receive bug fixes, updates, or responses to support issues.

What will happen if VAST 1 or an F2F creative is sent to the SDK?

If a VAST 1 ad tag response or F2F creative is sent to the SDK, the SDK will raise an AdErrorEvent with an appropriate error. For example, a VAST 1.0 response will return an AdErrorCodes.VAST_PARSING_ERROR which can be handled with the following ActionScript modified from the Flash IMA SDK example app:

  // ...
  import com.google.ads.ima.api.AdErrorCodes;

  private function initAdsLoader():void {
    // ...
    adsLoader.addEventListener(AdErrorEvent.AD_ERROR, adsLoadErrorHandler);
  }

  private function adsLoadErrorHandler(event:AdErrorEvent):void {
    // ...
    if (event.error.errorCode == AdErrorCodes.VAST_PARSING_ERROR) {
      trace("Invalid VAST format."); 
      // Error handling logic...
    }
  }

Other questions?

Questions about these support changes or other questions about the Flash IMA SDK? Check out the IMA SDK Flash Quick Start Guide or drop us a line on the IMA SDK forum. Follow our Google+ page for other announcements and updates.

Posted:
In our previous blog post on exception handling in the DFP API, we went over the first of two major scenarios where adding exception handling can help you troubleshoot issues when they occur. In this blog post, we finish off by discussing how to handle exceptions that occur when retrieving entities.

Retrieving entities

When retrieving entities, you may have run into errors such as ServerError, QuotaError, or client library specific errors like RemoteException. Generally these errors are not caused by user error, but caused by the API server being busy, or by issues with the entities you are retrieving being too large or corrupted. If you’re already following our best practices of paging through your entities with our suggested page size and are still running into these errors from time-to-time, you can tackle these issues by writing code to handle the exceptions.

The general way we recommend you reduce the page size, wait a few seconds, and then retry the request to handle most errors you can receive. If it continues to fail, repeat this process up to five times. This will give you an idea of whether the failure is a temporary server error, or if there is a deeper issue. The following is an example that augments the GetAllLineItemsExample from the Google Ads API Java Client Library showing how to do this. It reduces the page size for each retry by halving it, and starts off the wait time between retries at two seconds, doubling it with each retry.
  private static final int MAX_RETRY_LIMIT = 5;
  private static final long BASE_WAIT_TIME = 2000;

  public static void runExample(DfpServices dfpServices, DfpSession session)
      throws Exception {
    int pageLimit = StatementBuilder.SUGGESTED_PAGE_LIMIT;

    // Get the LineItemService.
    LineItemServiceInterface lineItemService =
        dfpServices.get(session, LineItemServiceInterface.class);
    // Create a statement to select all line items.
    StatementBuilder statementBuilder =
        new StatementBuilder().orderBy("id ASC").limit(pageLimit).offset(0);

    // Default for total result set size.
    int totalResultSetSize = 0, retryCount = 0;
    LineItemPage page = null;
    long waitTime = BASE_WAIT_TIME;

    do {
      // Reset these values for each page.
      retryCount = 0;
      pageLimit = StatementBuilder.SUGGESTED_PAGE_LIMIT;
      waitTime = BASE_WAIT_TIME;
      page = null;

      do {
        try {
          System.out.printf(
              "Getting line items with page size of %d at offset %d (attempt " +
                  "%d)...\n", pageLimit,
              statementBuilder.getOffset(), retryCount + 1);
          // Get line items by statement.
          page = lineItemService.getLineItemsByStatement(
              statementBuilder.toStatement());
          System.out.printf("Attempt %d succeeded.\n\n", retryCount + 1);
        } catch (Exception e) {
          pageLimit /= 2;
          System.out.printf(
              "Attempt %d failed. Retrying in %d milliseconds with page size " +
                  "of %d...\n",
              retryCount + 1, waitTime, pageLimit);
          Thread.sleep(waitTime);
          waitTime *= 2;
          statementBuilder.limit(pageLimit);
          retryCount++;
        }
      } while (page == null && retryCount < MAX_RETRY_LIMIT);

      if (page != null) {
        totalResultSetSize = page.getTotalResultSetSize();
        // Your code to handle the line item page, e.g., save it to a database.
      } else {
        throw new Exception(String.format(
            "Failed to get line items at offset %s with page size %d after " +
                "%d attempts.",
            statementBuilder.getOffset(), pageLimit, retryCount));
      }

      statementBuilder.increaseOffsetBy(pageLimit);
    } while (statementBuilder.getOffset() < totalResultSetSize);

    System.out.printf("Number of results found: %d\n", totalResultSetSize);
  }
Using the above code, the output would look like the following if the first three attempts failed, but the fourth one succeeded for the first page.
Getting line items with page size of 500 at offset 0 (attempt 1)...
  Attempt 1 failed. Retrying in 2000 milliseconds with page size of 250...
  Getting line items with page size of 250 at offset 0 (attempt 2)...
  Attempt 2 failed. Retrying in 4000 milliseconds with page size of 125...
  Getting line items with page size of 125 at offset 0 (attempt 3)...
  Attempt 3 failed. Retrying in 8000 milliseconds with page size of 62...
  Getting line items with page size of 62 at offset 0 (attempt 4)...
  Attempt 4 succeeded.

  Getting line items with page size of 500 at offset 62 (attempt 1)...
  Attempt 1 succeeded.
If you’re getting exceptions that weren't addressed by our examples and are unclear on how to diagnose them, then you can always write to us on the API forums. Include the requestId of the call that failed, especially in the case that you receive a SERVER_ERROR.

Posted:
Starting on April 22nd, 2014, a v201309 or v201402 AdGroupBidModifierService.mutate request will fail with a CriterionError and reason CANNOT_BID_MODIFY_CRITERION_TYPE if all of the following conditions are met for the same criterion:
  • The criterion is a Platform criterion for the mobile platform ID (30001)
  • The Campaign has a CampaignCriterion for the mobile platform criterion with a bidModifier set to 0 (this is displayed as a Bid adj. of -100% under Settings in the AdWords UI)
  • The AdGroupBidModifier has the same mobile platform criterion and attempts to set the bidModifier to any value other than 0
The AdWords API and UI will start rejecting such requests because allowing this combination could give the impression that the ad group will serve ads for the mobile platform criterion when in fact it will not.

For example, assume you create a campaign with a CampaignCriterion containing the following criterion and bid modifier:
<criterion xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:type="Platform">
    <id>30001</id>
    <type>PLATFORM</type>
    <Criterion.Type>Platform</Criterion.Type>
    <platformName>HighEndMobile</platformName>
</criterion>
<!-- This will appear as "-100%" in the UI. -->
<bidModifier>0.0</bidModifier>
If you attempt to create an AdGroupBidModifier containing the following criterion and bid modifier for any ad group in the campaign on or after April 22nd, 2014, it will fail because the non-zero ad group bid modifier of 1.25 would have no effect:
<criterion xmlns:ns2="https://adwords.google.com/api/adwords/cm/v201402"
  xsi:type="ns2:Platform">
    <ns2:id>30001</ns2:id>
</criterion>
<!-- This will appear as "+125%" in the UI.  Any other non-zero
     value will also fail. -->
<bidModifier>1.25</bidModifier>
Before April 22nd, 2014, please take the following actions to ensure a smooth transition for your application:
  • Make sure that your application will be able to properly handle the error
  • Examine your existing campaigns and ad groups and address any bid modifiers that meet the conditions above
Not using bid adjustments in your campaigns and ad groups? Check out our bid modifiers guide to learn how to use this powerful feature of AdWords.

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

Posted:
We’ve long worked to keep your searches on Google secure. We provided SSL encryption for signed-in searches in 2011 and have rolled that out to searches from the omnibox in the Chrome browser. Today, we are extending our efforts to keep search secure by removing the query from the referer on ad clicks originating from SSL searches on Google.com.

Advertisers will continue to have access to useful data to optimize and improve their campaigns and landing pages. For example, you can access detailed information in the AdWords search terms report and the Google Webmaster Tools Search Queries report.

Best practices

The AdWords search terms report (previously known as the search query performance report) lets you see search queries that generated ad clicks along with key performance data. And the Search Queries report available in Google Webmaster Tools provides aggregate information about the top 2000 queries, each day, that generated organic clicks.

If you use the query in the referer for reporting, automated keyword generation or landing page customization, then we suggest using the following alternatives: We understand that some partners may need to make changes to their systems and operations, but we think that this is the right path forward for the security of our users searching on Google.com.

Posted:
We often get a lot of questions about running into exceptions when using the DFP API and what to do about them. Seeing an exception from time-to-time is a normal part of the API workflow and should be expected. Some exceptions are caused by user errors, others by server issues. We strongly recommend that you write code to handle exceptions early on so that it’s easier to troubleshoot issues when they occur. In this blog post, we’ll go over the first of two major scenarios where adding exception handling will benefit you.

Creating or updating entities

When creating or updating entities with the DFP API, if you forget to supply a required field or set a field to an invalid value, the API throws an ApiException. If you write code to catch this exception, you can print out the error message to show the root cause. The following is an example showing how to do this when using the Google Ads API Java Client Library to create line items.

  // Create a line item.
  LineItem lineItem = new LineItem();
  // lineItem.setSomeThings(...);

  try {
    // Create the line item on the server.
    lineItemService.createLineItems(new LineItem[] {lineItem});
  } catch (ApiException e) {
    ApiError[] apiErrors = e.getErrors();
    for (ApiError apiError : apiErrors) {
      StringBuilder errorMessage = new StringBuilder();
      errorMessage.append(String.format(
          "There was an error of type '%s', on the field '%s',"
          + "caused by an invalid "
          + "value '%s', with the error message '%s'",
          apiError.getApiErrorType(), apiError.getFieldPath(),
          apiError.getTrigger(), apiError.getErrorString()));
      if (apiError instanceof NotNullError) {
        errorMessage.append(String.format(", with the reason '%s'.",
            ((NotNullError) apiError).getReason()));
      } else if (apiError instanceof FrequencyCapError) {
        errorMessage.append(String.format(", with the reason '%s'.",
            ((FrequencyCapError) apiError).getReason()));
      }

      // Append details of other ApiErrors that you are interested in.

      System.err.println(errorMessage.toString());
    }
  }
If you use this code to create a line item, it prints the following if you don’t specify an order ID:
There was an error of type 'NotNullError', on the field 'lineItem[0].orderId',
  caused by an invalid value '', with the error message 'NotNullError.NULL',
  with the reason 'NULL'.
If you provide invalid values for the frequency caps field when creating a line item, you’ll get the following:
There was an error of type 'FrequencyCapError', on the field
  'lineItem[0].frequencyCaps', caused by an invalid value '1000', with the
  error message 'FrequencyCapError.RANGE_LIMIT_EXCEEDED', with the reason
  'RANGE_LIMIT_EXCEEDED'.
There was an error of type 'FrequencyCapError', on the field
  'lineItem[0].frequencyCaps', caused by an invalid value '0', with the error
  message 'FrequencyCapError.IMPRESSIONS_TOO_LOW', with the reason
  'IMPRESSIONS_TOO_LOW'.
Depending on the type of application you’re writing, you may want to show these error messages to your user in a UI or log them. Note that you can find an entity’s required fields and valid field values in our reference documentation, for example, LineItem.

If you’re getting exceptions when creating or updating entities that are not ApiException errors (such as a SERVER_ERROR) and are unclear on how to diagnose them, then you can always write to us on the API forums and include the requestId of the call that failed and we will help you diagnose the issue.

Look forward to part II of this blog post where we will discuss handling exceptions that are thrown when retrieving entities.

Posted:
We're pleased to announce that the AdWords API Workshops are coming back for another round in April and May of 2014. Registration is now open!

Workshop topics include:
  • Shopping campaigns - how shopping integrates into the AdWords API
  • MCC scripts - The feature that was most requested is now available for beta signup
  • FeedServices updates - including the new location extensions setup
  • Targeting types - DSAs, DomainSetting and AutoTagging
  • Analytics - getting started with the Analytics API and how it fits within your AdWords apps
  • Bid Estimation - the different ways to estimate bids using the API

Not only are the workshops an important way to keep up-to-date with new features and best practices in the AdWords API, they are a great way for you to meet with and ask questions of the Google AdWords API team in person. This is also a key event for members of the community to bring their feedback directly to us. Finally, it’s a great opportunity for you to exchange ideas and best practices with fellow developers.

Register now and join us at a workshop in one of the following cities:
  • London, UK, April 29
  • Hamburg, Germany, May 13
  • Amsterdam, Netherlands, May 15
  • New York City, USA, May 5
  • San Francisco, USA, May 12
  • Shanghai, China, May 20 (in Chinese)
  • Taipei, Taiwan, May 22 (in Chinese)
  • Delhi, India, May 26
  • Sydney, Australia, May 29

Note: The workshops in the USA, Europe, and Australia are technical in nature and best suited to developers. Those in China, Taiwan, and India will have additional sessions accessible to a broader audience, including non-developers.

For more information on the agenda, location and logistics, please visit the AdWords API Workshop website.

Posted:
Starting with v201402 of the AdWords API, all newly created Search and Display Network campaigns will automatically be Search Network with Display Select campaigns. This means:
  • If you don't specify displaySelect when creating a Search and Display Network campaign, it will default to true, creating a Search Network with Display Select campaign
  • If you edit the networkSetting of an existing Search only campaign to target Content Network and do not specify displaySelect, we will upgrade the campaign to Search Network with Display Select by setting displaySelect to true
  • If you create a Search and Display Network campaign or edit the networkSetting of an existing Search only campaign to target Content Network, and specify displaySelect as false, you will receive an OPERATION_NOT_PERMITTED_FOR_CAMPAIGN_TYPE error
We encourage you to update your campaigns to Search Network with Display Select by setting the displaySelect property to true. Starting on September 16, 2014, we will start converting all Search and Display Network campaigns to Search Network with Display Select.

Search Network with Display Select uses improved signals and methods of predicting when and where your ads are likely to perform best, and sets a higher bar for when to show them. That means your ads are more likely to be shown to a smaller number of prospective customers, who are more likely to be interested in your offerings.

For more information about creating these types of campaigns, see our previous blog post. For more general information about this AdWords feature, please see here.

If you have any questions about this change, please contact us on the forum or via our Google+ page.