Pineapple Orange

Archive for June 2009

How WordPress Tracks Visitor Clicks

leave a comment »

Most websites that want to track links do so by redirecting it through another page. For instance a link to http://www.example.com would become http://www.mywebsite.com/?redirect=http://www.example.com. The redirect page would record the target and send the user to that page. The problem with such methods is that it becomes more difficult for visitors to determine where the link will take them, since the URL looks like it is going to another page on the same website.

JavaScript to the Rescue

Instead of redirecting links, WordPress loads some JavaScript that tracks all clicks that are made on the page. Here is the function that is first called to start monitoring clicks.

function linktracker_init(b, p) {
    _blog = b;
    _post = p;
    _host = document.location.host ? document.location.host: document.location.toString().replace(/^[^\/]*\/+([^\/]*)(\/.*)?/, '$1');
    if (document.body) {
        document.body.onclick = clicktrack;
        document.body.oncontextmenu = contexttrack;
    } else if (document) {
        document.onclick = clicktrack;
        document.oncontextmenu = contexttrack;
    } else {}
}

It initializes the variables about the current page and sets the functions clicktrack and contexttrack to be called for the events onclick (left click) and contextmenu (right click). It needs to check if document.body exists or if document exists because of the differences between browsers.

Receiving Events

function clicktrack(e) {
    var t;
    if (e) {
        t = e.target;
    } else {
        t = window.event.srcElement;
    }
    linktrack(t, 500);
}

function contexttrack(e) {
    var t;
    if (e) {
        t = e.target;
    } else {
        t = window.event.srcElement;
    }
    linktrack(t, 0);
}

The functions check if e (the event) exists, otherwise it uses window.event. The is also due to the different ways browsers handle events. Both these functions are identical, except for the second parameter that is passed to linktrack. We’ll see what this parameter does later. The first parameter to linktrack is the element that triggered the click event.

The Pièce de résistance

Yes, I do like using fancy French words.

function linktrack(a, d) {
    try {
        if (!a || a == null) return;
        while (a.nodeName != "A") {
            if (typeof a.parentNode == 'undefined') return;
            a = a.parentNode;
            if (!a) return;
        }
        b = a;
        while (b.nodeName != "BODY") {
            if (typeof a.parentNode == 'undefined') return;
            b = b.parentNode;
            if (b.id == 'wpcombar') return;
        }
        if (a.href.match(eval('/^(http(s)?:\\/\\/)?' + _host + '/'))) return;
        if (a.href.match(eval('/^javascript/'))) return;
        var bh = a.href;
        var pr = document.location.protocol || 'http:';
        var r = (typeof a.rel != 'undefined') ? escape(a.rel) : '0';
        var b = (typeof _blog != 'undefined') ? _blog: '0';
        var p = (typeof _post != 'undefined') ? _post: '0';
        //var x=document.createElement('IMG');
        var src = pr + '//stats.wordpress.com/c.gif?b=' + b + '&p=' + p + '&r=' + r + '&u=' + escape(bh) + "&rand=" + Math.random();
        if (a.className.match('flaptor')) {
            var fx = function(c) {
                return c.replace(/flaptor\s*/, '')
            };
            var f = 'b' + _blog + 'p' + _post + ' ' + fx(a.className);
            var links = document.getElementsByTagName('A');
            for (i = 0; i < links.length; i++) {
                if (links&#91;i&#93;.className.match('flaptor')) f = f + ' ' + fx(links&#91;i&#93;.className);
            }
            src = src + '&f=' + f;
        }
        if (typeof _acseed != 'undefined') src += '&ac=' + _acseed;
        var x = new Image(1, 1);
        x.src = src;
        if (d) {
            var now = new Date();
            var end = now.getTime() + d;
            while (true) {
                now = new Date();
                if (now.getTime() > end) {
                    break
                }
            }
        }
    } catch(e) {}
}

The linktrack function is where all the magic happens. The first while loop checks if the current element is the A element that contains our URL, if not it keeps checking its parent until it finds it or fails. This is required because of the way JavaScript handles events. For every event, JavaScript goes to the lowest level element and checks if the event triggers anything for that element. It then continues to bubble its way up each level until it is done. Since WordPress is getting all clicks on the page instead of clicks for a single item, it will always get the lowest level element and must manually work its way up to the link element.

The second loop does the same to find the BODY element that contains the A element we found. If the id is “wpcombar” (the WordPress Admin bar), then it stops.

Next it checks that the link is for another website. If it is a link to another part of the blog, or contains JavaScript, then it won’t report it.

The next few lines of code build the URL to send the tracking information to. In addition, it removes “flaptor” class from the current link for some unrelated purpose. I’m not sure what it does exactly, but it could be used to flag a link so it doesn’t report it, if it is clicked more that once.

Afterwards, it creates a new Image object and sets the source to the URL we send the tracking information to. If you look at the variable src, you can see that it loads “c.gif” and one of the parameters “escape(bh)” is the link we need to track. The image is loaded in the background, unknown to the user. It does not matter what the image is, only the request needs to be sent in order to record the transaction.

Finally, it uses the second parameter of linktrack to specify the amount of time it needs to run in a loop. If the function was called from contexttrack (right click), then the parameter is 0 and it does not need wait at all. If the function was called from clicktrack (left click), then it must run for at least 500 milliseconds so that the request for the Image can get through before going to the new page.

Conclusion

There are a variety of ways to track visitors, and each has its advantages and disadvantages. The disadvantage of using JavaScript is that it uses more bandwidth to load the file and some users have JavaScript disabled. However, it increases usability and tracks clicks in a transparent manner.

Written by Awesome Monkey

June 19, 2009 at 11:51 am

Google Chrome Extension – Google Reader!

leave a comment »

Hey guys,

I had some free time yesterday night, so I thought I’d write an extension for the Google Chrome browser, and maybe learn a bit of JavaScript on the way. One of the coolest Google features I recently discovered was Google Reader, and so I though why not write an extension that’ll tell me exactly how many unread posts I have in Google Reader? This way I wouldn’t have to constantly check for updates and whatnot… so check it out and tell me what you think. Here’s what it looks like:

Google Reader Extension

Google Reader Extension

Installation Instructions

Download the extension: http://drop.io/pineappleorange/asset/google-reader-crx

To install an extension in Google Chrome, you must first have the developer build of Google Chrome. The stable release currently does not support extensions.

To get the developer build, check here: http://dev.chromium.org/getting-involved/dev-channel.

Now once you’ve updated to the developer build, you need to let Chrome know that it can start using extensions. To do this, find your Google Chrome shortcut icon, and right click -> properties. In the ‘ Target ‘ field, append to the end of what’s already there the following: ” –enable-extensions”.

Finally, double click the installer, and enjoy!

If you wish to uninstall, type in “chrome:\\extensions” in your browser’s URL window, and click uninstall.

Let me know what you think! I’m now also trying to make some more extensions, so if you have any suggestions, let me know.

Written by Skyd

June 18, 2009 at 1:14 pm

Getting Past the “activation server is temporarily unavailable” iPhone Update Error

with 9 comments

Due to the large number of people trying to update at once, it seems the iPhone activation server is not responding. Here is a simple workaround to fix this issue.

Alternative 1:

From mozcheez in the comments:

disconnect from the internet as the (already downloaded) update is extracting, before it tries to connect to the activation server.

Alternative 2:

  1. Download the update through iTunes.
  2. Exit out of iTunes.
  3. Unplug the USB cable for the iPhone and plug it back it. (Edit: I’ve been getting reports that you need to turn the phone off after unplugging the cable.)
  4. If iTunes does not automatically open, then start it.
  5. You should see a dialog asking if you want to install. Click the “Install” button.
  6. It should get past the activation step and complete the update.

Note that after the update is complete it checks the activation a second time. It worked for me, but there have been reports of errors happening. In most cases, after waiting for a few minutes the phone activated by itself. An unactivated phone can only make emergency calls. If you do not want to risk this, wait a few days until the server is steady.

This is the final result, if everything works correctly:

iPhone Activated Dialog

iPhone Activated Dialog

Written by Awesome Monkey

June 17, 2009 at 4:14 pm

Posted in Apple

Tagged with , , ,

5 Common Mistakes of Using a Version Control System

leave a comment »

For any large or medium sized projects, a version control system is a necessity to properly manage code. Using one results in a large boost in productivity, by allowing multiple developers to edit the same code base. However, in order to be effective, a version control system must be used correctly. The following mistakes results in decreased productivity, and lower quality code.

1. Checking in Changes Without a Summary

The only reason this occurs is due to pure laziness. Without adding a comment with your submission, other developers have no indication to the purpose of your submission, forcing them to check if it’s safe to update or if they need to adapt their code. In addition, a summary makes it easier to identify a revision, if there is ever a need to roll back to it. A few sentences for each check in prevents wasted time by other members of your team.

2. Checking in Big Changes with a Single Submission

This mostly concerns changes that affect large number of existing files. However, it can also apply to the addition of numerous files in a single submission. Although this cannot always be avoided, it is better to have incremental changes. Incremental changes make it easier to identify which update or file may be causing an elusive bug.

3. Using Version Control for Peer Review

Like #2, there are special times where it is necessary to do this, but for most circumstances submitting code for peer review results in repeated submissions and lower quality code. By having peer reviews before the code is checked in, there is a decline in revisions, and the code base contains fewer bugs.

4. Not Verifying Submissions

One of the biggest hassles I’ve experienced came from a submission that did not merge files correctly. Most of the team had already updated to the latest code, only to find out it created errors when running the application. Although it was fixed by pulling back to a previous version and manually merging the files, many hours were wasted by not having a working application. Similar issues include forgetting to check in a file, or checking in the wrong file. This type of problem can easily be avoided by synchronizing with the repository after each submission and making sure the code compiles and runs properly.

5. Not synchronizing with the repository in a timely matter

Another effect of laziness is that developers will not stay up-to-date with the latest release in the repository. While its fine to delay synchronization for a week or two (assuming an average of ten releases a week), postponing an update for a long amount of time increases the likelihood that complications will occur. Errors such as merge conflicts, and bugs from incompatible code will start to appear. By updating in a timely fashion, most of these problems will disappear.

By following these simple guidelines, a version control system can be used to its full potential, resulting in faster development and higher quality code.

Written by Awesome Monkey

June 17, 2009 at 12:59 pm

Posted in Software

Tagged with ,