Making All Internal Link Clicks a Conversion

A common use case of Google Website Optimizer (GWO) is to test (in order to optimize) a page's ability to have a user click an internal link, I like to call this the internal pass thru rate of a page. Meaning the click event of any internal link on a test page will count as a conversion for the test. This is not the opposite of the bounce rate which it is sometimes mistaken for, because the pass thru rate is oblivious to the difference between first time visits and other visits. The pass thru rate is not the same as the click thru rate either, because the pass thru rate relates to visits and the click thru rate relates to impressions. This is usually desired either because you have no other conversion to track -- although time on page is always another option, but the results typically take longer to acquire -- or because you wish to optimize the bounce rate, and this is as close as you can get at the moment.

Google doesn't have any documentation on how to track all internal links on a page, but they do provide a page on how to track an individual link, which any novice JavaScript programmer can follow in order to track all of the internal links, by simply repeating the process for every internal link on the test page(s). The main problem here is that Google's process requires that the onclick attribute of every link be set to "return false", albeit this can be done via JavaScript, it is not desirable. Google Website Optimizer's Technical Lead Engineer, Eric Vasilik, explained Google's method in a blog post from August 2009, called "Tracking Outbound Links -- The Right Way", and I wrote a follow up post in December 2009, called "Tracking Outbound Links - The Really Right Way" in which I describe a better method which is slightly harder to implement but does not require any use of the onclick attribute.

If you are at least a novice JavaScript programmer that wants to measure the pass thru rate of a page, then you can probably implement Google's method or mine with relative ease after reading the blog posts I mentioned.

If you are not a novice JavaScript programmer, or simply want to save some time implementing this type of conversion over and over again, then I would suggest you take a look at the JavaScript click track library that I released in early December '09, because with this javascript library you could simply add the following code to your page:

clickTrackingLib.addMatches([{
match: clickTrackingLib.getMatchPreset( "all-internal" ),
trackingFunc: function(e, link){
var gwoTracker=_gat._getTracker("UA-XXXXXXX-X");
gwoTracker._trackPageview("/YYYYYYYYYY/goal");
}
}]);
clickTrackingLib.attachTrackingFunctions(null,99);

The above code will tag all non-rel-external links or links with the internal hostname on the page; for just internal hostname links replace "all-internal" with "internal-hostname". I would recommend that you wrap the above into a function though, to be run on the DOM ready event or page loaded event, with jQuery that would look like:

$(document).ready(function(){
clickTrackingLib.addMatches([{
match: clickTrackingLib.getMatchPreset( "all-internal" ),
trackingFunc: function(e, link){
var gwoTracker=_gat._getTracker("UA-XXXXXXX-X");
gwoTracker._trackPageview("/YYYYYYYYYY/goal");
}
}]);
clickTrackingLib.attachTrackingFunctions(null,99);
});

The first line in the code above will setup a function to be executed when the DOM is ready, and all of the page's links have been added. The second line is the first of the function the be executed on DOM ready, and it is adding an array of match objects to the global clickTrackingLib object provided by the click tracking library that I wrote. The following 5 lines define a single match object for the input array, which consists of a preset match function to match internal links (as I said already this preset can be changed, and you can also define a custom match function), and a simple tracking function. When clickTrackingLib.attachTrackingFunctions(null,99); is executed, links are tested against the match functions in the clickTrackingLib object's match object array, and where there is a match the associated trackingFunc function is made in to a onclick event listener for the matched link. As for the two inputs, the null means try all links, and the 99 means use a 99 millisecond delay.

At this point you might be wondering, what if the page has dynamic content, which is changed via ajax, well in that case you can round up the new link(s) in to an array and run the clickTrackingLib.attachTrackingFunctions(links, delay) function again like so:

clickTrackingLib.attachTrackingFunctions(newLinksArray,99);

clickTrackingLib.attachTrackingFunctions(links, delay) will also accept a single link.

Greasemonkey Optimization: Convert2RegExp

Over the last week I've been spending a great deal of time looking over the Greasemonkey and Webmonkey source code, both because I want to understand both code bases more, but also because I'm interested in Firefox extension internals in general. While looking through these two code bases I saw a common file which could be optimized. This file was the convert2RegExp.js file, which looks like it came from Adblock at some point, at least in part. In fact I saw a number of changes that I could try in order to speed up the function, so I decided to time them all.

Test Factors

Factor I: Check for /\.[^\.ld]*t[^\.td]*l[^\.lt]*d/ in pattern string character loop

The first thing I noticed was that the regular expression that checks the pattern string for a ".tld" string was being run on every pattern input, this seemed obviously bad to me since there was a loop prior to the regular expression which runs through the pattern string's characters, so why didn't that loop at least check for the ".tld" substring first? the check could be as simple as making sure all of the required letters exist in the string first, or make sure that the ".tld" substring, exactly, is in the pattern string, or what I found to be the best way was to make sure the regular expression /\.[^\.ld]*t[^\.td]*l[^\.lt]*d/ matched the pattern string via the character loop through the pattern string. The average cases and best cases will go much faster despite the fact that the latter case would be matching some pattern strings that following tld regular expression (that is already in convert2regexp) would not match, thus just adding work in this case, and making the worst possible case even slower.

Factor II: Cache tldStr and tldRegExp

The convert2RegExp( pattern ) function creates the tldRegExp and tldStr from literals on every execution! that might be a faster operation I thought, but I expected it to be slower than simply looking up the value of a variable when I timed it, and even though I haven't figured out how to test the memory consumption yet, I expect creating a large string from a string literal over and over again would increase the peak memory usage, and thus the garbage collector pause time as well. So, caching the tldStr and tldRegExp seemed like it would be a small win.

Factor III: Use array.push()/array.unshift() and array.join() instead of +=

From what I've read about Firefox 3.6 the += operator in loops is optimized to use a single StringBuffer, but there were a few += outside of the loop, and I figured some people will probably use versions of Firefox < 3.5 for some time to come still, and using an array there would certainly improve/decrease the peak memory usage. I didn't know what the affect on performance would be, but this change is commonly said to be the better approach for JavaScript in the past to present, mainly because of the memory issue. Furthermore, the more memory that is used, the more work there is for the garbage collector to deal with, which means your computer is even slower, and that time is hard to measure. I do know that a new feature to Firefox 3.6 is that the garbage collector frees the memory in a new thread, which means that older versions of Firefox did not, and that means that the chances of pauses were even greater. For more reading on these changes I am mentioning in Firefox 3.6 please read this article.

The Tests

Description

In order to test the factors listed above I knew I needed a number of different versions of the convert2RegExp function, but the other piece I needed was a collection of pattern strings to test. I made the different versions of convert2RegExp easily, but when it came to making the pattern set(s) to test I had to do some more thinking.

Test Pattern Sets

I may not have made the best choice, but I decided to use two pattern sets:

  1. Pattern Set 0: 3/50 patterns use the magic tld expression, 2/50 do not use the tld expression, but match /\.[^\.ld]*t[^\.td]*l[^\.lt]*d/
  2. Pattern Set 1: 2/50 patterns use the magic tld expression
In retrospect I think testing an even worse case might be advantages, although I don't suspect the tld expression is used very often. It's hard to say however, I would like to see an audit of userscripts.org, but even with that it'd hard to know what the average case is for all Greasemonkey users, even when you take the install counts from userscripts.org into account, although all of that perspective would be nice to have.

I am an avid user of Greasemonkey and I write quite a few userscripts, and I find that in practice that there are very few times when I would need to userscript to use the magic tld expression, so my feeling is that the ratio is probably closer to 1 tld pattern per 100 or more.

Test Pages/Versions

I decided to run my tests of the different factors listed above for FF3.5/FF3.6 on WinXP, OSX, and Ubuntu (only FF3.5). The test pages worth pointing out are:

  • Original
  • Alternate 3: test of only factor I
  • Alternate 5: test of only factor II
  • Alternate 6: test of factor II + minor change to return a value asap.
  • Alternate 11: test of factor I + II, uses array.unshift() and array.join(), and returns a value asap
  • Alternate 12: test of factor I + II, uses array.push() and array.join(), and returns a value asap
  • Alternate 13: test of factor I + II, and returns a value asap
  • Alternate 15: test using array.unshift() and array.join() as only change

Test Results

Here are the tests I ran and the results I record (the links are to published google docs spreadsheets, all values are in seconds):

AMD 2.21Ghz, DDR2, WindowsXP

Intel Duo 2.0Ghz, DDR3, Mac OSX

Intel Duo 2.0Ghz, DDR3, Windows XP

Intel 2.0Ghz, DDR, Ubuntu

Each test was using a version of convert2RegExp, on a set of 50 patterns, 2500 times.

Results

  • In all cases alternate 3 was faster than the original.
  • In all cases alternate 5 and 6 were faster than the original.
  • In all cases alternate 6 seemed to be slightly faster than 5.
  • In all cases alternate 15 is much faster than the original for FF3.6, and slightly slower for FF3.5.
  • For FF3.5 alternate 13 > alternate 12 ~= original ~> alternate 11
  • For FF3.6 alternate 11 > alternate 13 > alternate 12 > original.
Although for FF3.5 we know that alternate 13 is a bad choice because it uses the += operator which result in O(N^2) characters copied, so we can't use that in my opinion. The final choice has to be between alternate 11 and alternate 12.

This is where I need your help, I have no idea why using array.unshift() is so much faster in Firefox 3.6, and taken that it is, and that the majority of Greasemonkey users will be using the latest version of Firefox, should we use array.unshift() and not array.push()?

Tweet Me!

Some Firefox About:Config Performance Suggestions

After reading "JavaScript speedups in Firefox 3.6" by Alix Franquet, which mentions the JIT for browser UI JavaScript about:config variable named javascript.options.jit.chrome, which was available in Firefox 3.5 and I didn't know it, I finally decided to review all of the Firefox about:config variables and find out what they all were. After I did so I found quite a few settings that if changed from their default settings would make Firefox even faster. These are the settings I want to go over in this article.

To start off with, I would recommend that you install Firefox 3.6 RC2 or higher, because if you read the article I mention above, then you will know why Firefox 3.6 is so much faster than 3.5 is.

About:Config Settings

I'm not going to list every about:config setting, only the ones that I think if changed should improve Firefox's performance.

[More]

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!

Tracking Outbound Links - The Really Right Way

About 5 months ago Eric Vasilik wrote a post on his GWO Tricks blog about Tracking Outbound Links -- The Right Way which was ment to point out a solution for the problem with the technique outlined in the Analytics Help Center article called "How do I manually track clicks on outbound links?", is that it suffers from a Race Condition which may mean the tracking doesn't take place. If you haven't read Eric's article, please do.

Well as readers of my blog would know, I recently wrote a JavaScript click tracking library which can be found at GitHub here. In the blog post I mention that I implemented Eric Vasilik's "Right Way" to track links, but today I started thinking about this some more.

I decided to do some searching on how to cancel a click event, and I found a great old blog post from 2006 by Ryan Campbell pretty quickly which mentions a method implemented by Prototype called Event.stop(). So I decided to dig in to the Prototype code to see what Event.stop() did exactly, so I could extract it, and I found that it does two things, one is to stop the event propagation, and the second is to stop the default behavior for the event. At the end of the post Ryan said that it not work for Safari 2.0.3, which is why it could not be relied on at the time, but today Safari 2.0.3 is dead, and I tested Safari 3 out which works. In fact I decided to do some PPK style testing and try test cases on every browser I could.

After seeing that Event.stop() had two purposes I wanted to find out why this was done, and found this documentation page for Event.stop(), which says this was done "because stopping one of those aspects means, in 99.9% of the cases, preventing the other one as well", but in the case of simply click tracking we don't really want to stop the event propagation, we just want to stop the default action from being triggered eventually. So here is what my update to Eric's example looks like:

<a id="example" href="http://www.example.com">Click me</a>
<script type="text/javascript">
function doGoal(e){
if(!e) var e = window.event;

var targ;
if ( e.target ) targ = e.target;
else if ( e.srcElement ) targ = e.srcElement;
// Safari..
if ( targ.nodeType == 3 ) targ = targ.parentNode;

setTimeout('document.location = "' + targ .href + '"', 100);

try{
var pageTracker=_gat._getTracker("UA-123456-1");
pageTracker._trackPageview("http://www.example.com");
}
catch(err){}

if (e.preventDefault) e.preventDefault(); // w3c
else e.returnValue = false; // for ie
}
if ( document.body.addEventListener ) {
// w3c
document.getElementById('example').addEventListener( "click", doGoal, false );
}
else if ( document.body.attachEvent ) {
// ie
document.getElementById('example').attachEvent( "onclick", doGoal );
}
</script>

To try the code above see the test page here. I have tested this out on IE6+, FF2+, Opera9+, Safari for the iPhone OS 3.0, Google Chrome, and Safari3+ on MacOSX and WindowsXP and they all work, so I am pretty confident that this is going to work for something like ~99% of web users today, and since it would not error even for a user using Safari 2 (which I wasn't able to test), and Safari 2 is so slow, there is a good chance the user would still be tracked anyhow.

If anyone else could try this out on some other browsers at let me know what they find good or bad that would be nice so that I can add them to the list above. The best way to test the test page is to comment out the setTimeout line, and make sure that clicking the link doesn't do anything.

The beautiful part about this method is that it is totally unobtrusive JavaScript code, and will work even if you are using the onclick attribute for other site functionality (even though you shouldn't ever use the onclick attribute).

Merry Clicking!

P.S. The Click Tracking JavaScript Library has been updated to use this really right method, check it out if you haven't already!

A Jetpack: Java Settings

This Jetpack is meant to help Firefox users quickly enable and disable Java or JavaScript, and it is my third entry for the Jetpack 50-line Code Challenge.

Java Settings Jetpack

About

This Jetpack will add a "Enable Javascript" and "Enable Java" menu items to your "Tools" menu for quick access to these settings.

Screen Shot

How To Install

  1. Get Firefox here.
  2. Get Jetpack here
  3. Get the "Java Settings" Jetpack here

[More]

A Jetpack: Firefox 'Restart' Menu Item

I wrote this Jetpack as another entry for the Jetpack 50-line Code Challenge, it is simply a 'Restart' menu item for Firefox's 'File' menu.

When I was trying to come up with ideas I starting thinking about replacing a number of Firefox extensions I currently use with a lightweight Jetpack. So I instantly thought about Quick Restart, by Juan Carlos Avila B, which I have used a lot in the past, but it had a bunch of extra data packaged with it that I didn't want such as localization (albeit I'm sure this is something others want), xul, css, and images files.

I've used Quick Restart for some time now, and still think it is a great addon, but I'm pleased to say that there is a Jetpack option available now.

Firefox 'Restart' Jetpack

About

This Jetpack is using source lifted from the Ubiquity Firefox extension's built-in 'restart' command.

Screen Shot

Screen shot of the 'Restart' menu item in Firefox's 'File' menu

How To Install

  1. Get Firefox here.
  2. Get Jetpack here
  3. Get the "Firefox 'Restart' Menu Item" Jetpack here

[More]

A Jetpack: Tweet This!

I wrote my first entry for the Jetpack 50-line Code Challenge a few weeks ago and I would like to share it with you now. The Jetpack is called Tweet This!, and it is meant to help you quickly tweet about a page you are viewing in Firefox with the document's published short url, if it is defined (otherwise tr.im is used).

Tweet This!

Details

The Tweet This! Jetpack adds a 'Tweet This!' menu item to Firefox's 'Bookmarks' menu and context menu, which when used, will allow the user to Tweet about the page they are on. A user can select some text on the page, or else the page's title will be used for some text in the tweet, and then the Jetpack will first check if the text + long url is less than 140 characters long, and just use the long url if so, but otherwise it will use my Get Short URL service (hosted by Google App Engine) to find the shortest url for the page, which is published by the page, and if one has not been published which is smaller than a length you can change in settings, but is by default 35. If the shortest url found is not shorter than the setting length specified then the tr.im service is used to create a short url for the page.

After the Jetpack has a short url for the page, and some text to tweet about it, it will finally trim the text so that the tweet is equal to 140 chars if necessary, then send the tweet, and notify you with the tweet if it has been sent (also the username that it was sent from is displayed).

Notes

  • If you do not see a notification, then an error occurred, and no tweet was sent, so it will be safe to try again, just make sure you wait about a minute before trying again (don't be too hasty). An error would only occur if the Tr.im or Twitter servers return an error.
  • The jetpack settings are pretty basic, and while they provide a range type they do not show the range to the user, or the value the user has selected in the range. Hopefully this will be changed in short time, but until then I'll just let you know here the Max URL Length range is from 20 to 100.

[More]

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.

More Entries

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