Better know a service: InfoService

Friday, March 27, 2009


We, at the AdWords API Team, are often asked questions such as "Where have all my units gone?" and "How many API units has a particular account used in the last month?" Luckily, we have supplied you with a great set of tools with InfoService to answer these questions. In this blog post, we'll talk about some basic uses of this service, as well as some caveats that can be solved using some more advanced techniques. All code examples have been coded using the AdWords Java Client Library.


Update: both of these examples have now been included as utility methods in the file UnitsUtils.java. The example links below have been updated as well.

Where have all my units gone?

"Where have all my units gone?" is one of the most frequent questions asked by our developers seeking to trim down their API usage. Although InfoService provides the method getUnitCountForMethod, it is not inherently obvious how to generate a full mapping of usage. The heart of the problem is that, to call getUnitCountForMethod, you must pass it a service name and method. To get a full mapping of method to usage, getUnitCountForMethod must be called for each service and method pair. In the method UnitUtils.getMethodUsage, I have shown how you might do this.

The method is broken into two parts: populating a full mapping of service name to list of method names, and calling getUnitCountForMethod for each mapping. The result of each call is then put into a new map, referred to as
methodUsage in the method. When the method has finished running, which may take a few seconds, methodUsage will have a mapping of serviceName.methodName to quotaUsage and the output will resemble:

AccountService.getAccountInfo = 3
AccountService.getClientAccountInfos = 257
AccountService.getClientAccounts = 0
AccountService.getMccAlerts = 0
AccountService.updateAccountInfo = 0
...
AdService.addAds = 5005
AdService.checkAds = 0
AdService.findBusinesses = 0
AdService.getActiveAds = 0
AdService.getAd = 0
AdService.getAdStats = 0
AdService.getAllAds = 0
AdService.getMyBusinesses = 0
AdService.getMyVideos = 0
AdService.updateAds = 0
...
TrafficEstimatorService.checkKeywordTraffic = 0
TrafficEstimatorService.estimateAdGroupList = 0
TrafficEstimatorService.estimateCampaignList = 0
TrafficEstimatorService.estimateKeywordList = 0

As you can see, many of my units went towards adding Ads. Using this data, I could enter my monthly values into a spreadsheet and plot my usage over several months. Not only could I easily spot where all of my units have gone, but I would also be able to spot any out of the ordinary behavior as well.

As a side note, regardless of the credentials supplied to the service, this method will only gather data against the developer token. Meaning that, supplying a clientEmail or clientCustomerId will not give a finer grained set of results.

How many API units has a particular child account used in the last month?

Another great feature of InfoService is that it allows you to determine how many units a particular child account has used over a period of time. This information can be used to invoice clients, if you are developing for an Agency, or to perform cost/ctr analysis, if you wished to optimize your accounts per API spend.

There is one caveat, however. Let's say that we have an account structure that resembles the one below:




We have a top most MCC, Top-MCC, which is the root of our tree. Since our goal is to generate a mapping of child account to the amount of quota used, a first approach may be to run getUnitCountForClients for each client, as shown below:

InfoService.getUnitCountForClients(["Sub-MCC-1",
"Sub-MCC-2", "Client-1", "Client-2",
"Client-3", "Client-4"],
"3/1/2009", "3/31/2009");

From the results, you can create a mapping that resembles:

Sub-MCC-1 = 55
Sub-MCC-2 = 70
Client-1 = 500
Client-2 = 650
Client-3 = 600
Client-4 = 400

You'll notice that while this data gives you some idea of client usage, there's no aggregation of client usage up to the MCC; Sub-MCC-1 returns just the number of units called directly on that account, such as from a command with headers:

<email>Top-MCC</email>
<password>passwordForTop-MCC</password>
<developerToken>...</developerToken>
<applicationToken>...</applicationToken>
<userAgent>...</userAgent>
<clientEmail>Sub-MCC-1</clientEmail>

What you may actually want is an aggregation of unit usage such as:

Top-MCC = 2275
Sub-MCC-1 = 1305
Sub-MCC-2 = 470
Client-1 = 500
Client-2 = 650
Client-3 = 600
Client-4 = 400

In the method UnitUtils.getClientUnitsUsage, I show how to traverse the full account tree below the top most MCC and sum the units for each client to produce a mapping like the one above. However, if by some chance, a client has two parent accounts, linked through UI/API and API, and those parents are both distant children of the same parent, that client will be doubly counted. We've also shown how to keep track of these doubly counted clients in the demo.

We hope that these new utility methods will help you keep track of your API usage and stay tuned for more great demos like these!

--Adam Rogal, AdWords API Team

AdWords API sandbox - Best practices

Friday, March 20, 2009


The API sandbox is open to anyone who wants to test code during development, and it's completely free. We recommend using the sandbox as much as possible to catch your bugs during development so they won't hit your production account later. Here are some tips on using the sandbox effectively:


Initialize your sandbox account

Make sure that the first call to the sandbox is a get() call from AccountService, preferably AccountService's getClientAccounts(). Assuming you use [email protected] as the login email, this call will initialize the sandbox and create 5 test client accounts, namely [email protected] to [email protected] for your sandbox account. While making this call you should not provide the clientEmail or clientCustomerId headers, since this call expects an MCC account to succeed. 

While making a getClientAccounts() call to the sandbox, set the SOAP headers as follows:

email: address of any google account, such as a Gmail account
password: password of the account
useragent: set to any identifying string
developerToken: set to the value for email, with the string '++USD' (or the currency code of your choice) appended
applicationToken: ignored, and could be set to anything or left out
clientEmail: should be either set to the empty string or left out
clientCustomerId: should be either set to the empty string or left out

The sandbox database is usually refreshed once every month, wiping out all client accounts. Making getClientAccounts() as your application's first API call ensures that all your calls happen against a properly initialized sandbox account.

Simulate error responses

Because a good application needs to gracefully handle errors thrown by the AdWords API, the sandbox provides a mechanism for simulating error messages. If you use [email protected]++errorCode as the email for a call to the sandbox, the sandbox will return an error response with error code set as the desired errorCode, and a text message indicating that an error response has been forced by the sandbox. 

The error code should be set to one of the valid error codes. For instance, by providing login email as [email protected]++17, I can simulate error code 17 (account exceeded maximum number of allowed campaigns). 

The SOAP response looks as follows:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <soapenv:Body>
    <soapenv:Fault>
      <faultcode>soapenv:Server.userException</faultcode>
      <faultstring>Error forced by the request (Sandbox)</faultstring>
      <detail>
        <ns1:fault xmlns:ns1="https://adwords.google.com/api/adwords/v13">
          <ns1:code>17</ns1:code>
          <ns1:message>Error forced by the request (Sandbox)</ns1:message>
          <ns1:trigger>[email protected]++17</ns1:trigger>
        </ns1:fault>
      </detail>
    </soapenv:Fault>
  </soapenv:Body>
</soapenv:Envelope>

Similarly, you can also test for some policy violations in ads and keywords. For instance, providing repeated punctuation in the ad or keyword text, such as "Hello World!!" as the ad title, should trigger a policy violation error. However, the sandbox doesn't have all of the policy checks in place, so you can't test your application against every possible policy violation, e.g. trademark-related violations. 

Generate reports

Since generating reports is one of the most common calls in the AdWords API, the sandbox provides features to test each stage of your report generation logic. In the sandbox, you can create either a report whose status does not change, or a report whose status changes from pending to deleted. If you include any one of the following strings in the report name field while creating it, it will create a report with the specified status.

  • fixstatus=Pending
  • fixstatus=InProgress
  • fixstatus=Completed
  • fixstatus=Failed

If the name doesn't contain any of the above codes, the sandbox will create a report whose status changes as follows:

  • During the first minute since the report job was scheduled, the status is Pending.
  • During the second minute, the status is InProgress.
  • During the third minute, the status is Completed.
  • After the third minute, the report is deleted.

Also, a call to getAllJobs will return four reports, one for each value of ReportJobStatus. Sandbox reports do not return any data related to any live accounts. So if you want to test your report parsing logic against some live data, you can generate a report of the desired type in the Reports Center of your production account, download it in xml format, and use it to develop and test your code.  

Handling account limits

As with a live account, an AdWords sandbox account can hold a maximum of 25 active campaigns, with up to 100 active ad groups per campaign. If your program runs into these limits, then you can change the status of some campaigns or ad groups to "deleted."

TrafficEstimatorService and KeywordToolService behavior

Both TrafficEstimatorService and KeywordToolService are available for use in AdWords API sandbox. However, both these services return fake data. TrafficEstimatorService will give you fake data for Position, CPC, and Clicks per day. KeywordToolService can give you fake Seed-based keyword suggestions when using getKeywordVariations. It can also give you content-based keyword suggestions and SiteKeyword statistics when using getKeywordsFromSite.

The AdWords API sandbox can greatly help you with your development by preventing bugs from hitting production account during early stages of development. You can find more information on AdWords API sandbox at http://code.google.com/apis/adwords/docs/developer/adwords_api_sandbox.html.

-Anash P. Oommen, AdWords API Team

AdWords Downtime: March 14, 10am-2pm PDT

Tuesday, March 10, 2009


We'll be performing routine system maintenance on Saturday, March 14 from approximately 10:00am to 2:00pm PDT. You won't be able to access AdWords or the API during this time frame, but your ads will continue to run as normal.

Cheers,
-Jeffrey Posnick, AdWords API Team

AdWords API Developer Docs: Now in Chinese and Japanese!

Tuesday, February 17, 2009


It's easy to write code using the AdWords API in the programming language of your choice, thanks to all of our client libraries. But when it comes to written language, you're more constrained--our recent developer documentation has only been maintained in English.

We're happy to announce that this is no longer the case, and our Developer's Guide now features a Chinese and Japanese translation. If you're not automatically redirected to the appropriate language when you visit that page, use the popup menu in the upper right hand corner of the web page to switch to one of the supported languages.

Please note that only the v12 version of the Developer's Guide has been translated. We're working hard to get v13 translated as well, and hope that the v12 documentation proves useful for v13 developers--the majority of the documentation is the same between the two versions. We will be leaving the v12 documentation up on the site for an extended period of time.

We'll be releasing translations for additional languages in the future, so stay tuned for more updates!

--The AdWords API Team

AdWords Downtime: February 21, 10am-2pm PST

Tuesday, February 17, 2009


We'll be performing routine system maintenance on Saturday, February 21 from approximately 10:00am to 2:00pm PST. You won't be able to access AdWords or the API during this time frame, but your ads will continue to run as normal.

Cheers,
-Jeffrey Posnick, AdWords API Team

Sunsetting v12 on February 23, 2009

Wednesday, February 04, 2009


In accordance with our policy of sunsetting older versions of the AdWords API, we will turn off access to version 12 of the API on Monday, February 23, 2009. Version 13 of the API has been available for over four months now, and supports a number of new features. We hope that you've already taken the opportunity to upgrade your code.

The latest versions of the publicly available official Google client libraries all support version 13 of the API, so if you're using one of those, please check the relevant README file for information on how to switch from version 12 to 13.

As always, if you have any questions about the AdWords API or upgrading to our latest versions, you can check out our Frequently Asked Questions or ask them in our developer forum.

-- AdWords API Team

Keyword Match Type and the KeywordToolService

Tuesday, January 20, 2009


We first blogged about AdWords API v13's new keyword search volume info functionality back in November, and it remains a popular topic among developers. We've heard a number of follow-up questions about how the results from v13's KeywordToolService match up with the results available via the corresponding web application, especially when it comes to issues regarding keyword match type. There are two different scenarios in which you might want to specify match type when retrieving keyword variations, and hopefully the information in this blog post will clear up some confusion as to how the KeywordToolService supports that functionality.

One scenario involves giving a hint to the keyword variation service as to what kind of query you want to use as the seed. If you're calling getKeywordVariations(), you use the type attribute of the SeedKeyword object to do this. So, for example, if you want to generate variations based on a phrase match for "baseball bat", you'd specify "Phrase" for the type attribute and "baseball bat" for the text attribute of the SeedKeyword. If instead of a phrase match you were interested in generating keyword variations based on a broad match, you'd instead specify "Broad" for the type attribute. The important thing here is that the type attribute can affect the specific variations that are returned. In the "baseball bat" example, most of the variation keywords that are returned are the same for the two match types, but there are some differences. For example, the variation "baseball training bat" is only returned when you specify a Broad match type.

The options outlined above directly translate into using the web version of the tool and specifying two different match types for the source keyword. In the section in which you're instructed to "Enter one keyword or phrase per line", if you were to enter the literal text "baseball bat" (with quotes) you'd specify a Phrase match type. If you entered baseball bat (without quotes) you'd specify a Broad match type. (An Exact match type is expressed as [baseball bat], i.e. with brackets around the text.)

This distinction only applies to the getKeywordVariations() method of the KeywordToolService. getKeywordsFromSite() doesn't allow you to specify a match type for the source keyword because there is no source keyword; instead, you're passing in a specific URL to use as the source, and a match type would not make sense in that context.

The second scenario in which you might care about match type involves the search volume results for each SiteKeyword or KeywordVariation object that is returned from getKeywordsFromSite() and getKeywordVariations(). The web version of the tool provides a popup menu in the results area allowing you to select the match type you're interested in. When you choose a match type, it will update the search volume information of each suggested keyword accordingly. Unfortunately, there is currently no way to retrieve search volumes for different match types using the API's KeywordToolService methods. The search volumes in the results returned from the API should roughly correspond to what you'd see with the Broad setting for match type in the web tool, but retrieving search volumes for Phrase or Exact match types is not possible.

--Jeffrey Posnick, AdWords API Team