UserScript: Showing Page Titles & URLs in Google Analytics

Often, when you're using Google Analytics, you want to be able to segment by the page's title, but there is no default way to do this with Google Analytics.

Well, a couple of hours ago I started catching up on my reading in Google Reader, and I noticed a blog post from LunaMetrics titled "Showing Page Titles & URLs in Google Analytics", and that post pointed out exactly how to segment by page title.

So, I took a couple of minutes and wrote a userscript to add this dimension to the 'segment by' drop down with a userscript so that you can easily segment by page title, without having to think about how to do this. Here's the code:

This userscript is available on userscripts.org as well, here: Google Analytics Page Title Segmentation

Enjoy!

The Principle of JavaScript Illumination

Every web developer knows that their site should work when the site's users disables JavaScript, but I constantly find this principal is violated when it is simple thing to obey. When web UI developers violate this principal it shows an extreme laziness and a failure to understand good practices on their part; this can greatly worsen the user experience. So, I'd like to articulate what I'm going to call The Principle of JavaScript Illumination which is an idea I haven't seen articulated yet, but that everyone knows in their gut they should do, and yet I hardly ever see this principal adhered to in practice.

Definition

The Principle of JavaScript Illumination is a simple one, if some user interface element will not work when JavaScript is disabled, then have JavaScript add the element.

Implications

If you have a user interface (UI) element that uses JavaScript, then make sure there is a default functionality that will work when JavaScript is disabled. If the UI element cannot work at all without JavaScript, then you should make JavaScript add the element, this way if JavaScript is disabled then the user will not see UI elements that will not work, causing a bad user experience.

Examples

Facebook Chat

When you log in to Facebook with JavaScript disabled, the chat widget is displayed to you on the bottom right of the screen, but it doesn't do anything, it's completely useless to you and it's just in the way, so why the heck is it displayed to the user?

Kampyle

Kampyle provides some widget code for anyone to put on their site which adds a "Give Feedback" button to the bottom right of the user's screen, which the user can click on to give feedback for the site. The trouble is, when JS is disabled, or when the user uses NoScript to block assets from the kampyle.com domain, then the button doesn't work (see ROIRevolution's site for an example of this), so why the heck is it displayed to the user?

Conclusion

Be a good web citizen, and a smart web developer by obeying The Principle of JavaScript Illumination, because it's the right thing to do and because you're users will thank you for it.

Using Web Workers Today

I did a little reading on Web Workers a few months ago, and I recently used them in a little test I was asked to perform, so I thought I would share what I've discovered since I don't see much in Google search results about how to use Web Workers in a cross browser fashion with graceful degradation.

Web Workers

For those of you that do not know what Web Workers are I suggest you read the Web Workers Draft Recommendation, but in brief they provide web developers with the ability to create thread-like operations.

This is obviously useful for long operations. The standard way of dealing with laborious tasks like these in the past was to split up the work with multiple setTimeout() calls.

setTimeout

Before Web Workers, setTimeout() had to be used to split up long operations in to multiple small operations, because you only had a single thread, so this had to be done in order to avoid having an unresponsive UI or triggering a unresponsive script warning.

Current Browser Support For Web Workers

Currently the latest versions of Firefox, Chrome, and Safari all support Web Workers; IE and Opera do not support Web Workers.

So how do you detect if a browser supports Web Workers programmatically? this is how:

if( Worker /*check for support*/ )
// Web Workers are supported
else
// Web Workers are not supported

Minor Note For Safari

While Safari supports Web Workers it requires that strings be used when passing messages, which is something that Firefox and Chrome do not require. Firefox and Chrome both stringify anything not already a string that is crossing the bridge to or from a Web Worker, but Safari does not do this, so you must. This is a simple thing to do, but one that you must remember, always use the JSON object to JSON.stringify when sending a message and JSON.parse when receiving a message (if web workers are supported, then so will the JSON object be).

Supporting Browsers That Do Not Support Web Workers

The biggest hurdle for most to implement Web Workers today is the fact that not all browsers support them, but the fact is that it is simple to degrade gracefully, thus allowing those users that are using browsers that support web workers to start reaping the rewards, and allowing you to improve your site and be prepared for when IE and Opera finally come around.

So what is the best way to handle the browsers that do not support Web Workers? well I see two options:

  1. Maintain a secondary script to be used when Web Workers cannot be, and add it to the page by creating a script element and appending it to the document.body.
  2. Make the Web Worker friendly to being used in a window scope instead of a Web Worker's scope so that it can be simply added to page like I describe in option 1.

Option 2 will be the better approach in most cases I suspect, because it means that two separate files with two slightly different methods of achieving the same task do not need to be maintained. In order to implement option 2 two there are some things to consider:

  • You cannot use functions like postMessage, onmessage, or importScripts while in the window scope.
  • You will need to split the work up with setTimeout (which is available in the Web Worker scope as well) to avoid an unresponsive UI and unresponsive script warnings.
  • You should assume that your Web Worker will be used in the window scope, so do not pollute your global scope.

There are a couple of ways to determine if you are not in a Web Worker's scope, as to avoid using the postMessage, onmessage, and importScripts functions (which are available to Web Workers) when your script is run in the window scope (postMessage has another purpose in the window scope). The first method is this:

if(typeof importScripts == "function") {
// web worker scope
}
else {
// not web worker scope, assume window scope
}

The other method is to check if you are in the window scope:

if(typeof window != "undefined") {
// window scope
}
else {
// not window scope, assume web worker scope
}

Or, combining the two methods above:

if(typeof window == "undefined" && typeof importScripts == "function") {
// web worker scope
}
else {
// another scope
}

These methods will allow us to avoid using postMessage, onmessage, or other methods we use while in the scope of a Web Worker.

To avoid polluting the global space normal tactics apply, I would simply suggest wrapping all of the code in an anonymous automatically executed function, like so:

(function(){
// this is an anonymous automatically executed function
})()

Putting these methods together, we would get web workers like so:

(function(){
var winScope = true;
if(typeof window == "undefined" && typeof importScripts == "function") {
// web worker scope
winScope = false;
}

if(!winScope) {
onmessage = function() {
postMessage("blah");
}
}
else {
alert("blah");
}
})()

Except that real Web Workers would do interesting things, and use setTimeout.

Goo.gl Now Open For General Use

Screen shot of Goo.gl fixed up with the userscript mentioned below

Three days ago Google announced it's release of Goo.gl a url shortener which is more reliable and trust worthy (to a user) than other services such as tinyurl.com, tr.im, bit.ly, etc.

Now I think all web publishers should maintain their own url shortener which only they can create urls for and control, for example I bought the domain evold.ca, and use the subdomain r.evold.ca as my url shortener. I primarily use this domain to shorten urls to my other domains, like erikvold.com, but I can and do occasionally use it to create short urls for domains that are not mine. As a user, when I see a blog post that I want to share, I first check if the publisher has published a short url for the page, which any smart web publisher does, but for the other web publishers (the majority atm) I have to create a short url, which I can now use Goo.gl to do.

The problem is that Goo.gl does not allow users to use it to shorten links directly. Currently, the Google URL Shortener is only officially available via the Google Toolbar and FeedBurner.

Well, I noticed that this problem was solved yesterday by a Google Chrome extension called goo.gl shortener. Amit Agarwal drew my attention to this extension in a blog post he wrote yesterday, where he pointed out the important javascript parts needed to create goo.gl short urls. So I took this information and opened Goo.gl up with a userscript, a ubiquity command, and a jetpack to help everyone create short urls with Goo.gl, check them out!

Click Tracking JavaScript Library Now Available

Purpose

To help web publishers easily track link clicks the correct way, across browser platforms, with tools like Google Analytics (GA) and Google Website Optimizer (GWO).

Typically a web publisher will want to do something like track all external links on a website with GA, setup a GWO test where the conversion is a click through, or do both on the same page for a few pages of their site. This javascript library was designed to make tasks such as these simple.

About

clickTrackingLib

Adding the click-tracking-lib.js or the click-tracking-lib-with-presets.js to a web page provides you with a clickTrackingLib javascript object. Once you provide clickTrackingLib with some match objects, you can then have clickTrackingLib scan a single, set, or all document links to determine if the link(s) should have tracking functions applied to it or not, and do so if needed. If one or more tracking functions are applied to a link, then a delay function will be applied to the link (this can be disabled too of course, and the delay can user defined but the default is 99 ms).

The Delay Function

The delay function is meant to delay the user from being redirected to a new page for just a bit to allow time for say a Google Analytics image request to complete, and avoid being canceled by the user's browser. It can be disabled, but it is added by with a 99 sec delay by default, which can be customized, as the very last onClick event listener, after all of the desired provided Match object trackingFunc's are applied.

The delay function technically only sets a timeout to redirect the user after x ms, but in order for the delay to work the link's default functionality, namely redirecting the user, needs to be disabled, if the link doesn't just open in a new tab (target="_blank" and target="_new" are checked for). To disable the default functionality the link's onclick attribute must be set to onclick="return false;" which I figured should be fine because all well made websites won't use that attribute except to make it equal to "return false;" anyhow. If your site is not well made, then you should think about fixing it or having it fixed for you, but you can still use this library by simply not using the delay function and implementing it by some other means.

Presets

There are a number of presets available if you use click-tracking-lib-with-presets.js or click-tracking-presets.js; presets are predefined match functions for common use cases, such as matching all internal links, or external links, or download links. They can be used as they written, you could cut out the ones you won't use, or simply use them as examples when you define your own custom match objects.

The can be accessed from the clickTrackingLib.getMatchPreset( name ) method. The possible name values and the meanings behind them are as follows:

  • 'rel-external': matches rel-external links
  • 'external-hostname': matches external hostname links
  • 'all-external': matches all rel-external and external hostname links
  • 'filetypes': matches file names: (docx*|xlsx*|pptx*|exe|zip|pdf|xpi|rar|xls)
  • 'non-rel-external': matches non-rel-external links
  • 'internal-hostname': matches internal hostname links
  • 'all-internal': matches non-rel-external links or internal hostname links

Match Objects

Any object that has a 'match(link):boolean' method and 'trackingFunc(event,link):void' method defined.

match(link):boolean

This method will take a link element as input, run some test on it and return true or false, if true is returned then the Match object's trackingFunc will be added to the link.

trackingFunc(event,link):void

This method will be provided with two input values; event is the click event object, and link is a reference to the link element. You can obtain a reference to this from the event object, but there is some cross browser logic you would need to implement, so I thought a direct reference to the link would be handy. The function should not return anything.

new clickTrackingLib._clickTrackingLib();

If you want to create multiple clickTrackingLib objects, that contain different sets of match object arrays, then you need to create a new one, like so:

var myNewClickTrackingObj = new clickTrackingLib._clickTrackingLib();

This will give you a new object, myNewClickTrackingObj, which is like clickTrackingLib in all but two ways. First myNewClickTrackingObj will not have a _clickTrackingLib() method, and second it will not have a getMatchPreset() method, even if clickTrackingLib.getMatchPreset() was defined. This is because you don't need a bunch of objects in memory with those two methods, only one, which is the singleton clickTrackingLib object.

How To Use

  1. Download either click-tracking-lib-with-presets.js or click-tracking-lib.js (see ABOUT fore more information) from the project repository at GitHub.
  2. Minify it with one of the following options:
  3. Upload the minified script to your site.
  4. Add <script src=".." type="text/javascript"></script> for the script to the desired pages.
  5. Write some code:
    • define some match objects (just an object with a match method and trackingFunc method)
    • Add match objects to your clickTrackingLib object
    • Call the clickTrackingLib.attachTrackingFunctions( links, delay ) when desired.
      • links: can be a single anchor element, an array of anchor elements, or falsely so that the default is used, which is document.links.
      • delay: should be a positive integer or falsey, in the latter case no delay function will be added to the links scanned, in the former case a delay function will be applied with the specified delay value.

[More]

Would You Like To Know More?

This is just a last moment idea inspired by the movie Starship Troopers which flashed in to my mind a couple of days ago as I was thinking about Jetpacks for the Jetpack for Learning Design Challenge. It is primarily a Microformat/Link Type proposal for rel-info with some ideas and prototypes demonstrating how it could be used.

Abstract

When you are reading something on the web there are usually pages which exist elsewhere on the web that would provide background information, and further reading if you desired to dig deeper into the subject(s) you are reading about. Sometimes some of those pages are linked to from the article you are on, but often the link wouldn't make sense in the context of the content, and using a link tag isn't very useful to a user, so the link is not made.

I propose a rel-info link type, even if just as a Microformat, for 'a' and 'link' tags to provide a link to context-sensitive information.

With rel-info a user can read more about the Movie that was discussed at Netflix or IMDB easily for example, because the publisher (or a script the user subscribes to, more on this later) provided a rel-info link which the user can easily find and follow with a Jetpack, Firefox extension, or some other browser extension.

Proposal

When rel-info links are provided on a page browser extensions can easily extract them from the page, which can lead to a large number of use cases, of which I am sure I have only just scratched the surface. There is another side to this coin however which is that there are a large number of ways that rel-info links might be added to a page.

Let's explore the latter case, first the person who published the page could add rel-info links, but then browser extensions could add rel-info links, they could also search for and remove rel-info links. A user could subscribe to a person's or institution's suggestion feed or script which adds and/or removes rel-info links to pages, along with using a AI based browser extensions to add rel-info links.

When the rel-info links are going to be consumed there are some other interesting possibilities, for example a browser extension could filter the links by a HTML 5 'data-topic' attribute by keeping a list of topics that the user dislikes or likes, the domain could also be used for filtering. A browser extension could allow the user to mark pages as read so that they are removed from pages in the future as another example.

Prototypes

To test this link type out with a Jetpack I first had to add it to some pages, so I decided to write a couple of UserScripts to do this demonstrating how they can be dynamically added to pages by anyone even users themselves. The first userscript was to add the rel-info link type to IMDB links, and another to add the rel-info link type to Wikipedia links.

If you install the above UserScripts then you should find rel="info" or rel="... info" on your IMDB and Wikipedia links. Once you have done that you can check out and install the "Would You Like To Know More?" Jetpack. This is a slidebar Jetpack, and when you open this slidebar the focused tab is then scanned for rel-info links, if any are found then they are displayed in a list for you to choose from, if you click one of the provided links a new tab will be opened for the new page.

These UserScripts and the Jetpack take advantage of HTML 5 'data-' attributes, by adding a 'data-source' attribute to the rel-info links added on the userscript side, which the jetpack was written to check for and display if found. This is an example of how HTML 5 'data-' attributes can be used with the rel-info link type which I propose to create more interesting results.

The Daily UserScript: Google Images Smush It Link

Today's userscript adds "Smush It!" links to Google Images results, which makes use of the Yahoo! YSlow Smush.it web service.

The Unpleasantry:

When I'm searching through images on Google Images and I find something that I want to use, I naturally want to smush it using Yahoo! YSlow Smush.it, but to do that I have first get the url of the image, then go to Smush.it, paste the image url and hit the "Smush" button.

The Alleviation:

Once you install the "Google Images Smush It Link" UserScript there will be a link added to each image result which will enable you to quickly smush the image.

Screen Shots:


Before: Google Image search result before installing the Google Images Smush It Link userscript.

After: Google Image search result after installing the Google Images Smush It Link userscript.

After: Google Image search result after clicking the provided 'Smush It!' link.

Greasemonkey Tip: Simulating a click on a DOM element without the click() method

While I was working on today's userscript for Google Reader I had to clone a node, and when I did that the mouse events were not part of the clone, so the clone wasn't really a clone..

I thought about it for a moment and decided to simulate a click of the original node when the clone was clicked, but the problem was that I had relied on libraries for this in the past, which is a good idea in general, but I didn't want to add code that is meant for other browsers to my userscript. So I did some searching, and didn't find any results that helped me at all after > 1 hours. So after I had it with searching, I took a look at the jQuery code, and got lost, then switched to the YUI 3 Event library code and found my answer. So I thought I would put it on the web for the next guy.

Simulating a click:

[More]

Greasemonkey Command With Input String For Ubiquity 0.5

I have been working hard on this for the last week, trying to get a better version out by getting an update I did for Greasemonkey into the trunk (this will take a lot of time, and will be an improvement), but I am now pleased to release a version of the Greasemonkey Ubiquity Command (ready for Ubiquity 0.5) which will accept an input string.

What is it?

It is a Ubiquity command which allows you find and execute Greasemonkey menu commands.

How do you get it?

  1. Get Ubiquity 0.5 or greater.
  2. Get Greasemonkey.
  3. Get the Greasemonkey Ubiquity Command.
  4. Get a UserScript with a menu command, and that is it!

[More]

Short URL Discovery Using Google App Engine

URL Shorteners and Link Rot

Short urls have numerous benefits I won't go through here, one example is for use in twitter which has a string length limit of 140 characters, another example is shortening urls with Google Analytics campaign tracking url variables.

The problem with all of the third party url shortening services out there is that eventually they will have to reset old urls in order to continue providing "short" urls, and even if they don't they could at any time stop providing service, in either case any link using the short url will be dead. Dead links are something all webmasters and users dislike.

The best way to defend against link rot is to create your own personal url shorting service for your own use, on a domain that you control. An added benefit to this approach for Google Analytics campaign tracking is that you will have the control to change the variable values in your campaign links even after the links have been used, like in an email campaign that wasn't setup properly for example.

Google App Engine (GAE)

Google App Engine is another one of those fantasic services which Google provides, this one however is meant to give developers the ability to write their own apps to use the Google infrastructure. GAE provides two programming language choices: Java and Python. Python was the first choice available and recently Java became a option.

I knew about the Google App Engine for a while now, but did not get started writing apps until I saw this RevCanonical project by Kellan who provided the source . After I saw Kellan's source, I noticed that it did not check the HTTP Headers for Links, which was a proposed technique which can potentially save a lot of bandwidth. Also, because I was interested in learning Python, GAE, and Git, I decided to created a copy of the Git repository, and run the code on one of my own Google App Engine spaces, and I learned how to do this by reading the Google App Engine Python tutorial. After I got Kellan's code running, I dug into the Python tutorial (which was an excellent read), and started hacking away the code.

Get Short URL

Well after modifying the RevCanonical project's source code I had made Get Short URL. Get Short URL will scan HTTP and HTML header links for a url which is sigalled as an alternative for the given url, this can be signaled a few different ways which I list at http://getshorturl.appspot.com

I must thank Kellan too, because I learned a lot from his source, and it got me started learning Python, and once I figure out Git I will create a patch for his project.

More Entries

© Erik Vold 2007-2010. Contact Erik Vold. Top ^