This article is written for advanced ASP programmers and a walk-through of the common principles in the code will not be provided. In fact, after spending a few hours tackling the darkest secrets of Google Base amid a complete absence of sensical documentation, I don't feel like explaining much if anything about the code. If you are reading this post, you should understand everything in this code simply enough so I won't bog you down with over-complicated explanations.
Show me the CODE!
If you've read the forums, many of you have tried feeding into Google Base using ASP and the forum responses usually say it cannot be easily done. I posted a question a few days ago along w/ a simple code snippet and got a response similar to:
"Why are you using native HTTP access? Why don't you use the pre-packaged libraries available in the most common languages like C#, Python, and Java?"
My response was similar to (but more nicely worded):
A.) Because I'm using ASP and no examples are posted for ASP, nor are any libraries available.
B.) Because as a programmer I tend to stick w/ the language and technology I amm most familiar w/, despite which examples are readily available, though I will glean as much information as possible from the samples if properly provided.
C.) As a programmer who loves my "sport", I prefer to stay away form libraries, components, and anything else that abstracts me from the code.
D.) So I don't one day answer someone's post w/ a stupid comment about using the provided libraries instead of figuring it out on my own.
You should know a few things before proceeding down this path:
A.) Don't even bother w/ the examples. The Base team provides pre-written libraries in some languages that accomplish so much of the task that the example code shown for the actual operation is only a few lines, completely abstracted from what is actually going on! Heavn forbid you need to loop around a transaction and ensure memory levels are kept at minimums!
B.) The most confusing point - Base accepts data in two very different and distinct main XML formats and they differ for whether you are sending the data via HTTP or FTP. An excerpt below form my conversation w/ a Base employee:
"I had no idea the XML format was different b/w the feed and the API. I incorrectly assumed the formats you accepted would be universal, regardless of means of data transport. I assumed such b/c it's the way I would've designed the system, primarily to encourage developers to move towards a real-time HTTP transfer from an asynchronous FTP feed without much of a re-write."
I am pasting the code for a working example below and I will discuss it below the entire code section:
'--DIM
dim http
dim gbase_username
dim gbase_password
dim gbase_key
dim gbase_token
dim lis_id
dim lis_xml
dim gbase_item_id'--INIT
gbase_username = "yourregisteredusername@youremaildomain.com"
gbase_password = "yourpassword"
gbase_key = "ABQIAAAAXARkTM3sv...your key here....AAXARkTM3"
lis_id = "12345"'--CREATE http object once so it can be used universally for all operations
set http = server.createObject("MSXML2.ServerXMLHTTP")'--CONNECT to gbase and retrieve token value for data exchange
gbase_token = gbase_connect(gbase_username, gbase_password, gbase_key)'--HAS token value?
IF (gbase_token <> "") THEN'--GENERATE xml for item from our database
lis_xml = gbase_xml(lis_id)'--TRANSFER item to google base and return id
gbase_item_id = gbase_transfer(gbase_key, gbase_token)'--HAS item id in response?
IF (gbase_item_id <> "") THEN'--UPDATE listing in database w/ gbase item id
'conn.execute ("UPDATE LISTING SET GBASE_ID = '" & gbase_item_id & "' WHERE LIS_ID = " & lis_id)END IF
END IF
'--CLOSE
set http = nothingFUNCTION midstr(byval str, byval char1, byval char2)
IF (instr(str, char1) > 0 AND instr(str, char2) > 0) THEN
midstr = mid(str, (instr(str, char1) + len(char1)), (instr((instr(str, char1) + len(char1)), str, char2) - (instr(str, char1) + len(char1))))
END IF
END FUNCTION
FUNCTION gbase_connect(byval gbase_username, byval gbase_password, byval gbase_key)
'--OPEN object
http.open "POST", "https://www.google.com/accounts/clientlogin", false'--SET headers
http.setrequestheader "Content-Type", "application/x-www-form-urlencoded"
http.setrequestheader "X-Google-Key", gbase_key'--EXECUTE request
http.send ("Email=" & gbase_username & "&Passwd=" & gbase_password & "&service=gbase&accountType=HOSTED_OR_GOOGLE")'--PARSE the token out of the gbase server response
gbase_connect = midstr(http.responsetext, "Auth=", chr(10))END FUNCTION
FUNCTION gbase_transfer(byval gbase_key, byval gbase_token)
'--OPEN object
http.open "POST", "http://www.google.com/base/feeds/items", false'--SET headers
http.setrequestheader "Content-Type", "application/atom+xml"
http.setrequestheader "X-Google-Key", gbase_key
http.setrequestheader "Authorization", ("GoogleLogin auth=" & gbase_token)'--EXECUTE request
http.send lis_xml'--GET google base id from response
gbase_transfer = midstr(http.responsetext, "<id>http://www.google.com/base/feeds/items/", "</id>")END FUNCTION
FUNCTION gbase_xml(byval lis_id)
'--GENERATE xml - sample from gbase
gbase_xml = ("<?xml version='1.0'?>" & vbcrlf & vbcrlf & _
"<entry xmlns='http://www.w3.org/2005/Atom' xmlns:g='http://base.google.com/ns/1.0'>" & vbcrlf & _
" <author>" & vbcrlf & _
" <name>Jane Doe</name>" & vbcrlf & _
" <email>JaneDoe@gmail.com</email>" & vbcrlf & _
" </author>" & vbcrlf & _
" <category scheme='http://www.google.com/type' term='googlebase.item'/>" & vbcrlf & _
" <title type='text'>He Jingxian's chicken</title>" & vbcrlf & _
" <content type='xhtml'>" & vbcrlf & _
" <div xmlns='http://www.w3.org/1999/xhtml'>Delectable Sichuan specialty</div>" & vbcrlf & _
" </content>" & vbcrlf & _
" <link rel='alternate' type='text/html' href='http://www.host.com/123456jsh9'/>" & vbcrlf & _
" <g:item_type>Recipes</g:item_type>" & vbcrlf & _
" <g:cooking_time>30</g:cooking_time>" & vbcrlf & _
" <g:main_ingredient>chicken</g:main_ingredient>" & vbcrlf & _
" <g:main_ingredient>chili peppers</g:main_ingredient>" & vbcrlf & _
" <g:main_ingredient>peanuts</g:main_ingredient>" & vbcrlf & _
" <g:spices_used>Szechuan peppercorn</g:spices_used>" & vbcrlf & _
" <g:cook_technique>blackened</g:cook_technique>" & vbcrlf & _
"</entry>")END FUNCTION
I wrote the code above purely for the sake of publication of this article so it appears not to have a grand real world application. In practical implementation, many of the variables would be stored in initialization files, the functions would be in standard and Google Base-specific include files, and the operation would do more than update a record in a table on successful feeding. I've kept this very simple so it can be readily understood.
I also have not implemented an update or delete method. They're not necessarily as easy to implement as one would think but w/ a little tweaking of the above code, it could be accomplished w/ relative ease by sending back the Google Base Item ID (gbase_item_id) in the xml for updating or deleting. Silly me, I thought this would be enough for you feed-hungry programmers to get started w/.
Also, try to stay away from the documentation on the Google website as much as possible. Google does some things phenomenally well; however, they're extremely bad at publishing documentation. So bad in fact that it may turn you off to the idea of feeding to Base at all - which is certainly not what they want!
I have successfully run the code above to insert items into the Google Base website and am certain the code above works as advertised. To get started you will need to register for a Google account if you don't have one already, enter the domain name you will be making your server calls from, and obtain a Developer Key.
1.) Create a Google Account:
https://www.google.com/accounts/NewAccount
2.) After signing up for an account, you must generate a valid Developer Key for use w/ any of the Google APIs:
http://code.google.com/apis/base/signup.html
a.) Click the "I agree..." checkbox.
b.) Select "Web applications on the domain:" and enter your referring domain address.
c.) Save the generated key shown on your screen.
That's it! If you have questions or notes for others above this article or the code, please feel free to leave your comments.

This code comes just at the right time for me, but most of it on the right side has been cutoff on the right-side of the page, begininning at "'conn.execute ("UPDATE LISTING ...". Any chance of emailing it to me?
Posted by: Steve G | Sunday, April 20, 2008 at 12:03 PM