Because sharing is caring

Tracking Facebook likes, shares and sends in Google Analytics

Posted: May 23rd, 2011 | Author: | Filed under: Javascript, JQuery, SEO, Web Development | Tags: , , | No Comments »

Following up on my previous post about Tracking External links with Google Analytics. Here’s something you can use to track Facebook likes and shares.

We’ll track clicks using the Facebook Events. Note that this only works if you’re using FBML!
Here’s the things we’re going to be tracking:

  • Somebody clicks the ‘Like’ button on your website to ‘Like’ your Facebook page
  • Somebody clicks the ‘Like’ button on your website to share the current page on his ‘Wall’
  • Somebody clicks the ‘Send’ button to share this page with some friends on Facebook

And it’s all in here:

FB.Event.subscribe("edge.create",function(response){
	if(response.indexOf("facebook.com") > 0){
                 //if the returned link contains 'facebook,com'. It's a 'Like' for your Facebook page
		_gaq.push(['_trackEvent','Facebook','Like',response]);
	}else{
                 //else, somebody is sharing the current page on their wall
		_gaq.push(['_trackEvent','Facebook','Share',response]);
	}
});
FB.Event.subscribe("message.send",function(response){
	_gaq.push(['_trackEvent','Facebook','Send',response]);
});

As you may have noticed, the Facebook event contains the liked/shared/sent link as response


Easily track outgoing links with jQuery and Google Analytics

Posted: May 19th, 2011 | Author: | Filed under: Javascript, JQuery, SEO, Web Development | Tags: , | 1 Comment »

Outgoing links on your websites cause 3 things:

  • Take linkjuice away from your page
  • Drive traffic away from your webiste
  • They don’t allow you to measure the amount of clicks on that link

The first problem, you have to sort manually by adding the rel=”nofollow” attribute to all external links, as recommended by Google.

The second and third problem, can be easily fixed by using jQuery. I’ll show you how:

Opening external links in a new tab

By opening those links in a new tab, your page stays open, therefore not driving the user away from your page.
Normally, this is done by manually appending target=”_blank” to each link. Let’s let jQuery do that for us.

$(document).ready(function(){
    $("a[@href^='http']").attr('target','_blank');
});

(Do note that I chose to define links starting with ‘http’ as external links)

Tracking clicks on external Links

We can track links by using Google Analytics Event tracking:

$(document).ready(function(){
    $("a[@href^='http']").click(function(){
        _gaq.push(['_trackEvent', 'External Link','Click', $(this).attr("href")]);
    });
});

Putting it all together

$(document).ready(function(){
    $("a[@href^='http']")
        .attr('target','_blank')
        .click(function(){
            _gaq.push(['_trackEvent', 'External Link','Click', $(this).attr("href")]);
        });
});

Help! My internal links also start with ‘http’

No problem, you can do like me and borrow this trick from Karl Swedberg:

$('a').filter(function() { return this.hostname && this.hostname !== location.hostname; })
.attr('target','_blank')
.click(function(){
    _gaq.push(['_trackEvent', 'External Link','Click', $(this).attr("href")]);
});


lib.js: Good practice and generally a good idea

Posted: February 4th, 2011 | Author: | Filed under: Javascript, JQuery, Web Development | Tags: , , , | No Comments »

I recently stumbled upon an article on Six Revisions titled Are Current web design trends pushing us back to 1999?.

I found it to be a very interesting article. It mainly talks about how new trends in the web are barking up old problems, like the Flash splash page, or the shoutbox.

On thing I found very interesting was the part called Modern-Day Bloated, Cut-And-Paste Scripts.

Being involved with jQuery on a day-to-day basis, you start using some plugins, or even write some of your own.
But once you start stacking plugins, the browser has to load all of these plugins, generating more request. Which is generally a good idea.
Bloated plugins

Now whenever creating a new webproject, I use one JS file: lib.js. This JS file contains everything I need, it’s like a swiss pocket knife!
Structure is usually like following (depends on your project needs):

  • jQuery
  • jQuery UI
  • Plugins
  • $(document).ready(function(){ /**magic here **/});

You could argue by saying: but doesn’t the filesize increase by a lot, letting the user download a 250k file is quite a lot!
I agree, but play your cards right in server configuration with a little help from Google’s mod_pagespeed or simply by getting goot ETags or Expires headers, the load happens just once (!!). And the rest of your surfing experience stays snappy.


Executing Javascript from an external Iframe

Posted: January 21st, 2011 | Author: | Filed under: Javascript, Web Development | Tags: , , , , , | 3 Comments »

Whats the problem?

Maybe you’ve made a deal with a partner website, or you’re just loading a page from another server. The point is: You’ve got an IFrame on your page coming from another domain.
All is well (except for Google, they don’t like iframes) untill you want some client-side interaction coming from that page.

But now you’ve reached the point where you want some client-side interaction from that IFrame. “Great!” you say. I’ll just put JS in the IFrame, and I’ll be fine. But hold your horses cowboy, there’s 2 things stopping you as a great developer from doing so:

  • Don’t have you JS scattered, have it nice and organised, centralized
  • You’re visually constrained to the IFrame

So how do we execute JS on the parent frame?

Directly from the IFrame? You can’t! Sandbox specifications say you can’t call functions defined in pages coming from another domain (kind of like loading JSON/Ajax from another domain).

But in that problem also lies the solution: just load a Proxy page from the other server!
Let me make myself a bit more clear through some Graphs:

Normally, you’de have 2 pages, page A contains an Iframe to page B:
Page A to Page B
Now we’re introducting a Proxy page, on the same server as page A. Page B contains a IFrame to the proxy page:
Page A to B to Proxy
All Done! Now you can execute JS, like so:
all done

The Code!

So how do we do it? Here you go!
index.html (on your server)

<html>
	<head>
		<script type="text/javascript">
			function alertme(str)
			{
				alert("String: " + str);
			}
		</script>
	</head>
	<body>
		<iframe src="http://yourpartner.com/iframe.htm"></iframe>
	</body>
</html>

proxy.html (on your server)

<html>
	<head>
		<script type="text/javascript">
			function gup( name )
			{
			  name = name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
			  var regexS = "[\\?&]"+name+"=([^&#]*)";
			  var regex = new RegExp( regexS );
			  var results = regex.exec( window.location.href );
			  if( results == null )
			    return "";
			  else
			    return results[1];
			}
			eval("top."+gup("execute"));
		</script>
	</head>
</html>

And finally!
iframe.html (on any other server)

<html>
        <head>
        </head>
        <body>
        Hi There!
        <iframe src="http://yourserver.com/proxy.html?execute=alertme(123);"></iframe>
        </body>
</html>

What you did there, I don’t quite see it

In the page on the other server, I pass a function call as an argument to my proxy.
My proxy then gets this function out of the parameter, and executes it through eval()!

Warning

Handle with care, allowing anyone to simply execute JS on/from your server through a parameter just opens up a whole new spectrum of XSS attacks.
That sandbox was created for a reason!


jQuery Plugin Development

Posted: September 24th, 2010 | Author: | Filed under: Javascript, JQuery, Web Development | Tags: , , | 4 Comments »

You can write your jQuery plugin as advanced as you please.
This for example, is a jQuery Plugin:

	jQuery.fn.log = function (msg) {
		console.log("%s: %o", msg, this);
		return this;
	};

But the whole jQuery UI Accordion is also a plugin :-)

I went out to write a larger kind of plugin for a website. And I wanted to find a good plugin writing pattern. These links helped:

Most of them agree to extending the jQuery namespace:

(function($) {
    $.fn.myplugin = function(){
        //Stuff here...
    };
})(jQuery);

But I do miss a bit of Object Orientation in most of them.
I decided to take a bit of each, and create my own approach.
I won’t explain it much, it should be understandable with the comments in code:

(function($){
	/**
	** Seperate object. So each element applied with this plugin has an object structure
	**/
	function PluginObject(container,options){
		//I like to keep a reference to the object I'm working on
		var holder = container;
		//Store 'this' as an instance variable. This comes in handy when you want to speak to it as a reference in clickhandlers etc.
		var _self = this;
		this.init = function()
		{
			//initialize UI and data here
		}
 
		this.test = function()
		{
			//This function serves as a demo method that can be called from outside
		}
		this.render = function()
		{
			// Do complicated rendering here
 
			// Trigger the onRender that could be set through the options
			this.trigger('onRender');
		}
		this.init();
	}
	$.fn.myplugin = function(action,options){
		/**
		** 'action' can be an argument for a function to call
		** If no action is defined, and we just start with the options, initialize is called
		**/
		if (typeof(action) == 'object') {
			options = action;
			action = 'initialize';
		}else if(action == undefined)
		{
			action = 'initialize';
		}
		if(options == undefined)
		{
			options = {};
		}
		/**
		** Set, or update the options
		**/
		function setOptions(el) {
			// If any of the options is a function, bind that as an event
			// this can be something like: 'onRender'
			$.each(options, function(event, fn) {
				if (typeof(fn) == 'function') {
					//Unbind the event if it was already bound
					el.unbind(event);
					//Bind the event with the given function
					el.bind(event, fn);
				}
			});
			//Extend the options with the defaults, and the options already saved in the object
			options = $.extend({}, defaults, el.data('shelf.options'), options);
			// Save the options in the object's data
			el.data('shelf.options', options);
		};
		// Default options
		var defaults = {
			width: 	'900px',
			title: 'Cool Stuff'
		};
		/**
		** This is called everytime we do $(..).myplugin(..)
		**/
		return this.each(function(el){
			el = $(this);
			setOptions(el);
			if(action == 'initialize' || el.data('shelf') == undefined){
				// Initialize the object, save it in itself
				el.data('shelf', new PluginObject(el, options));
			}
			// if called like $(..).myplugin('test'), this is called
			if(action == 'test')
				el.data('shelf').test();
			// This will call render(), render will also trigger 'onRender'
			if(action == 'render')
				el.data('shelf').render();
		});
 
	};
})(jQuery);

Do you develop plugins differently? Or got a good link? I would love to hear about it!


Radio Button values in jQuery

Posted: August 27th, 2010 | Author: | Filed under: Javascript, JQuery, Web Development | Tags: , , , , | No Comments »

Getting the values of radio buttons in Javascript can be a bit of a pain in the behind at times.
You’ll have to assign a different ID to each radiobutton, loop over them to see which one is checked, and return that value.
Too much hassle.

However, jQuery selectors to the rescue!
Suppose you have the following radio buttons:

<input type="radio" name="animals" value="Dog" />
<input type="radio" name="animals" value="Cat" />
<input type="radio" name="animals" value="Bird" />

Getting the selected value could be done like so:

$('input[name=animals]:checked').val()

Try it here:

Dog

Cat

Bird

Good luck, hope it helps someone!


Those fancy GMail buttons

Posted: August 24th, 2010 | Author: | Filed under: css, Javascript, Web Development | Tags: , , , | 2 Comments »

For a project I’ve been working on, I wanted to use a different kind of button then the normal HTML .

I decided to go for the GMail style button!
They’re really nice:

  • simple HTML
  • still looks like a button (user friendlyness++)
  • has a modern look aswell

It’s been done before by stopdesign.com, but I wanted to do it myself
I went to dive in some Google CSS and came up with the following:
CSS:

.btn{
	margin:0 8px 0 0;
	padding:3px 8px;
	text-align:center;
	vertical-align:middle;
	white-space:nowrap;
	cursor:default;
	outline:none;
	font:arial,sans-serif;
	color:#000;
	border:	1px solid #bbb;
	-webkit-border-radius:3px;
	-moz-border-radius:3px;
	border-radius: 3px;
	background: -webkit-gradient(linear, left top, left bottom, from(#f9f9f9), to(#e3e3e3)); 
        background: -moz-linear-gradient(top, #f9f9f9, #e3e3e3);
        filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#f9f9f9', endColorstr='#e3e3e3');
	border-top-color:#ccc;
	border-bottom-color:#a0a0a0;
	cursor: pointer;
	display: inline-block;
	position: relative;
}
.btn:hover{
	border: 1px solid #636363;
}

Now simply make all your buttons like so:

<div class="btn"><span>Cooler button!</span></div>

which gives you this:

Cooler button!

Strong note: These aren’t actually buttons, they can’t really be used as form-submit buttons as they can only respond to Javascript onClick events! My newer post on the real buttons does do this!
Tested in FF 3.6, Chrome 5, IE8


JQuery UI tabs with selected by #location.hash

Posted: August 5th, 2010 | Author: | Filed under: Javascript, JQuery, Web Development | Tags: , , , | No Comments »

I’m using JQuery UI Tabs in an application.
I really love the implementation, never seen anything so easy.

If you want to make sure another tab but the first one is selected on page load, just give the ‘selected’ option like so:

$("#tabs").tabs({selected: 1});

For the second tab in the tabarray (counting starts with 0).

If you want to make your url’s do the following however: http://www.example.com/mytabbedpage.do#gotothistab. There’s no support from JQuery itself just yet.

I found a solution on Rootsmith Inc’s blog.
Especially sami‘s comment helped me:

1
2
3
4
$(’#my_selector’).tabs({
’select’: function(){$(this).index($(document.location.hash));},
‘load’: function(event, ui){document.location.hash = ui.panel.id;}
});

However, applying this loses your default tab.
My solution:

1
2
3
4
5
var selectedtab = 1;
if(document.location.hash!="" && typeof(document.location.hash)!="undefined" && document.location.hash!= null){
	selectedtab = $(document.location.hash).index() - 1;
}
$("#tabs").tabs({selected:selectedtab});

I know, I like to be thorough in my checks ;-)