WordPress Stats: Create A Simple Stats Plugin For Your Site

Have you wanted to just have a simple WordPress stats system for your website without having to go through all the hassles of creating a new site under Google analytics.  Well I have a simple solution for you. It does not give you every detail of stats but it's good enough to show you Total Visits and Unique Visits.

So you are probably eager to get started with this? First off create a new folder under your plugins directory called “simple stats” and within that folder a file called stats.php

STEP 1

First thing you need to do is open the stats.php file and right at the top of the file add the following so that the plugin can be detected.

/*
Plugin Name: Zooker Simple Stats
Plugin URI: http://yoururl.net
Description: Simple WordPress stats
Version: 1.0
Author: Your Name
Author URI: http://teachingyou.net
License: GPL2
*/

STEP 2

Create a init function to register the database and javascript files needed to run the stats plugin.

    add_action('init', 'zkr_stats_init_plugin');
function zkr_stats_init_plugin() {
//wp_enqueue_script( 'jquery' );
zkr_stats_table_plugin(); // create table for slider images

// Register google charts JS
wp_register_script( 'zkr_google_charts', 'https://www.google.com/jsapi'); // this is for js bowser detections css
wp_enqueue_script( 'zkr_google_charts' ); //this part put the script in to our page header

}

STEP 3

Here we set our version number and also create a function that will create our database table to hold our visitors details.

/*
* Create stats Table
*/
global $zkr_stats_version;
$zkr_stats_version = "1.0";
function zkr_stats_table_plugin() {
global $wpdb;
global $zkr_stats_version;
// table for ads
$table_name = $wpdb->prefix . "zkr_stats";

if($wpdb->get_var("show tables like '$table_name'") != $table_name) {

$sql = "CREATE TABLE " . $table_name . "  (
`ID` INT NOT NULL AUTO_INCREMENT ,
`ip` VARCHAR(255) NULL ,
`filename` VARCHAR(255) NULL ,
`referer` VARCHAR(255) NULL ,
`browser` TEXT NULL ,
`method` VARCHAR(45) NULL ,
`timestamp` DATETIME NOT NULL ,
`number` VARCHAR(45) NULL ,
PRIMARY KEY (`ID`) )
CHARACTER SET utf8 COLLATE utf8_general_ci;";

require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
dbDelta($sql);

add_option("zkr_db_version_stats", $zkr_stats_version);

}
}

We create table with the name zkr_stats and of course added any table prefix to that name as it could also be wp_zkr_stats. This is all done with $table_name = $wpdb->prefix . "zkr_stats";

This mysql table will contain fields called:

ID, this holds ids for new records created.

ip, this holds the visitors ip and helps tracking unique visitors.

filename, this holds the page name where the person landed on for example index.php. This is not the same as the referrer.

referer,  holds the url where the visitor came from.

browser, keeps details on the type of browser the user is using, example, IE and Firefox

method, this will tell you whether the person got here with a get or post method.

Timestamp, holds the time the person came to your site, also used to check monthly stats.

Number, holds the amount of times a visitor has been on the site.

STEP 4

Here we will add JavaScript to our header which gets the details of our visitors and send those details  via ajax to our function which handles the storing of the details in our database.

//add ajax to header for tracking users
add_action('wp_head', 'myjavascriptheader');
function myjavascriptheader(){

if(isset($_SERVER['HTTP_REFERER'])){ $myreferer = $_SERVER['HTTP_REFERER']; }else{ $myreferer = null; }

echo "<script type='text/javascript'>

jQuery(document).ready(function() {
var thedata = {
action: 'my_action',
zkr_ajax_test: 'AJAX test',
zkr_filename: '" . $_SERVER['PHP_SELF'] ."',
zkr_ip: '". $_SERVER['REMOTE_ADDR'] ."',
zkr_referer: '". $myreferer ."',
zkr_browser: '". $_SERVER['HTTP_USER_AGENT'] ."',
zkr_method: '". $_SERVER['REQUEST_METHOD'] ."'
};

// since 2.8 ajaxurl is always defined in the admin header and points to admin-ajax.php
var ajaxurl = '". admin_url('admin-ajax.php') ."';
jQuery.post(ajaxurl, thedata, function(response) {

});
});

</script>";
}

STEP 5

In this step we add the function which will handle the storing of the data that was sent to it via ajax.

add_action("wp_ajax_nopriv_my_action", "test"); //ajax callback
add_action("wp_ajax_my_action", "test"); //ajax callback
function test() {
global $wpdb;

$filename = $_POST['zkr_filename'];

$ip = $_POST['zkr_ip'];
$referer = $_POST['zkr_referer'];

$method = $_POST['zkr_method'];
$browser = $_POST['zkr_browser'];

$table_name = $wpdb->prefix . "zkr_stats";
$row = $wpdb->get_results( "SELECT * FROM ".$table_name." WHERE ip = '$ip' ");
if($wpdb->num_rows === 0){

$num = 1;

$wpdb->query(  "INSERT INTO ". $wpdb->prefix ."zkr_stats(ip, filename, referer, browser, method, timestamp, number) VALUES('".$ip."', '".$filename."', '".$referer."', '".$browser."', '".$method."', NOW(), '".$num."')" ) or wp_die( 'Could not save data!' ); //insert new data if the current ip was not used before
}
elseif($wpdb->num_rows === 1){

foreach($row as $rows){
$num = $rows->number + 1;
}
$wpdb->query( "UPDATE ".$table_name." SET number = '".$num."' WHERE ip = '".$ip."'" )or wp_die( 'Could not update data!' ); //update visit data for old ip

}

$response = array(
'what'=>'Data saved',
'action'=>'save_something',
'id'=>'1',
'data'=>'Just saved a record'
);
$xmlResponse = new WP_Ajax_Response($response);
$xmlResponse->send();

die();

}

You will notice that we have added two actions above the function, those are to be able to receive data from our ajax calls. Without it, it will simply not work as we are running the ajax on the front end.

add_action("wp_ajax_nopriv_my_action", "test"); //ajax callback
add_action("wp_ajax_my_action", "test"); //ajax callback

We then set our global $wpdb variable to be able to create queries to our database.

global $wpdb;

Then we get our POST variables and set them to custom named variables so it’s easy to see what is what.

$filename = $_POST['zkr_filename'];

$ip = $_POST['zkr_ip'];
$referer = $_POST['zkr_referer'];

$method = $_POST['zkr_method'];
$browser = $_POST['zkr_browser'];

Next we do a select query to check if our visitor IP exists in our database if not then insert a new record.

$table_name = $wpdb->prefix . "zkr_stats";
$row = $wpdb->get_results( "SELECT * FROM ".$table_name." WHERE ip = '$ip' ");
if($wpdb->num_rows === 0){

$num = 1;

$wpdb->query(  "INSERT INTO ". $wpdb->prefix ."zkr_stats(ip, filename, referer, browser, method, timestamp, number) VALUES('".$ip."', '".$filename."', '".$referer."', '".$browser."', '".$method."', NOW(), '".$num."')" ) or wp_die( 'Could not save data!' ); //insert new data if the current ip was not used before
}

If a record or say a users IP already exists, then we update our record and plus one to our number so that we can count how many times that visitors been on our site.

elseif($wpdb->num_rows === 1){

foreach($row as $rows){
$num = $rows->number + 1;
}
$wpdb->query( "UPDATE ".$table_name." SET number = '".$num."' WHERE ip = '".$ip."'" )or wp_die( 'Could not update data!' ); //update visit data for old ip

}

Next I added some ajax response code to send back to our javascript so that I can see that our code is actually being called and saved and we then end the function with a die(); to complete it.

    $response = array(
'what'=>'Data saved',
'action'=>'save_something',
'id'=>'1',
'data'=>'Just saved a record'
);
$xmlResponse = new WP_Ajax_Response($response);
$xmlResponse->send();

die();

STEP 6

In this step we create a function to display our stats in nice looking Google charts. Google charts makes it easy to put data in to nice looking charts so that people using your data can see it in a visual representation.

add_action('admin_head', 'zkr_chart_js_admin');
function zkr_chart_js_admin() {
global $wpdb;
$table_name = $wpdb->prefix . "zkr_stats";
//Daily stats
$row = $wpdb->get_results( "SELECT * FROM ".$table_name." WHERE DAY( TIMESTAMP ) = DAY( NOW( ) ) ");
$visits = $wpdb->get_var(  $wpdb->prepare( "SELECT SUM( number ) FROM ".$table_name." WHERE DAY( TIMESTAMP ) = DAY( NOW( ) )" ));
$unique = count($row);
//Monthly Stats
$rowm = $wpdb->get_results( "SELECT * FROM ".$table_name." WHERE DATE( TIMESTAMP ) = DATE( NOW( ) ) ");
$visitsm = $wpdb->get_var(  $wpdb->prepare( "SELECT SUM( number ) FROM ".$table_name." WHERE DATE( TIMESTAMP ) = DATE( NOW( ) )" ));
$uniquem = count($rowm);

echo "<script type=\"text/javascript\">

// Load the Visualization API and the piechart package.
google.load('visualization', '1.0', {'packages':['corechart']});

// Set a callback to run when the Google Visualization API is loaded.
google.setOnLoadCallback(drawChart);

// Callback that creates and populates a data table,
// instantiates the pie chart, passes in the data and
// draws it.
function drawChart() {

// Create the data table for day stats
var data = new google.visualization.DataTable();
data.addColumn('string', 'Visits');
data.addColumn('number', 'Total Visits');
data.addRows([
['Visits', $visits],
['Unique Visits', $unique],
]);

// Set chart options for day stats
var options = {'title':'Your total site visits for the Day',
'is3D':true,
'width':400,
'height':300};

// Create the data table for day stats
var data_month = new google.visualization.DataTable();
data_month.addColumn('string', 'Visits');
data_month.addColumn('number', 'Total Visits');
data_month.addRows([
['Visits', $visitsm],
['Unique Visits', $uniquem],
]);

// Set chart options for day stats
var options_month = {'title':'Your total site visits for the Month',
'is3D':true,
'width':400,
'height':300};

// Instantiate and draw our chart, passing in some options.
var chart = new google.visualization.BarChart(document.getElementById('chart_div'));
chart.draw(data, options);

// Instantiate and draw our chart, passing in some options.
var chart_month = new google.visualization.BarChart(document.getElementById('chart_month_div'));
chart_month.draw(data, options);
}
</script>";

}

Here we did two queries, one to get the daily stats and one to get the monthly stats. We then echoed our JavaScript to display the charts data.

STEP 7

Next we create the functions and action to add our stats chart data to our dashboard.

// Create the function to output the contents of our Dashboard Widget

function zkr_dashboard_widget_function() {
// Display whatever it is you want to show
echo "<h2>Daily Stats</h2><div id='chart_div'></div><h2>Monthly Stats</h2><div id='chart_month_div'></div>";
}

// Create the function use in the action hook

function zkr_add_dashboard_widgets() {
wp_add_dashboard_widget('zkr_dashboard_widget', 'Simple Stats', 'zkr_dashboard_widget_function');
}

// Hook into the 'wp_dashboard_setup' action to register our other functions

add_action('wp_dashboard_setup', 'zkr_add_dashboard_widgets' );

That’s it you have just written your own simple stats plugin, but if you don’t want to go through all that trouble in coding you can download the plugin.

Demo Link

Related Posts:

  • rss
  • email
  • rss
  • email
I'm a full time PHP developer and I just love all things web related. If you need help I'm your guy.

8 Responses to WordPress Stats: Create A Simple Stats Plugin For Your Site

  1. KolorGuild says:

    Thanks for this. It’s really helpful to see how easy it is to set up a basic stat plugin. BTW I caught an error in your code. You initiated the daily stat twice instead of the month. I fixed it on my version but you might want to correct it here for future questions. :)

  2. Morné says:

    Hi, thanks for letting me know I will fix it. :) Glad you like it. Look out for some future posts and please retweet and share the tutorial.

  3. kainam2014 says:

    Best tutorial of its kind – been looking for something like this for a while! Thanks!

    Quick question i just installed your demo plugin and it’s showing 2 similar errors:

    Warning: Missing argument 2 for wpdb::prepare(), called in /public_html/wp-content/plugins/zooker-simple-stats/stats.php
    on line 145 and defined in /public_html/wp-includes/wp-db.php on line 992

    Warning: Missing argument 2 for wpdb::prepare(), called in /public_html/wp-content/plugins/zooker-simple-stats/stats.php
    on line 149 and defined in /public_html/wp-includes/wp-db.php on line 992

    I did some research to try and debug the issue and it looks to be related to a change in the wpdb::prepare() function that came about in WordPress 3.5

    Source: http://make.wordpress.org/core/2012/12/12/php-warning-missing-argument-2-for-wpdb-prepare/

    Have tried to reformat it following that post but am doing something wrong – any pointers greatly appreciated!

  4. Morné says:

    Hi there,

    Thanks for pointing it out. I did write this quite a while back. Will see if I can update this for you to work with the latest version of WordPress.

    Chat soon.

  5. kainam2014 says:

    hi i tried a few things and replaced $wpdb->prepare with esc_sql – it seemed to do the trick!

    Let me know if that’s not the best way to implement a fix – this has been a great tutorial, coming across this minor error message has lead me to read up more on $wpdb->prepare! Good stuff!

  6. Morné says:

    Thanks for the kind words :) I’m writing some more tutorials to add on the site in future. Currently working on a tutorial to build a mobile android app using PhoneGap.

    The App will communicate with WordPress to get the latest tutorials and so on.

    Follow me on Google Plus https://plus.google.com/+Morn%C3%A9ZeelieTY

    And Like the Facebook page here https://www.facebook.com/teachingyou

    I’m trying to more time to write more useful tutorials, frequently.

    Thanks again for the comment.

    Will try and update the code on this page tomorrow.

  7. kainam2014 says:

    Good stuff look forward to the new tutorials

    Am playing around with this plugin right now trying to better understand it – trying to break down what each $wpdb call does.

    Where you use the DATE( TIMESTAMP ) = DATE( NOW( ) ) how does that determine the current month am not familiar with that usage? Any pointers greatly appreciated!

    Thanks in advance!

  8. Morné says:

    Basically what I’m doing is I’m comparing the date within the timestamp field with the current date to get the difference between the date in the database and the today (current) date.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>