There have been some discussions about this already, notably a QCon presentation, but a redundant tutorial or two never hurt a soul. This is for the Python version of App Engine, but it shouldn’t be much different for Java.
Why?
App Engine datastore writes are really expensive, and prohibitively so for something like custom statistics. For example, in an early version of SearchEkko, where I read and wrote to an “Admin” Model object on most operations, it was costing over $6.20 CPM to serve SearchEkko search results pages! This when the marginal cost of web-delivered content is supposed to be zero. Obviously, App Engine wasn’t designed with this kind of usage in mind, but it was equally clear that I needed some type of custom statistics dashboard (how many displays, how many installs, etc). So I started poking around.
The Requirements (And Can-Do-Withouts)
To summarize, I needed some type of database solution that:
- Offered cheap (as in resources) read and write access
- Was cheap (as in money)
- Was easily accessible from App Engine (so probably REST)
- Tolerated frequent accesses and responded relatively quickly
Since all I needed was a way to track statistics, I could forego a lot of typical database niceties, like:
- Transactions and thread safety
- Guaranteed data integrity
- Bullet-proof security
Google Spreadsheets was what I eventually found, and so far it’s met my needs almost to a T.
Note: if you’re looking for something to use with real, critical data, look elsewhere. This is definitely a little hacky, and certainly isn’t perfect, but it’s a relatively easy way to track things you don’t care that much about in App Engine.
Setting Up Your Spreadsheet
Just go into Google Documents and create a new spreadsheet. The URL will be something like
http://spreadsheets.google.com/ccc?key=bNadyGyiH2Ma6Cx54NmiL2e__4g&hl=en
Note the value of the key argument — you’ll have to use it later.
When you’re accessing your spreadsheet from App Engine, it’s easiest to just set specific cells to the values you want. This means you can lay out the spreadsheet pretty intuitively. In my SearchEkko statistics spreadsheet, I simply made the first row labels for each column, with the corresponding data falling below each label, exactly as you’d set up a standard spreadsheet.
Accessing Your Spreadsheet
In order to access your spreadsheet you have to use the Google Spreadsheets API. There is a Python library you can use, but it’s apparently outdated now. Plus, for something pretty easy like this, I’d rather just use the base protocol, and that way I’ll be more likely to know what’s going on when something breaks.
In any case, you need to authenticate in order access your private spreadsheet data from App Engine. The best way to do that for our purposes is by using AuthSub. AuthSub is similar to OAuth, but isn’t an open standard, and is a bit better-suited to Google-specific tasks. More to the point, it’s what I used, so it’s what you’re learning.
One of the easiest ways to play around with AuthSub is by downloading RESTClient, an addon for Firefox. Play around with it to learn how to submit HTTP POST and GET requests to specific URLs, and with modified headers, or use another tool of your choice.
The next steps are also documented here, but I’ve tried to simplify and streamline them for your coding pleasure.
- Direct your browser to:
https://www.google.com/accounts/AuthSubRequest?scope=http%3A%2F%2Fspreadsheets.google.com%2Ffeeds%2F&session=1&secure=0&next=http%3A%2F%2Fwww.example.com
Naturally swap www.example.com with your own site. Grant access, and note the URL that it sends you to. Copy the the token parameter. That’s your single-use AuthSub token.
Note: This should work fine as-is if your site is hosted on App Engine, but if it’s not (ignoring for the moment why you’re reading this), there may be some additional steps here.
- Send a GET request (in RESTClient terms) to the URL
https://www.google.com/accounts/AuthSubSessionToken
Use headers:
Content-Type: application/x-www-form-urlencoded
Authorization: AuthSub token="yourAuthToken"
Obviously replace "yourAuthToken" with the single-use token you received, but keep the quotes. You should get back a 200 OK status code, and the body will include your session token. Though some documentation shows this value having an expiration, it really is usable indefinitely. (You can revoke any tokens your Google Account has given out here).
Alright, now you have your indefinite-use AuthSub session token, and you’re one giant step closer to mingling Google Spreadsheets and App Engine.