Archive

Archive for October, 2011

WordPress: How to add Google Analytics to WordPress blog

October 27th, 2011 No comments

    Google Analytics is a web analytics solution that allows to see into our traffic data. It’s a small JavaScript code that we should put in every page, which requires tracking. Of course, at first we have to sign up for a Google Analytics account at http://www.google.com/analytics/. After registration we will be provided with the JavaScript code which looks similar to the following:

<script type="text/javascript">

  	var _gaq = _gaq || [];
  	_gaq.push(['_setAccount', 'UA-32102375-1']);
  	_gaq.push(['_trackPageview']);

  	(function() {
    	var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
    	ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
    	var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
  	})();

</script>

This script has to be placed within the HTML of the web pages of our WordPress blog. The simplest way to do that is to use the capabilities provided by your WordPress theme. Check if your current theme already allows to add a web analytics code to the blog. Log into admin section of the blog (wordpress/wp-admin), go to Appearance -> Current Theme Options (wordpress/wp-admin/themes.php), scroll to the Web Analytics field. If it’s exist, that means that your theme supports web analytics. Just put JavaScript code provided by Google into the field, check the ‘Add web analytics code to your site. (e.g. Google Analytics, Yahoo! Web Analytics, …)’ option and save changes. Ever since changes are applied web analitycs code gets inserted into every page.

Current Theme Options

My current theme, iNove, supports web analitycs, but the way described above is too easy for such geek as I’m. I decided to inject web analytics code into the site pages by my own hands.

It is known, if you want to have some code inside every page of the WordPress blog, you should utilize such files as header.php or footer.php. Both are included into every page. We can alter them by using admin section. Go to Appearance -> Editor (wordpress/wp-admin/theme-editor.php), select the required theme in drop-down list on the right if it’s not selected yet, then select, for example, header.php, put your web analytics code before the original content and press Update File button.

Edit Theme Files

We can do the same through the ftp by locating header.php or footer.php in the appropriate folders. Copy one or another from the web server to the local environment, alter the php file and replace old version on the web server by modified one.

iNove Folders

Note that in iNove theme the header.php, which is available for edit through the Appearance -> Editor, is situated in the templates sub-folder, while the footer.php is in the root folder of iNove. In the root folder also there is another header.php. Both of them supplement each other, to be more precise the header.php from the root folder includes the one from the templates sub-folder by using the <?php include(‘templates/header.php’); ?> directive.

Personally I have modified the header.php from the root folder of iNove and replaced the old one through the ftp. I’ve put the web analitycs code right before the closing html head-tag (</head>). It works perfectly. The altered file is shown below:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<?php
	global $inove_nosidebar;
	$options = get_option('inove_options');
	if (is_home()) {
		$home_menu = 'current_page_item';
	} else {
		$home_menu = 'page_item';
	}
	if($options['feed'] && $options['feed_url']) {
		if (substr(strtoupper($options['feed_url']), 0, 7) == 'HTTP://') {
			$feed = $options['feed_url'];
		} else {
			$feed = 'http://' . $options['feed_url'];
		}
	} else {
		$feed = get_bloginfo('rss2_url');
	}
?>

<html xmlns="http://www.w3.org/1999/xhtml">
<head profile="http://gmpg.org/xfn/11">
	<meta http-equiv="Content-Type" content="<?php bloginfo('html_type'); ?>; charset=<?php bloginfo('charset'); ?>" />
	<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7" />

	<title><?php bloginfo('name'); ?><?php wp_title(); ?></title>
	<link rel="alternate" type="application/rss+xml" title="<?php _e('RSS 2.0 - all posts', 'inove'); ?>" href="<?php 

echo $feed; ?>" />
	<link rel="alternate" type="application/rss+xml" title="<?php _e('RSS 2.0 - all comments', 'inove'); ?>" href="<?php 

bloginfo('comments_rss2_url'); ?>" />
	<link rel="pingback" href="<?php bloginfo('pingback_url'); ?>" />

	<!-- style START -->
	<!-- default style -->
	<style type="text/css" media="screen">@import url( <?php bloginfo('stylesheet_url'); ?> );</style>
	<!-- for translations -->
	<?php if (strtoupper(get_locale()) == 'ZH_CN' || strtoupper(get_locale()) == 'ZH_TW') : ?>
		<link rel="stylesheet" href="<?php bloginfo('stylesheet_directory'); ?>/chinese.css" type="text/css" 

media="screen" />
	<?php elseif (strtoupper(get_locale()) == 'HE_IL' || strtoupper(get_locale()) == 'FA_IR' || strtoupper(get_locale()) 

== 'UG_CN' || strtoupper(get_locale()) == 'CKB') : ?>
		<link rel="stylesheet" href="<?php bloginfo('stylesheet_directory'); ?>/rtl.css" type="text/css" 

media="screen" />
	<?php endif; ?>
	<!--[if IE]>
		<link rel="stylesheet" href="<?php bloginfo('stylesheet_directory'); ?>/ie.css" type="text/css" 

media="screen" />
	<![endif]-->
	<!-- style END -->

	<!-- script START -->
	<script type="text/javascript" src="<?php bloginfo('template_url'); ?>/js/base.js"></script>
	<script type="text/javascript" src="<?php bloginfo('template_url'); ?>/js/menu.js"></script>
	<!-- script END -->

	<?php wp_head(); ?>
	
	<script type="text/javascript">

  	var _gaq = _gaq || [];
  	_gaq.push(['_setAccount', 'UA-32102375-1']);
  	_gaq.push(['_trackPageview']);

  	(function() {
    	var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
    	ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
    	var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
  	})();

	</script>

</head>

<?php flush(); ?>

<body>
<!-- wrap START -->
<div id="wrap">

<!-- container START -->
<div id="container" <?php if($options['nosidebar'] || $inove_nosidebar){echo 'class="one-column"';} ?> >

<?php include('templates/header.php'); ?>

<!-- content START -->
<div id="content">

	<!-- main START -->
	<div id="main">

An alternative way is to use appropriate plugins. For example, like Google Analytics for WordPress or similar. But besides evident conveniences, the dealing with plugins has some small disadvantages as well. The use of too many plugins may slow down your site. As for me the adding of analytics code isn’t worth having one more plugin, which requires recurrent updates and some kind of maintenance.

Related posts:

SharePoint: How to find all controls of a certain type

October 12th, 2011 No comments

    A small, but useful method to find recursively all controls of a certain type:

public static List<T> FindControlRecursiveByType<T>(Control root) where T : Control
{
    List<T> res = new List<T>();

    if (root != null)
    {
        Stack<Control> tmpStack = new Stack<Control>();
        tmpStack.Push(root);

        while (tmpStack.Count > 0)
        {
            Control ctrl = tmpStack.Pop();
            if (ctrl is T)
                res.Add(ctrl as T);

            foreach (Control childCtrl in ctrl.Controls)
                tmpStack.Push(childCtrl);
        }
    }

    return res;
}

The sample usage is below:

// return all save buttons on the page
List<SaveButton> saveButtons = FindControlRecursiveByType<SaveButton>(Page);
Related posts:
Categories: ASP.NET, Share Point Tags: ,

JavaScript: Event aggregator

October 3rd, 2011 No comments

    JavaScript is an event-driven language. The most of JavaScript objects (from document to button) contains events, which some response actions can be bound to. Suddenly I wanted to use the event-driven approach with my own objects, so that they could subscribe to events of each other. I implemented a special object – EventAggregator, which allows to manage listeners of events. EventAggregator is a pure JavaScript implementation, without jQuery and others.

function EventAggregator() {

    this._eventToListenersMap = {}; // key-value dictionary: key is an event name, value is an array of listeners

    // Method adds listener
    // eventName - a string event name
    // callback  - a function that has to be called, when event is raised
    // context   - object containing the callback function
    this.Subscribe = function(eventName, callback, context) {
    
        if (!this._eventToListenersMap.hasOwnProperty(eventName)) // check if key exists
            this._eventToListenersMap[eventName] = []; // create an array to store listeners

        // add listener of a certain event to the array. Listener is a combination of 
        // a callback function to call when event is raised and an object containing the callback function
        this._eventToListenersMap[eventName].push({ 'Callback': callback, 'Context': (typeof context != "undefined" ? context : null) });
    }

    // Method removes listener
    // eventName - a string event name
    // callback  - a function that has to be removed
    this.Unsubscribe = function(eventName, callback) {

        if (this._eventToListenersMap.hasOwnProperty(eventName)) { // check if key exists
            // get through the array of listeners of a certain event to find the listener that has to be removed
            for (var i = 0; i < this._eventToListenersMap[eventName].length; ++i) {
                // check if it's a required listener    
                if (callback == this._eventToListenersMap[eventName][i].Callback) {
                    this._eventToListenersMap[eventName].splice(i, 1); // remove the found listener
                    break;
                }
            }
            
        }
    }

    // Method raises event
    // eventName - a string event name
    // args      - a data that has to be passed into a callback function
    this.Fire = function(eventName, args) {

        if (this._eventToListenersMap.hasOwnProperty(eventName)) { // check if key exists
            // get through the array of listeners of a certain event to find the listeners that has to be called
            for (var i = 0; i < this._eventToListenersMap[eventName].length; ++i) {
                try {
                    // get the object containing the callback function
                    var contextObj = this._eventToListenersMap[eventName][i].Context;
                    // invoke callback in context of the object
                    this._eventToListenersMap[eventName][i].Callback.call(contextObj, args);
                } catch (e) {
                }
            }
        }
    }
}    

Note that if you use the Subscribe method and pass a callback function, which is a member of some object, you have to pass this object as well. If you pass null as the parameter context or pass nothing, EventAggregator try to call the callback function of the top-level object of the client-side object hierarchy. This top-level object is the window object.

Code sample how to use EventAggregator is shown below:

function Dog() {
    this.Events = new EventAggregator();
    
    this.ON_BARK  = "OnBark";
    this.ON_WHINE = "OnWhine";   

    this.Bark = function() {
        this.Events.Fire(this.ON_BARK, this);
    }
    this.Whine = function() {
        this.Events.Fire(this.ON_WHINE, this);
    }
}

function Master() {
    this.Events = new EventAggregator();
    this.Dog    = new Dog();

    this.ON_WAKE_UP = "OnWakeUp";

    this._init = function() {
        this.Dog.Events.Subscribe(this.Dog.ON_BARK, this._wakeUp, this);
        this.Dog.Events.Subscribe(this.Dog.ON_WHINE, this._wakeUp, this);
    }

    this._wakeUp = function(args) {
        this.Events.Fire(this.ON_WAKE_UP, args);
    }

    this._init();
}


var ownerlessDog = new Dog();
ownerlessDog.Events.Subscribe(ownerlessDog.ON_BARK, function() { alert('Dog barked'); }, null);
ownerlessDog.Bark();

var master = new Master();
master.Events.Subscribe(master.ON_WAKE_UP, function() { alert('Master woke up') }, null);
master.Dog.Whine();

Probably, It will be useful for somebody.

Categories: JavaScript Tags: ,