Update of /project/cl-soap/cvsroot/public_html In directory common-lisp.net:/tmp/cvs-serv646
Modified Files: google-adwords-api.html index.html Log Message: documentation update to latest state of code
Date: Sat Oct 1 11:24:11 2005 Author: scaekenberghe
Index: public_html/google-adwords-api.html diff -u public_html/google-adwords-api.html:1.2 public_html/google-adwords-api.html:1.3 --- public_html/google-adwords-api.html:1.2 Tue Sep 27 22:35:16 2005 +++ public_html/google-adwords-api.html Sat Oct 1 11:24:11 2005 @@ -35,110 +35,63 @@ Binding: api:InfoServiceSoapBinding SOAP style [document] Operation: getUnitCountForMethod Input: getUnitCountForMethodRequest - Element "getUnitCountForMethod" [required] - Member "service" of primitive type "string" [required] - Member "method" of primitive type "string" [required] - Member "startDate" of primitive type "date" [required] - Member "endDate" of primitive type "date" [required] - <getUnitCountForMethod> - <service>string</service> - <method>string</method> - <startDate>date</startDate> - <endDate>date</endDate> - </getUnitCountForMethod> + (getUnitCountForMethod + ("service" :STRING) 1 + ("method" :STRING) 1 + ("startDate" :DATE) 1 + ("endDate" :DATE) 1 ) 1 Output: getUnitCountForMethodResponse - Element "getUnitCountForMethodResponse" [required] - Member "getUnitCountForMethodReturn" of primitive type "long" [required] - <getUnitCountForMethodResponse> - <getUnitCountForMethodReturn>long</getUnitCountForMethodReturn> - </getUnitCountForMethodResponse> + (getUnitCountForMethodResponse + ("getUnitCountForMethodReturn" :LONG) 1 ) 1 Operation: getUnitCount Input: getUnitCountRequest - Element "getUnitCount" [required] - Member "startDate" of primitive type "date" [required] - Member "endDate" of primitive type "date" [required] - <getUnitCount> - <startDate>date</startDate> - <endDate>date</endDate> - </getUnitCount> + (getUnitCount + ("startDate" :DATE) 1 + ("endDate" :DATE) 1 ) 1 Output: getUnitCountResponse - Element "getUnitCountResponse" [required] - Member "getUnitCountReturn" of primitive type "long" [required] - <getUnitCountResponse> - <getUnitCountReturn>long</getUnitCountReturn> - </getUnitCountResponse> + (getUnitCountResponse + ("getUnitCountReturn" :LONG) 1 ) 1 Operation: getMethodCost Input: getMethodCostRequest - Element "getMethodCost" [required] - Member "service" of primitive type "string" [required] - Member "method" of primitive type "string" [required] - Member "date" of primitive type "date" [required] - <getMethodCost> - <service>string</service> - <method>string</method> - <date>date</date> - </getMethodCost> + (getMethodCost + ("service" :STRING) 1 + ("method" :STRING) 1 + ("date" :DATE) 1 ) 1 Output: getMethodCostResponse - Element "getMethodCostResponse" [required] - Member "getMethodCostReturn" of primitive type "int" [required] - <getMethodCostResponse> - <getMethodCostReturn>int</getMethodCostReturn> - </getMethodCostResponse> + (getMethodCostResponse + ("getMethodCostReturn" :INT) 1 ) 1 Operation: getUsageQuotaThisMonth Input: getUsageQuotaThisMonthRequest - Element "getUsageQuotaThisMonth" [required] - <getUsageQuotaThisMonth> - </getUsageQuotaThisMonth> + ("getUsageQuotaThisMonth") Output: getUsageQuotaThisMonthResponse - Element "getUsageQuotaThisMonthResponse" [required] - Member "getUsageQuotaThisMonthReturn" of primitive type "long" [required] - <getUsageQuotaThisMonthResponse> - <getUsageQuotaThisMonthReturn>long</getUsageQuotaThisMonthReturn> - </getUsageQuotaThisMonthResponse> + (getUsageQuotaThisMonthResponse + ("getUsageQuotaThisMonthReturn" :LONG) 1 ) 1 Operation: getOperationsQuotaThisMonth Input: getOperationsQuotaThisMonthRequest - Element "getOperationsQuotaThisMonth" [required] - <getOperationsQuotaThisMonth> - </getOperationsQuotaThisMonth> + ("getOperationsQuotaThisMonth") Output: getOperationsQuotaThisMonthResponse - Element "getOperationsQuotaThisMonthResponse" [required] - Member "getOperationsQuotaThisMonthReturn" of primitive type "long" [required] - <getOperationsQuotaThisMonthResponse> - <getOperationsQuotaThisMonthReturn>long</getOperationsQuotaThisMonthReturn> - </getOperationsQuotaThisMonthResponse> + (getOperationsQuotaThisMonthResponse + ("getOperationsQuotaThisMonthReturn" :LONG) 1 ) 1 Operation: getOperationCount Input: getOperationCountRequest - Element "getOperationCount" [required] - Member "startDate" of primitive type "date" [required] - Member "endDate" of primitive type "date" [required] - <getOperationCount> - <startDate>date</startDate> - <endDate>date</endDate> - </getOperationCount> + (getOperationCount + ("startDate" :DATE) 1 + ("endDate" :DATE) 1 ) 1 Output: getOperationCountResponse - Element "getOperationCountResponse" [required] - Member "getOperationCountReturn" of primitive type "long" [required] - <getOperationCountResponse> - <getOperationCountReturn>long</getOperationCountReturn> - </getOperationCountResponse></pre> + (getOperationCountResponse + ("getOperationCountReturn" :LONG) 1 ) 1 </pre> The input and output characteristics of each operation are described in some detail. - Example template XML code of actaul input and output are also given. + Example lisp template code of actaul input and output are also given (along with multiplicity indication, whether elements are required, optional, can occur zero ore more times, or one or more times). </p> <p> Given that you understand a particular operation, you can implement it quite easily. - <pre>(defun get-method-cost (service method &optional (date (get-universal-time))) + <pre>(defun get-method-cost (service method &optional (date (ut))) (wsdl-soap-call (wsdl-cache-get "https://adwords.google.com:443/api/adwords/v2/InfoService?wsdl") "getMethodCost" - :input `("service" ,service - "method" ,method - "date" ,date) - :headers `("email" ,*google-adwords-email* - "password" ,*google-adwords-password* - "useragent" ,*google-adwords-user-agent* - "token" ,*google-adwords-token* - "clientEmail" ,*google-client-email*)))</pre> + :input `("getMethodCost" ("service" ,service "method" ,method "date" ,date)) + :headers (make-google-headers)))</pre> For the Google AdWords API, some headers are required. - The method implemented above requires some parameters, specified to the framework as a simple alist. + The method implemented above requires some parameters, specified to the framework as a structured alist. With debugging enabled (using (setf *debug-stream* *output-stream*)), executing the call looks as follows: <pre>CL-SOAP 85 > (get-method-cost "InfoService" "getMethodCost")
@@ -190,8 +143,7 @@ </units> </soapenv:Header> <soapenv:Body> - <getMethodCostResponse - xmlns="https://adwords.google.com/api/adwords/v2%22%3E; + <getMethodCostResponse xmlns="https://adwords.google.com/api/adwords/v2%22%3E; <getMethodCostReturn>1</getMethodCostReturn> </getMethodCostResponse> </soapenv:Body> @@ -203,8 +155,185 @@ Some sensitive data fields have been marked with X's. XML was beautified a little bit ;-) Note that two values are returned: the actual value and the headers. - Stay tuned for more complicated examples later on. </p> -<p>$Id: google-adwords-api.html,v 1.2 2005/09/27 20:35:16 scaekenberghe Exp $</p> +<p> + A more complicated example comes from the <a href="http://www.google.com/apis/adwords/developer/index.html">introduction to the Google AdWords API</a>: estimating the traffic for keywords. Again, we first look at the interpreted WSDL: + <pre>CL-SOAP 43 > (describe-wsdl-soap (wsdl-cache-get "https://adwords.google.com:443/api/adwords/v2/TrafficEstimatorService?wsdl")) +WSDL Document Definitions + Service: TrafficEstimatorService + Port: TrafficEstimatorService + SOAP Address Location "https://adwords.google.com:443/api/adwords/v2/TrafficEstimatorService" + Binding: api:TrafficEstimatorServiceSoapBinding SOAP style [document] + Operation: estimateKeywordList + Input: estimateKeywordListRequest + (estimateKeywordList + (keywordRequests ( + ("id" :LONG) ? + ("type" :STRING) ? + ("text" :STRING) ? + ("maxCpc" :LONG) ? + ("negative" :BOOLEAN) ? ) + )) 1 + Output: estimateKeywordListResponse + (estimateKeywordListResponse + (estimateKeywordListReturn ( + ("id" :LONG) ? + ("impressions" :INT) 1 + ("ctr" :FLOAT) 1 + ("cpc" :LONG) 1 + ("avgPosition" :FLOAT) 1 + ("notShownPerDay" :INT) 1 ) + )) 1 + Operation: estimateAdGroupList + Input: estimateAdGroupListRequest + (estimateAdGroupList + (adGroupRequests ( + ("id" :INT) ? + ("maxCpc" :LONG) ? + (keywordRequests ( + ("id" :LONG) ? + ("type" :STRING) ? + ("text" :STRING) ? + ("maxCpc" :LONG) ? + ("negative" :BOOLEAN) ? ) + )) + )) 1 + Output: estimateAdGroupListResponse + (estimateAdGroupListResponse + (estimateAdGroupListReturn ( + ("id" :INT) ? + (keywordEstimates ( + ("id" :LONG) ? + ("impressions" :INT) 1 + ("ctr" :FLOAT) 1 + ("cpc" :LONG) 1 + ("avgPosition" :FLOAT) 1 + ("notShownPerDay" :INT) 1 ) + )) + )) 1 + Operation: estimateCampaignList + Input: estimateCampaignListRequest + (estimateCampaignList + (campaignRequests ( + ("id" :INT) ? + ("optInSearchNetwork" :BOOLEAN) ? + ("optInContentNetwork" :BOOLEAN) ? + (geoTargeting + ("countries" (:STRING) * ) + ("regions" (:STRING) * ) + ("metros" (:STRING) * ) + ("cities" (:STRING) * )) ? + (languageTargeting + ("languages" (:STRING) * )) ? + (adGroupRequests ( + ("id" :INT) ? + ("maxCpc" :LONG) ? + (keywordRequests ( + ("id" :LONG) ? + ("type" :STRING) ? + ("text" :STRING) ? + ("maxCpc" :LONG) ? + ("negative" :BOOLEAN) ? ) + )) + )) + )) 1 + Output: estimateCampaignListResponse + (estimateCampaignListResponse + (estimateCampaignListReturn ( + ("id" :INT) ? + (adGroupEstimates ( + ("id" :INT) ? + (keywordEstimates ( + ("id" :LONG) ? + ("impressions" :INT) 1 + ("ctr" :FLOAT) 1 + ("cpc" :LONG) 1 + ("avgPosition" :FLOAT) 1 + ("notShownPerDay" :INT) 1 ) + )) + )) + )) 1</pre> + Next we define our little lisp function: + <pre>(defun estimate-keyword-list (keywords) + "((text type max-cpc)*) where type is Broad|Phrase|Exact" + (wsdl-soap-call (wsdl-cache-get "https://adwords.google.com:443/api/adwords/v2/TrafficEstimatorService?wsdl") + "estimateKeywordList" + :input `("estimateKeywordList" + ("keywordRequests" + ,(mapcar #'(lambda (keyword) + (destructuring-bind (text type max-cpc) + keyword + `("text" ,text "type" ,type "maxCpc" ,max-cpc))) + keywords))) + :headers (make-google-headers)))</pre> + Now we can test it, passing multiple requests and receiving multiple responses: + <pre>CL-SOAP 192 > (estimate-keyword-list '(("flowers" "Broad" 50000) ("tree" "Broad" 50000))) +;; SOAP CALL sending: +<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/1999/XMLSchema" xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance" xmlns:google="https://adwords.google.com/api/adwords/v2" xmlns="https://adwords.google.com/api/adwords/v2%22%3E; + <soapenv:Header> + <token>XXX</token> + <useragent>cl-soap-testing</useragent> + <password>XXX</password> + <clientEmail>sven@beta9.be</clientEmail> + <email>svc@mac.com</email> + </soapenv:Header> + <soapenv:Body> + <estimateKeywordList> + <keywordRequests> + <type>Broad</type> + <text>flowers</text> + <maxCpc>50000</maxCpc> + </keywordRequests> + <keywordRequests> + <type>Broad</type> + <text>tree</text> + <maxCpc>50000</maxCpc> + </keywordRequests> + </estimateKeywordList> + </soapenv:Body> +</soapenv:Envelope> +;; SOAP CALL receiving: +<soapenv:Envelope + xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:xsd="http://www.w3.org/1999/XMLSchema" + xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance%22%3E; + <soapenv:Header> + <responseTime + soapenv:actor="http://schemas.xmlsoap.org/soap/actor/next" + soapenv:mustUnderstand="0" + xmlns="https://adwords.google.com/api/adwords/v2%22%3E; + 412 + </responseTime> + <operations + soapenv:actor="http://schemas.xmlsoap.org/soap/actor/next" + soapenv:mustUnderstand="0" + xmlns="https://adwords.google.com/api/adwords/v2%22%3E; + 2 + </operations> + <units + soapenv:actor="http://schemas.xmlsoap.org/soap/actor/next" + soapenv:mustUnderstand="0" + xmlns="https://adwords.google.com/api/adwords/v2%22%3E; + 50 + </units> + </soapenv:Header> + <soapenv:Body> + <estimateKeywordListResponse xmlns="https://adwords.google.com/api/adwords/v2%22%3E; + <estimateKeywordListReturn> + <avgPosition>4.537519</avgPosition> + <cpc>50000</cpc> + <ctr>0.01547993</ctr> + <id>-1</id> + <impressions>7263</impressions> + <notShownPerDay>288532</notShownPerDay> + </estimateKeywordListReturn> + <estimateKeywordListReturn> + <avgPosition>2.8274193</avgPosition> + <cpc>50000</cpc> + <ctr>0.012525387</ctr> + <id>-1</id> + <impressions>18177</impressions> + <notShownPerDay>397941</notShownPerDay> + </estimateKeywordListReturn> + </estimateKeywordListResponse> + </soapenv:Body> +</soapenv:Envelope> + +("estimateKeywordListResponse" + ("estimateKeywordListReturn" + (("id" -1 "impressions" 7263 "ctr" 0.01547993 "cpc" 50000 "avgPosition" 4.537519 "notShownPerDay" 288532) + ("id" -1 "impressions" 18177 "ctr" 0.012525387 "cpc" 50000 "avgPosition" 2.8274193 "notShownPerDay" 397941)))) + +((GOOGLE:|responseTime| . "412") (GOOGLE:|operations| . "2") (GOOGLE:|units| . "50"))</pre> + That is all for now! More example and testing code can be found in the project's source tree. +<p>$Id: google-adwords-api.html,v 1.3 2005/10/01 09:24:11 scaekenberghe Exp $</p> </body> </html>
Index: public_html/index.html diff -u public_html/index.html:1.7 public_html/index.html:1.8 --- public_html/index.html:1.7 Tue Sep 27 22:28:32 2005 +++ public_html/index.html Sat Oct 1 11:24:11 2005 @@ -78,7 +78,7 @@ Currently, phase 1 (and then some) has been implemented. </p> <ul> - <li>S-XML was extended to support XML Namespaces</li> + <li>S-XML was extended to support XML Namespaces.</li> <li>Basic, manual SOAP calls are now possible, for example: <pre>(defun xmethods-get-quote (symbol) "Calling http://services.xmethods.net/soap/urn:xmethods-delayed-quotes.wsdl" @@ -122,13 +122,13 @@ "getRate" :input `("country1" ,country1 "country2" ,country2)))</pre> </li> - <li>Https support in http-client.lisp was added for LispWorks</li> - <li>The general function soap-call was extended to handle headers (input and output headers)</li> - <li>The function wsdl-soap-call now handles document based SOAP calls too</li> - <li>Partial support for XML Schema Defintion types definition in WSDL has been implemented</li> + <li>Https support in http-client.lisp was added for LispWorks.</li> + <li>The general function soap-call was extended to handle headers (input and output headers).</li> + <li>The function wsdl-soap-call now handles document based SOAP calls too.</li> + <li>Partial support for XML Schema Defintion types definition in WSDL has been implemented. To simplify the general XSD spec (which we don't need, does anybody ?), we are using a simplified template representation internally.</li> <li>The target of being able to talk to the Google AdWords API has been reached! A separate document, <a href="google-adwords-api.html">Google AdWords API</a> describes this in more detail - and with some verbose examples</li> + and with some verbose examples.</li> <li>Lot's of work remains to be done! All help is welcome.</li> </ul> </p> @@ -170,6 +170,6 @@ Initial developers and contributors will include Sven Van Caekenberghe (Beta Nine), Alain Picard (Memetrics), Ivan Melotte (Beta Nine) and Nicky Peeters (Beta Nine). <p> -<p>$Id: index.html,v 1.7 2005/09/27 20:28:32 scaekenberghe Exp $</p> +<p>$Id: index.html,v 1.8 2005/10/01 09:24:11 scaekenberghe Exp $</p> </body> </html>