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.
Comment by Alfonso on 1 June 2005:
Excellent article, can u writte de code for php 4 as well ?
thaks a lot .
Comment by Adam Trachtenberg on 1 June 2005:
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.
Comment by Alfonso on 15 June 2005:
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
Comment by Alfonso on 15 June 2005:
I’m sorry for paste the code uncorrectly ,
i pasted the code example here-> http://pastebin.com/299766
Comment by Ken on 18 January 2006:
Can you also post an example of a report service SOAP request?
Comment by Adam Trachtenberg on 18 January 2006:
Sorry Ken, I haven’t used this API in a while, so I don’t have an example I can share.
Comment by Ken on 19 January 2006:
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?
Comment by Adam Trachtenberg on 19 January 2006:
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.)
Comment by Sébastien Cramatte on 18 November 2006:
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
Comment by Georgi Mateev on 31 August 2007:
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)