Since fb:google-analytics only works in Canvas pages, you need to code Profile user interaction (which is, like, 95% of the action) tracking right into your backend. Joel Neubeck posted how you can achieve the same tracking effect on the profile with client-side FBJS. He does this by wiring onclick events on links in the Profile to post AJAX calls to an external server, which then logs the action. View the post for more information.
Friday, December 28, 2007
Track user interaction in Facebook Profile with FBJS
Friday, December 21, 2007
AppJet your Facebook application
Here's a link to a guide on writing, deploying and hosting full (client-side and backend-complete) JavaScript Facebook applications with AppJet.
Some time ago, I wrote a simple Facebook application completely in FBJS. It used DOM-based dynamic user interface updates and AJAX data retrieval (via Yahoo! Pipes). As I've mentioned, it was written completely in client-side JavaScript, and I hosted the static HTML file on Google Apps. There were no backend data stores although theoretically, I could've used AJAX calls with freely available services like Openomy and Amazon S3 (or its recently limited beta launched SimpleDB) for this. Well, you can now do all of this easily with AppJet. Check it out (also, the online reference).
Related posts,
Creating RESTful JSON services with AppJet
Monday, December 17, 2007
Creating RESTful JSON services with AppJet
The newly launched AppJet makes it extremely easy to host your own JSON services. Firstly, hosting is free. Secondly, serialization of objects (which are in JavaScript, to start with) into JSON is almost equally effortless.
Just to show how easy it is to do this, I've created a simple Contacts List service hosted at http://contactsapi.appjet.net/ (view the source). The API exposes CRUD operations on a Contacts List. This list is a collection of simple contacts, each containing only a Name and an Email.
AppJet let's you write and host JavaScript web applications. (That's right, server-side JavaScript programming, and from inside your browser.) Besides full-fledged applications with flashy UIs, I've found it works just as well for bare-bones web services. If you haven't yet checked it out, I suggest you do, it rocks!
How I created the services:
- I called
page.setMode("plain"), so I could output what I needed - in this case, JSON representation of Contact objects - and nothing more, no default xhtml document structures. - AppJet doesn't support PUT and DELETE, so I relied on POST and GET only to design a REST-styled API interface. I wired up Controller-esque URL-routing using
patternDispatch()withrequest.isGetandrequest.isPostto come up with the necessary CRUD operations over HTTP. - Finally, for the GET requests, I return serialized JavaScript data resources by simply calling
Print()on the Contacts objects and arrays. This works for about 96% of the serialization I used in this example (Print()auto formats some of the objects into HTML tables), and I suspect using a ported version of the JSON stringifier found on json.org will close this gap.
Adding client-side JavaScript callbacks to the JSON results? No-brainer, just output a query-specified callback to the end of the returned JSON. Email validation for the contacts? A quick Google search yielded this regex match test.
I forgot to mention I used AppJet's excellent persistent storage classes to store the Contact List. Couple features like that with the remote-web-request-capable
wget() and wpost() and you have a wonderful zero-configuration, fast-deploy, mashup-ready platform.
Thursday, December 13, 2007
Facebook Platform is open
When OpenSocial was launched last month, Mark Cuban revealed that he talked with someone in Facebook about licensing the Facebook API half a year ago. Today, the Facebook Platform was made open, with its APIs and FBML tags ready to be licensed for use in other social sites. The guys at Facebook are releasing example FBML tag implementations, the test consoles and full documentation (read the Facebook FBML High-Level Technical Specification)!
Previously,
Challenges with Google's OpenSocial API
Wednesday, December 12, 2007
Mapping resources
Some links:
- Get To Grips with Slippy Maps - a 24 ways tutorial using Mapstraction, a JavaScript mapping abstraction library which supports GeoRSS and multiple services.
- The mashup-ready GeoCommons.
- How to convert a street address to longitude and latitude (geocoding) via web services - the article focuses on consuming GeoCoder.us services with C# (using
XmlDocument.Load()), and makes mention also of Yahoo! Maps GeoCoding API, a similar service.
Also last weekend, I discovered Google Maps added more street data to Malaysian maps. The maps are now more detailed, and complete with street names, down to small lorong-lorong in the city (here in the capital, and it looks like Malaysian small towns are catching up too). Here's an idea; Mashup Malaysian food blogger, Masak-masak's delicious looking posts into a map-enabled dining guide of the Klang Valley!
Previously on this blog:
Easily get maps on Facebook with Popfly
Open source mapping with OpenLayers and OpenStreetMap
Drawing a Virtual Earth map with Yahoo! Pipes data
Elsewhere, an interesting article:
The Rise Of Hyperlocal Information
Friday, December 7, 2007
Reference external Facebook JavaScript with script tags
FBJS can now be placed into an external file and referenced using script tags, like this:
<script src=”http://foo.com/bar.js”></script>
You point the
src attribute of the script tag to (the absolute URL of) your hosted FBJS file, as you would normally do. When your Facebook application is run, this will be rendered into a Facebook URL, which points to a cached version of your FBJS file. The caching for the external file is implemented in the same way images loaded using the img tag are cached.Previously, you could only reference external FBJS by embedding the scripts into an external FBML file, which is then loaded into your Facebook application using AJAX (with Ajax.FBML). This new feature makes it easier to refactor and maintain your client-side scripts.
Related posts on FBJS:
Lessons in FBJS
How I created a Facebook application with FBJS
Facebook releases FBJS
No JavaScript for Facebook Mobile Platform
Thursday, December 6, 2007
Microsoft releases Volta
In September, Joel (on software) wrote a thought-provoking piece; JavaScript and the DOM is the new "native", and anyone who creates the development tool which successfully targets this new universal runtime will win. Fast forward to 3 months later and Microsoft releases Volta, "a developer toolset for building multi-tier web applications" which compiles .NET code for the browser. Well, the user interface bits. Sort of like the Google Web Toolkit (GWT) and Script# then? So, how is Volta different?
Script# [and I'm thinking the GWT as well] only targets JavaScript. Volta leverages the entire .NET suite of languages and libraries including VB and C#. Volta targets multiple platforms, including JavaScript and .NET runtimes.
So, besides browser-based JavaScript, Volta is also able to target Silverlight! And probably Mono-based runtimes!
Anyway, Volta uses declarative programming (think attributes) to split .NET code for multiple tiers. You first program your application as a vanilla .NET client application, and then decide much later which parts of your code goes where (as in to client tier, or to the server tier) by labeling the classes and methods with appropriate Volta attributes. I wonder how this will affect patterns which have evolved out of traditional web application architectures.
More information can be found at the Microsoft Live Labs site. You'll need Visual Studio 2008 to try the technology preview.
Somewhat related:
Reactions (and more) to Joel's Strategy Letter;
By Collin at 9:55 PM 0 comments Links to this post
Labels: javascript, Microsoft, Silverlight, Volta
Monday, December 3, 2007
Detecting a BLOB's MIME type
This post describes how easy it was for me to include a third-party class library into my existing ASP.NET application, to determine the MIME type of BLOB data.
We used to carry a crappy ASP.NET application as part of our software solutions offering. Though we no longer sell it, there remains one customer installation for which we were obliged to support with bug-fixes. One problem that surfaced was file uploads which accepted only image files. To be accurate, the application accepted user file uploads of all kinds, but for some reason, each of these uploaded files, when downloaded became either a jpeg or gif.
Upon inspection, I saw that when the file is uploaded and stored in a BLOB column, the file type information is not stored along with it. Worse still, jpeg and gif file extensions were just about randomly appended on the download page. Yep, WTF.
My task was to modify the program so that each file download was appended with the right file extension according to its MIME type. This way, the user can use pre-installed viewer softwares to download and view the files e.g. using Adobe Acrobat when a PDF link is clicked. Deciding only to change the download page, with inline C# script blocks (no code-behind), I found a C# library (Winista.Mime) which determined MIME types by analyzing binary data. Sweet.
All I needed to do to start using this wonderful library was to download the project, build it and put the resulting dll in the bin folder of my ASP.NET application. Then, I referenced the library from my download ASPX with this import directive:
<%@ Import Namespace="Winista.Mime" %>
And, in the download portion of the code (which happens to be in the
Page_Load method), I added the right file extension to the Content-Disposition header:
...
Response.AddHeader("Content-Disposition",
"attachment; filename=file." + GetExtension(theBlob) + "; " +
"size=" + theBlob.Length.ToString());
...
You'll notice this piece of code makes a call to a method named
GetExtension(). This is the only place where the library is used. Here it is:
private bool GetExtension(byte[] data)
{
MimeTypes mimeTypes =
new MimeTypes(Request.MapPath("mime-types.xml"));
MimeType mimeType =
mimeTypes.GetMimeType(Winista.Mime.SupportUtil.ToSByteArray(data));
return mimeType.Extensions[0];
}
That's it, short and simple. I forgot to mention that the library stores patterns for each MIME type in an XML file called mime-types.xml, which you'll need to put into the same folder.
If you need to add a class library to your ASP.NET application quickly (no recompiling your ASP.NET application), you can follow the steps described above. If the library you're building targets a different version of .NET, just put it in a bin folder in a virtual directory that has been set to the appropriate version of .NET, and which is accessible from the current application. This also means you'll need to replace the current webpage with a new one residing in the target virtual directory.
Also, although not really related, I previously wrote about using client-side scripting to hack in file upload functionality for a closed-source ASP.NET application (another submodule in the software described in this post):
Using unobtrusive JavaScripts to extend an ASP.NET product
Bad way to extend an ASP.NET product - the details
Bad way to extend an ASP.NET product