Posts Tagged ajax

Tracking AJAX in ASP.NET with Google Analytics

Google analytics for recruitment
Image by carveconsulting via Flickr

(skip down a little further if you don’t need an introduction to Google Analytics.)

I love Google Analytics. In fact, I’m a big fan of Google as a whole, and I do the majority of my work using Google Docs, Calendar, and Gmail (online collaboration! oh, and free) and Google Analytics is a beautiful tool for businesses, whether their website’s primary focus is online sales or just a small info-about-my-business site. If you don’t have some kind of tracking, you’re missing out on very important information; GA is a good place to start. Anybody can put GA into their website, and everybody should put something in.

The way GA works is by dropping a snippet of Javascript into your page; this javascript runs a series of tests against the visitor’s browser, checking screen resolution, flash capabilities, seeing if the user is unique, watching the user’s path through the website, checking the user’s location, and much, much more (all collected anonymously). This is all put into an interface where you can see the data collected and organized. However, AJAX applications don’t function as normal websites- you don’t get a new page hit every time you fire off an UpdatePanel, because it’s not a full page refresh. So, we need to do a little trickery to get things to work the way we want them to.

(you can start reading again if you skipped earlier.)

If you have the Google Analytics in the host page (whether the aspx page, or more likely, the master page), then you have to register a client script block that calls the trackpageview method. If you use jQuery, it’ll look something like:

ScriptManager.RegisterClientScriptBlock(UpdatePanelID, typeof(UpdatePanel), "uniqueIdentifierString", "$(document).ready(function(){ pageTracker._trackPageview('/pagename'); });", true);

If you’re not using jQuery, you’ll have to do a little more work to attach to the window’s onload event, but it’s pretty similar.
What you’re doing is registering a script block to execute when the UpdatePanel updates (because it won’t execute JS returned in the text), and using the pageTracker object (that the GA code you copied when you first set up GA on your site created) to force a pageview for a page you define. For my applications, I generally use something like “/dataentry/guestbook/edit” or “/dataentry/guestbook/delete” so that I can easily track guestbook views, as well as edits / deletes. It’s both a way to track controls you load via AJAX, and a cheap shot at logging (not perfect data, though, so you’re still best off doing all of your own logging on events, of course.)

The official Google help doc on the subject is also here: http://www.google.com/support/analytics/bin/answer.py?hl=en&answer=55519

Reblog this post [with Zemanta]

Tags: , , , , ,

Javascript Prototyping, an Adventure

Lately, I’ve more or less been the go-to guy at work for Javascript issues. Several times daily, I’ve been helping other people out with Javascript (something I like to do; keeps me sharpened on the art of browser scripting), whether it be an issue with Ajax or something strange with variable initialization (check that your variable’s not a keyword! make sure the src is set correctly!). So there I was, thinking myself somewhat of an expert on the subject, as my ego has a habit to coerce me into, until I came upon the Javascript “prototype”. Not to be confused with the popular Javasript framework, but rather a method to add methods to objects. Essentially, it is a plausible way to extend current objects and really use Javascript as an object-oriented language. And what with my affinity towards C#, this was perfect.

I decided that I’d first start with my Ajax framework, DeviantAjax. The framework was something I started a while back, beginning with Gevalum’s rudimentary system; I took the few base functions and threw them nicely in a file with comments. However, this wasn’t exactly anything new or groundbreaking; I wanted to put out a framework that was simple and easy (KISS), but still offered more than any wizened developer could throw together in a matter of minutes.

DA, as we’ll call it from here on out, would be different than the other frameworks (the three that come to mind are script.aculo.us, Prototype, and jQuery). It wouldn’t include all of the animation stuff and all the extra DOM code of the others; rather, it’d be for Ajax alone. It’d be a way for beginners to use the magic and a way for gurus to get a head start on a project.

So, first things first: I began with a Page object. Pleased with this, I began to add things into it’s prototype, like so:

function Page() {
    ajaxes = new Array();
}

Page.prototype = {
    SetAjaxRequestMax: function(ajaxObjectsToCreate){
        …
    },
    FillElement: function (element,source,postData,ajaxObjectIndex){
        …
    }
}

Excellent! I could make a new page – var MyPage = new Page(); – and it looked like good ol’ C# (well, close enough, anyway.) I could even call MyPage.SetAjaxRequestMax(4)! And that was great, except now I wanted to add functions to FillElement. So, I added a FillElement.prototype block inside of my FillElement, with functions like Set, OnLoad, OnRequestOK, and OnRequestBad. Except… prototype doesn’t quite work like that. You can’t put the prototype declaration inside the FillElement function, as I found out after several hours.

So, instead, the framework began to look more like:

_ajaxObjectArray = new Array();

function Page() {
   
}

function EvalAjaxPost(){};
function SetAjaxRequestMax(){};

SetAjaxRequestMax.prototype = {
    Set: function(ajaxObjectsToCreate){
        if(window.XMLHttpRequest){
            for(x=0; x<ajaxObjectsToCreate; x++){
                _ajaxObjectArray[x] = new XMLHttpRequest();
            }
        }else if(window.ActiveXObject){
            for(x=0; x<ajaxObjectsToCreate; x++){
                _ajaxObjectArray[x] = new ActiveXObject(“Microsoft.XMLHTTP”);
            }
        }
    }
};

FillElement.prototype = {
    Post: function(element,source,postData,ajaxObjectIndex){
        …
    },
    …
}

Page.prototype.SetAjaxRequestMax = new SetAjaxRequestMax();
Page.prototype.FillElement = new FillElement();

Now it started working better. I’d set the AjaxRequestMax on the HTML file it was used in, and then I could initialize and use FillElement objects- FillElement.Post(“div1″,…);. Cool.

So, the purpose of prototype, and how it works:
Prototype is a way to add methods onto objects. For example, you could add functions onto strings, like so:

function Reverse(){
    for (n=this.length-1;n>=0;n–){
        document.write(this.charAt(n))
    }
}
String.prototype.writeback=Reverse();

And use it like “jack”.Reverse(); and get a result. It’s Monkeypatching at it’s best. It also really lends itself to OO Javascript development, which is always a plus.

The next thing I’m trying to figure out is how to get other functions in the prototype (OnRequestOK, for example) to run on the FillElement object when I run Post and get a certain result. Feel free to leave any ideas in the comments, and otherwise I’ll be posting part 2 soon.

Check out my testing page (which may or may not be broken, if I’m working on it) and the zip file for yourself; it’s creative commons licensing, so do whatever you want.

Tags: , ,

n-Tiered AJAX

n-Tiered AJAX is one of my my
favorite development architectures. It’s how I developed Gevalum, and
it’s how I’ll develop every website to come that has to touch a
database, but doesn’t require a full-scale ASP.NET application
platform. It’s fast, it’s scalable, and in the end, you’ve got one
sweet site with amazing processing efficiency and pizazz. It’s a pretty simple idea. This is how I develop:

First
off: make a mockup of the design. Figure out what you want it to look
like; draw it up in Photoshop, or write up the CSS in notepad, or
however you’re doing what you do. Make a note of every bit of static
information, and every bit of dynamic information, and dump it all into
DIV tags.

Next, after the interface tier, comes the big part:
your JavaScript tier. There are three distinct parts to this, although
you may only require two.

Part 1: your object layer. If you have
things like I do (players, items, etc) you’ll want to make objects. An
example would be a player object, with player.strength, player.health,
player.level, player.name… etc. A variable for every bit of connected
information on your page.

Part 2: your update layer. Make a
library of functions for each bit of information that you update. Don’t
directly call the AJAX here; update the objects you made, or use these
as a wrapper to validate then call your AJAX functions. You’ll probably
want to include some DOM functions like:

function $(div){
return document.getElementById(div);
}

and interface updater functions like:

function updateStats(){
$(“playerStr”).innerHTML = player.str;
//etc for all other stats
}

and variable updater functions like:

function uSTR(newStr){
player.str = newStr
}
and
anything else that your page does. Try to keep everything seperated; at
a minimum, I always have a dom.js, functions.js, and then finally
AJAX.js. You’ll call your AJAX layer by using something like this:

function uSTR(){
player.str = evalAJAXPost(“playerstats.php?stat=str”);
}

Part
3: Your AJAX layer. These are the functions that use your server-side
pages. You always want to separate these because they’re things you use
over, and over, and over again. Another trick that I learned a while
ago, is that if you have simultaneous updates (e.g. sending dynamic
updates while requesting pages), make an array of AJAX objects, and
pass each page request through a different object. I’ve found that
there’s no need for more than two or three (even Gevalum only has
seven, and that’s probably overkill.) This is an excerpt from Gevalum’s
AJAXFun.js:

var ajaxes = new Array();
//if we’re FF
if(window.XMLHttpRequest){
ajaxes[0] = new XMLHttpRequest();
ajaxes[1] = new XMLHttpRequest();
ajaxes[2] = new XMLHttpRequest();
ajaxes[3] = new XMLHttpRequest();
ajaxes[4] = new XMLHttpRequest();
ajaxes[5] = new XMLHttpRequest();
ajaxes[6] = new XMLHttpRequest();
//or, if we’re IE
}else if(window.ActiveXObject){
ajaxes[0] = new ActiveXObject(“Microsoft.XMLHTTP”);
ajaxes[1] = new ActiveXObject(“Microsoft.XMLHTTP”);
ajaxes[2] = new ActiveXObject(“Microsoft.XMLHTTP”);
ajaxes[3] = new ActiveXObject(“Microsoft.XMLHTTP”);
ajaxes[4] = new ActiveXObject(“Microsoft.XMLHTTP”);
ajaxes[5] = new ActiveXObject(“Microsoft.XMLHTTP”);
ajaxes[6] = new ActiveXObject(“Microsoft.XMLHTTP”);
}

function evalAJAXHtml(source,nr){
ajaxes[nr].open(“GET”,source,true);
ajaxes[nr].onreadystatechange = function(){
try{
if(ajaxes[nr].readyState==4){
if (ajaxes[nr].status == 200){
eval(ajaxes[nr].responseText);
}
}
}
catch(e){
//Exception-bug in FF
}
}
ajaxes[nr].send(null);
}

function evalpostAJAXHtml(source,datan,nr){
ajaxes[nr].open(“POST”,source,true);
ajaxes[nr].setRequestHeader(“Content-type”, “application/x-www-form-urlencoded”);
ajaxes[nr].setRequestHeader(“Content-length”, datan.length);
ajaxes[nr].setRequestHeader(“Connection”, “close”);
ajaxes[nr].onreadystatechange = function(){
try{
if(ajaxes[nr].readyState==4){
if (ajaxes[nr].status == 200){
eval(ajaxes[nr].responseText);
}
}
}
catch(e){
//Exception-bug in FF
}
}
ajaxes[nr].send(datan);
}

Now,
for the server-side part of this AJAX tiered application. There are a
thousand ways to do this, depending on personal taste; I choose PHP,
since it’s lightweight. You could use ruby, or asp, or asp.net, or
anything that outputs text. All I have to do is pull the information I
need, and write out my JavaScript updater function, and I’m done.

You
may be asking: why bother? Well, the easiest is that it’s the absolute
fastest way to get information securely from a database to the client.
It sends the minimum information possible, and so saves you bandwidth.
It’s invaluable for a little hosted server, or if you’re hosting
yourself and can’t afford a business-class internet line. Not to
mention, it’s faster on the user’s end, so they wait less, making them
less likely to turn away from some lag-o-licious old monolith of a
website. It’s streamlined, it’s dynamic; what else could you ask for?

Tags: , , , ,