In "Why I’m writing my own blog system" I announced my plans to build a custom blog platform. Seeing as I wrote about it before I'd actually written the script I had to publish the announcement on a different blog system; Wordpress. Something happened while I was using Wordpress though; I actually started enjoying it. The sophistication behind the scenes really started to pique my interest and get me excited. I started looking at plugins and getting into how themes are put together; it's a really a well thought out and executed product.
Now, with the above realization came another; I shouldn't write a blog system anymore, Wordpress is just too damn good at it. Doing so would be the picture of reinventing the wheel; it would just be a waste of my time. That's not to say it's perfect. There are definitely a few areas that Wordpress is lacking in, for my needs especially. It's not really an issue though because the developers thought of this and implemented a very well thought out plugin system.
One of the more obvious features I wanted, that Wordpress is lacking, is some sort of tracking mechanism for links in posts. Basically, I want to know how many times links in my posts have been clicked so I decided to write a plugin to handle this. Surprisingly, I was able to get a working version up and going in about 12 hours of total work.
The Plan
Well, as I stated above the plugin is going to allow the tracking of link clicks in posts and pages. I want this to be as painless as possible to manage so there won't be any CRUD portion. Initially, the plugin will extract all links out of the post on the user side and modify them to allow for tracking. The tracking should delineate between unique and repeat clicks and stats should be displayed on the edit page. The plugin should be installable through the Wordpress plugin manager
The Basics
A plugin is just a php script that follows some formatting and business rules so it's pretty straight forward once you get the requirements out of the way. Here are the basics:
Plugins should all be placed in the /wp-content/plugins directory. It's also a good idea to place your plugin in it's own sub directory; this way all your files are segregated into a single place.
All plugins require a specific header comment format:
<?php
/*
Plugin Name: Name Of The Plugin
Plugin URI: http://URI_Of_Page_Describing_Plugin_and_Updates
Description: A brief description of the Plugin.
Version: The Plugin's Version Number, e.g.: 1.0
Author: Name Of The Plugin Author
Author URI: http://URI_Of_The_Plugin_Author
*/
?>
Right away I noticed how the above comment isn't in phpdoc but it turns out that's ok; you can still put that above anything else.
After that is where you can put the license:
<?php
/* Copyright YEAR PLUGIN_AUTHOR_NAME (email : PLUGIN AUTHOR EMAIL)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
?>
Having the above in a file placed in the plugin directory is enough to have the plugin displayed in the plugin manager.
The functionality of the plugin comes from custom functions that are placed in hook wrappers. The hook wrappers work through various actions and filters which are accessed through add_action() and add_filter() like the below:
<?php
function plugin_filter_function($content){
//do something to the post content
return $content;
}
function plugin_action_function(){
//execute some code...
}
add_filter('the_content', 'plugin_filter_function', 1);
add_action('wp_head', 'plugin_action_function');
?>
To activate a plugin there might be some preparation needed for the plugin; the same for deactivating. To execute functionality during both processes:
<?php
function plugin_install_function(){
//execute some code...
}
function plugin_deactivate_function(){
//execute some code...
}
register_activation_hook(__FILE__,'plugin_install_function');
register_deactivation_hook(__FILE__, 'plugin_deactivate_function');
?>
It's also possible to disable some built in actions and functions, though I didn't need to do this on my plugin.
<?php
remove_filter('filter_hook','filter_function')
remove_action('action_hook','action_function')
?>
The Program
With the above out of they way all that's left is the actual plugin code. Here's the basic outline:
<?php
/**
* Wordpress Click Tracker
*
* Contains all the click tracker functions.
*
* @author Eric Lamb
* @package wp-click-tracker
* @version 0.1
* @filesource
* @copyright 2009 Eric Lamb.
*/
/*
Plugin Name: Click Tracker
Plugin URI: http://blog.ericlamb.net/
Description: Tracks all links in posts.
Version: 0.1
Author: Eric Lamb
Author URI: http://blog.ericlamb.net
*/
/* Copyright 2009 Eric Lamb (email : eric@ericlamb.net)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/**
* Version of wp-click-tracker code
* @global string $click_tracker_version
*/
$click_tracker_version = "0.1";
/**
* Version of wp-click-tracker database
* @global string $click_tracker_db_version
*/
$click_tracker_db_version = "0.1";
/**
* Wrapper for click track filter
*
* @param string $content string to parse
* @return string The completed
*/
function wp_click_tracker_filter($content)
{
return wp_click_tracker_replace_uris($content);
}
/**
* Takes a string and extracts all the links (URIs)
*
* @param string $content string to parse
* @return array The links
*/
function wp_click_tracker_extract_urls($content){
}
/**
* Replaces all the URLs in a string with newly created URLs for tracking
*
* @param string $content string to parse
* @return string $content The filtered content
*/
function wp_click_tracker_replace_uris($content){
}
/**
* Installs the database tables and settings
*
* @return void
*/
function wp_click_tracker_install () {
global $wpdb;
global $click_tracker_db_version;
global $click_tracker_version;
add_option("click_tracker_version", $click_tracker_version);
add_option("click_tracker_db_version", $click_tracker_db_version);
}
/**
* Handles the removal of a plugin
*
* @return void
*/
function wp_click_tracker_deactivate(){
}
/**
* Adds the javascript embed to the header
*
* @return void
*/
function wp_click_tracker_head()
{
}
/**
* Execution of click tracker
*
* @return void
*/
function wp_click_tracker_go(){
}
/**
* Displays administration quick view
*
* @return void
*/
function wp_click_tracker_link_data(){
}
/**
* Adds the click tracker options page to the administration module
*
* @return void
*/
function wp_click_tracker_menu() {
add_options_page('Click Tracker Options', 'Click Tracker', 8, __FILE__, 'wp_click_tracker_options');
}
/**
* Displays the click tracker administration module
*
* @return void
*/
function wp_click_tracker_options() {
}
register_activation_hook(__FILE__,'wp_click_tracker_install');
register_deactivation_hook(__FILE__, 'wp_click_tracker_deactivate');
add_action('edit_form_advanced', 'wp_click_tracker_link_data');
add_action('edit_page_form', 'wp_click_tracker_link_data');
add_action('wp_head', 'wp_click_tracker_head');
add_action('init','wp_click_tracker_go');
add_filter('the_content', 'wp_click_tracker_filter', 1);
add_filter('the_excerpt', 'wp_click_tracker_filter', 1);
?>
Granted, the above doesn't really do anything; it's only the framework. Still, I was able to get the research and above code done in a little under 6 hours. After that it's just like any other project (write function, test, fix bugs, write new funtion, etc...) which only took an additional 6 hours.
Download the complete plugin.
Click Tracker
Resources
Writing a Plugin
Plugin API
Wordpress Hooks
Wordpress Code Documentation