About the Author

author photo

Adam Trachtenberg is the Director of the LinkedIn Developer Network, where he oversees developer relations and marketing for the LinkedIn Platform. Before LinkedIn, Adam worked at eBay in platform product management and marketing. Even earlier, he co-founded Student.Com and TVGrid.com. Adam is the author of PHP Cookbook and Upgrading to PHP 5. He lives in San Francisco.

See All Posts by This Author

Using the Google AdWords API with ext/soap

On Friday, Jeffrey showed me Nelson’s new Google AdWords API service. Google has now exposed all parts of the AdWords program via a SOAP Web service API.

Unfortunately, SOAP and PHP still aren’t the best of friends. True, Nelson has graciously provided us with some NuSOAP PHP example code. However, when I viewed it, I immediately barfed all over myself. Gross!

Any SOAP library that requires you to use angle-brackets is missing the point of SOAP. To be fair, I’d never used NuSOAP before today, so maybe it’s possible to rewrite the code to be more elegant, but I couldn’t stomach trying.

I mean, come on. This is no way to set a SOAP header:

// Set up the authentication headers
$email = "<email>youremail@your company.com</email>";
$password = "<password>yourpassword</password>";
$userAgent = "<useragent>YOURCOMPANY -- PHP KeywordReport Demo</useragent>";
$token = "<token>developer_token_here_</token>";
$header = $email . $password . $userAgent . $token;

And comments like this?

// With nusoap, you need to include XML with the parameters
$keyword0 = "<text>flowers</text>";
$keyword1 = "<text>chocolates</text>";
$otherinfo = "<maxCpc>50000</maxCpc><type>Broad</type>";

I need to include XML?!? Forget it.

So, out of the spirit of being a good citizen, I rewrote the "Estimating traffic for a keyword" example using PHP 5’s ext/soap extension.

// Connect to the WSDL for the TrafficEstimatorService
$wsdl = "https://adwords.google.com/api/adwords/v2/TrafficEstimatorService?wsdl";
$client = new SOAPClient($wsdl));

// Create the SOAP Headers for authentication
$ns = 'https://adwords.google.com/api/adwords/v2';
$email = new SOAPHeader($ns, 'email', 'adam@trachtenberg.com');
$password = new SOAPHeader($ns, 'password', 'XXX');
$useragent = new SOAPHeader($ns, 'useragent', 'Blah, blah');
$token = new SOAPHeader($ns, 'token', 'XXX');
$headers = array($email, $password, $useragent, $token);

// The Keywords we're interested in
$keywords = array(array('text' => 'php', 'maxCpc' => 100000, 'type'=> 'Broad'),
                  array('text' => 'mysql', 'maxCpc' => 250000, 'type' => 'Broad'),
                 );
try {
  // Make the request to estimate the keywords
  $response = $client->__soapCall('estimateKeywordList',  array($keywords), null, $headers);

  // If we got this far, $response contains the estimates
  $count = count($response->estimateKeywordListReturn);
  echo "<P>There are " . $count . " elements in the response array.";

  // A single  response is returned as an array of field values.
  // Multiple responses are returned as an array of arrays.
  if (! is_array($response->estimateKeywordListReturn)) {
    $response->estimateKeywordListReturn = array($response->estimateKeywordListReturn);
  }

  for ($i = 0; $i < $count; $i++) {
    // Need to get the keyword text out of $keywords array
    // because the keywordEstimate doesn't know the keyword text
    echo "<H3>" . $keywords[$i]['text'] . "</H3>";
    printResults($response->estimateKeywordListReturn[$i]);
  }
} catch (Exception $e) {
  // Barf
  print $e;
}

function printResults ($estimate) {
  echo "<blockquote>cpc " . $estimate->cpc;
  echo "<br>clicks " . $estimate->ctr * $estimate->impressions;
  echo "<br>ctr " . $estimate->ctr;
  echo "<br>impressions " . $estimate->impressions;
  echo "<br>notShown " . $estimate->notShownPerDay;
  echo "<br>position " . $estimate->avgPosition;
  echo "</blockquote>";
}

No more XML. Still a little kludgy because of the SOAP headers, but overall much nicer.

In the process, I found a bug involving SOAPHeader objects when you don’t want your data to live inside a namespace, but I managed to work around that by placing them inside the AdWords API namespace.

I was also thrown a little bit by the example, which places the keywords inside a “KeywordRequest” element, when the WSDL seems to want a “keywordRequests” element. (Note different capitalization and pluralization.) This had me running down all sorts of dead ends and blaming the WSDL parser.

Last, I’m confused why the server doesn’t return the keywords back to me. Forcing me to map the input and the output is a little kludgy.

Overall, however, this looks quite nice. I plan on playing around with it more later, and I’m sure our eBay API Affiliates are having a field day.

Popularity: 52% [?]

There Are 10 Responses So Far. »

  1. Excellent article, can u writte de code for php 4 as well ?
    thaks a lot .

  2. Google provides PHP 4 NuSOAP code examples. I would suggest you check out those, as I’m not really doing much in PHP 4 anymore.

  3. Hi again,
    I’m traying to do a newKeyword with the api , in the google adwords api forum i didn’t found nothing related with this problem the is in PHP5 based on your example.
    “123456789″,’text’ => ’spanish’, ‘maxCpc’=>’50000′ ,’type’=> ‘Broad’);

    try {
    // Make the request to create the keyword
    $response = $client->__soapCall(‘newKeyword’, $keyword, null, $headers);
    } catch (Exception $e) {
    // Barf
    print $e.’:Excepción’;
    }

    ?>

    I know this is not a thech support , but may be this example can be util for more people if we get working

  4. I’m sorry for paste the code uncorrectly ,
    i pasted the code example here-> http://pastebin.com/299766

  5. Can you also post an example of a report service SOAP request?

  6. Sorry Ken, I haven’t used this API in a while, so I don’t have an example I can share.

  7. Perhaps you know a bit more about ext/soap that you can help me. As you noticed that an array in PHP gets converted to a SOAP complex type like this:

    array(‘job’ => array(’startDate’ => ‘yesterday’, ‘endDate’ => ‘today’));

    yesterdaytoday

    What if I want

    ….

    instead? what would I have to do in the array?

  8. Hum… Maybe WordPress ate some of your comment? Regardless, try the PHP SOAP mailing list.

    http://us2.php.net/mailing-lists.php

    I’m on that list, and so are a lot of other people, maybe including someone who has done this before. (And the author of the SOAP extension.)

  9. Hi,

    I currently trying to make a soap call to paypal api …
    I’ve found this example for Express Checkout. I need to make a DirectPayment
    but I supose that the logical is the same …

    http://www.pdncommunity.com/attachments/pdn/api/594/1/DoExpressCheckoutRequestexample.xml

    So I’ve started to write this code … but my problem is I don’t how can I declare children body nodes as this …
    DoExpressCheckoutPaymentRequest
    + DoExpressCheckoutPaymentRequestDetails
    + PaymentDetails
    +OrderTotal

    Should I use SoapVar too ?

    $ns = “urn:ebay:api:PayPalAPI”;
    $wsdluri = ‘https://www.sandbox.paypal.com/wsdl/PayPalSvc.wsdl’;

    $paypalAuth = array(
    ‘Username’ => new SOAPVar(‘concentre_api1.zensoluciones.com’, XSD_STRING, null, null, null, $ns),
    ‘Password’ => new SOAPVar(”, XSD_STRING, null, null, null, $ns)
    );

    $headerBody = new SOAPVar($paypalAuth, SOAP_ENC_OBJECT);
    $header = new SOAPHeader($ns, ‘Credentials’, $headerBody);

    $client = new SOAPClient($_wsdluri);
    $client->__soapCall(‘DoDirectPaymentReq’, array(), array(), array($header));

    regards

  10. DONT! use the Google Apility (the OpenSource code provided by Google), because it is buggy AND uses nusoap. We are just about to rewrite it, using the same techniques this articles just offered (namely, using the WSDL :P)

Post a Response