How to Write a “Most Popular By Views” WordPress Plugin

How to Write a “Most Popular By Views” WordPress Plugin

Tutorial Details
  • Program: WordPress
  • Version: 2.5.1+
  • Difficulty: Moderate
  • Estimated Completion Time: 1 hour

As you continue writing for WordPress more and more, the level of difficulty and complexity of your plugins will eventually reach far beyond the simple back-end data manipulation, as demonstrated in our beginner’s article. In this installment we’ll cover in-depth: database interaction, Admin Widgets, and Sidebar Widgets. Today’s example will be a custom built “Most Popular by Views” plugin, which creates an admin area widget for us to view, and a sidebar widget for visitors to see.

Tutorial now on Wptuts+

Step 0. What it’s Gonna Do?

Before we open our IDE or write any code, you should always write out a list of what features your plugin will and will not have (at least in its initial phase, you can always extend later). For our plugin, “Most Popular By Views,” our primary feature is to display a list of the most popular posts (we’ll say, top 10). Secondly, we’ll also put the list in the admin area as a kind of low-tech analytics. Lastly, we’ll give the developers the option to display it anywhere by making it available as a sidebar widget, and via a simple function.

Features:

  • Creates a list of the top ten most popular posts based on views
  • List is displayed in Admin area as a low-tech analytics
  • List is available as both a sidebar widget and function
The finished widgets

Step 1. The Database

Before we can display the most popular posts, we need to gather data about which posts are being viewed and how often, but even before we can do that, we need somewhere to put all that data. Inside of a new plugin file, let’s create a new function (ppbv_create_table) that will check to see if our table exists. If it does not, we’ll create it. Our method of doing this is rather simple; we’ll use $wpdb->get_results to run a SQL statement that checks for a table named “wp_popular_by_views.” If it doesn’t find the table, get_results will return null. If that’s the case, we’ll use $wpdb->query to write in the new table. We run this function every time the plugin is activated.

<?php
/**
 * Plugin Name: Popular Posts by Views
 * Plugin URI: http://net.tutsplus.com
 * Description: Create a widget to show your most popular articles based on views.
 * Version: 1.0
 * Author: Jonathan Wolfe
 * Author URI: http://fire-studios.com
 * License: GPL2
 * .
 * This plugin and its accompanying tutorial are written for Nettuts+ at http://net.tutsplus.com
 * .
 */

global $wpdb; // call global so we can get the database prefix
$ppbv_tablename = $wpdb->prefix.'popular_by_views'; // combine the prefix with our tablename

function ppbv_create_table(){
    global $wpdb, $ppbv_tablename; // call global so we can use them within the function
    $ppbv_table = $wpdb->get_results("SHOW TABLES LIKE '{$ppbv_tablename}'" , ARRAY_N); // returns null if no results
    if(is_null($ppbv_table)){ // if we don't have a table
        $create_table_sql = "CREATE TABLE {$ppbv_tablename} (
            id BIGINT(50) NOT NULL AUTO_INCREMENT, 
            post_id VARCHAR(255) NOT NULL, 
            views BIGINT(50) NOT NULL, 
            PRIMARY KEY (id), 
            UNIQUE (id)
        );"; // be careful with SQL syntax, it can be VERY finiky
        $wpdb->query($create_table_sql); // run the SQL statement on the database
    }
}
register_activation_hook(__FILE__,'ppbv_create_table'); // run the function 'ppbv_create_table' at plugin activation
?>

Step 2. Catching the Data

The next thing we need to do, now that we have a table to store our data, is catch our data. We’ll create a new function (ppbv_page_viewed) that we’ll attach to the wp_head hook so that it’ll run on every page load. Inside this function, we’re going to do one of two things, after we check to see if the current page is already in the database: increase its views by one or, if it’s not in the database, add it to the database. To figure out if the current page is already in the database, we’re going to be using the $post object to get the “post_ID.” This step is actually really simple, because we aren’t collecting any complicated data; the comments in the code provide a detailed step by step in this process.

function ppbv_page_viewed(){
    if(is_single() && !is_page()){ // only run on posts and not pages
        global $wpdb, $post, $ppbv_tablename; // call global for use in funciton
        $wpdb->flush(); // clense the DB interface
        $data = $wpdb->get_row("SELECT * FROM {$ppbv_tablename} WHERE post_id='{$post->ID}'", ARRAY_A); // get the data row that has the matching post ID
        if(!is_null($data)){ // if we have a matching data row
            $new_views = $data['views'] + 1; // increase the views by 1
            $wpdb->query("UPDATE {$ppbv_tablename} SET views='{$new_views}' WHERE post_id='{$post->ID}';"); // update the data row with the new views
            $wpdb->flush(); // clense the DB interface
        }
        else { // if we don't have a matching data row (nobody's viewed the post yet)
            $wpdb->query("INSERT INTO {$ppbv_tablename} (post_id, views) VALUES ('{$post->ID}','1');"); // add a new data row into the DB with the post ID and 1 view
            $wpdb->flush(); // clense the DB interface
        }
    }
}
add_action('wp_head','ppbv_page_viewed'); // attach ppbv_page_viewed to the wp_head hook
Database and views process

Step 3. Creating the Admin Widget

Next up, we’re going to use this data we just added to our database to create an ordered list inside of an Admin Area Dashboard Widget. This process involves two functions: the first (ppbv_admin_widget) to generate everything inside the widget, and second, (ppbv_add_admin_widget) to create the widget itself. Let’s start with the content function, pppbv_admin_widget. Firstly, since we’re making an ordered list, let’s echo out the opening tags for that. Then we’ll globalize the $wpdb and $ppbv_tablename vars so we can access the database and retrieve the ten most viewed post’s IDs. Then we’ll run the returned array through a foreach statement, and use each individual ID to build a list-item and create a link to that page while also printing out its views (formatted with number_format to make it easier to read).

function ppbv_admin_widget(){
    echo "<ol id='popular_by_views_admin_list'>"; // create an unordered list
        global $wpdb, $ppbv_tablename; // call global for use in function
        $popular = $wpdb->get_results("SELECT * FROM {$ppbv_tablename} ORDER BY views DESC LIMIT 0,10",ARRAY_N); // Order our table by largest to smallest views then get the first 10 (i.e. the top 10 most viewed)
        foreach($popular as $post){ // loop through the returned array of popular posts
            $ID = $post[1]; // store the data in a variable to save a few characters and keep the code cleaner
            $views = number_format($post[2]); // number_format adds the commas in the right spots for numbers (ex: 12543 to 12,543)
            $post_url = get_permalink($ID); // get the URL of the current post in the loop
            $title = get_the_title($ID); // get the title of the current post in the loop
            echo "<li><a href='{$post_url}'>{$title}</a> - {$views} views</li>"; // echo out the information in a list-item
        } // end the loop
    echo "</ol>"; // close out the unordered list
}

Now that we’re generating content, let’s create the widget. Inside the creation function, ppbv_add_admin_widget, we’re going to call another function native to WordPress: wp_add_dashboard_widget. All we need to do is give wp_add_dashboard_widget the following parameters: [id of the container], [title in the container], [content function] (ours fills as such: ‘popular_by_views’, ‘Most Popular Posts by Views’, ‘ppbv_admin_widget’). The last thing we need to do is attach our creation function to the wp_dashboard_setup hook.

function ppbv_add_admin_widget(){
    wp_add_dashboard_widget('popular_by_views', 'Most Popular Posts by Views', 'ppbv_admin_widget'); // creates an admin area widget || wp_add_dashboard_widget([id of div],[title in div],[function to run inside of div])
}
add_action('wp_dashboard_setup','ppbv_add_admin_widget'); // attach ppbv_add_admin_widget to wp_dashboard_setup

And now we have a working dashboard widget for administraitors to see.

Admin Dashboard Widget

Step 4. Creating the Sidebar Widget

Creating a sidebar widget is fairly painless; unfortunately, certain parts aren’t documented well (like how to make them uniform), but we’ll cover that. Let’s start by writing a new function (ppbv_display_widget) and, inside of it, we’ll carbon copy our content function from the admin widget (I suggest moving the global calls to the top, outside the <ol> echo, of the function for clarity later on). Then the next step is to register our widget in WordPress via wp_register_sidebar_widget (parameters are: [id of the container],[title on the widget page],[content function] || ‘popular_by_views’, ‘Most Popular Posts by Views’, ‘ppbv_display_widget’).

function ppbv_display_widget() {
    global $wpdb, $ppbv_tablename; // call global for use in function
    
    echo "<div id='popular_by_views'>"; // create a container
        echo "<h2>Most Popular by Views</h2>"; // write the title
        echo "<ol id='popular_by_views_list'>"; // create an ordered list
            $popular = $wpdb->get_results("SELECT * FROM {$ppbv_tablename} ORDER BY views DESC LIMIT 0,10",ARRAY_N);
            foreach($popular as $post){ // loop through the returned array of popular posts
                $ID = $post[1]; // store the data in a variable to save a few characters and keep the code cleaner
                $views = number_format($post[2]); // number_format adds the commas in the right spots for numbers (ex: 12543 to 12,543)
                $post_url = get_permalink($ID); // get the URL of the current post in the loop
                $title = get_the_title($ID); // get the title of the current post in the loop
                echo "<li><a href='{$post_url}'>{$title}</a> - {$views} views</li>"; // echo out the information in a list-item
            } // end the loop
        echo "</ol>"; // close the ordered list
    echo "</div>"; // close the container
}
wp_register_sidebar_widget('popular_by_views', 'Most Popular Posts by Views', 'ppbv_display_widget'); // add the widget to the select menu || wp_register_sidebar_widget([id of the option],[title of the option],[function to run from the widget]))

This is actually the bare-minimum you need to do for a sidebar widget, but what 90% of all dynamic sidebars have certain settings applied about how widgets are styled, so let’s conform our widget to those settings. The first thing we need to do is add in a parameter to our ppbv_display_widget function, $args. By adding this parameter inside the function, using the extract function on it, we gain access to several variables which will allow our plugin to be styled the same as the rest of the widgets in the sidebar.

“We don’t need to provide any input for $args, WordPress will do that for us.”

Thanks to $args and extract, we now have access to the following variables that we can echo to style our widget:

  • $before_widget
  • $after_widget
  • $before_title
  • $after_title
function ppbv_display_widget($args){
    global $wpdb, $ppbv_tablename; // call global for use in function
    extract($args); // gives us the default settings of widgets
    
    echo $before_widget; // echos the container for the widget || obtained from $args
        echo $before_title."Most Popular by Views".$after_title; // echos the title of the widget || $before_title/$after_title obtained from $args
        echo "<ol id='popular_by_views_list'>"; // create an ordered list
            $popular = $wpdb->get_results("SELECT * FROM {$ppbv_tablename} ORDER BY views DESC LIMIT 0,10",ARRAY_N); // Order our table by largest to smallest views then get the first 10 (i.e. the top 10 most viewed)
            foreach($popular as $post){ // loop through the returned array of popular posts
                $ID = $post[1]; // store the data in a variable to save a few characters and keep the code cleaner
                $views = number_format($post[2]); // number_format adds the commas in the right spots for numbers (ex: 12543 to 12,543)
                $post_url = get_permalink($ID); // get the URL of the current post in the loop
                $title = get_the_title($ID); // get the title of the current post in the loop
                echo "<li><a href='{$post_url}'>{$title}</a> - {$views} views</li>"; // echo out the information in a list-item
            } // end the loop
        echo "</ol>"; // close the ordered list
    echo $after_widget; // close the container || obtained from $args
}
Sidebar Widget

Step 5. The Non-widget Function

Not everybody who uses this plugin is going to want to use the widget, so it’s imperative that we provide them with another method of displaying our list. Thankfully, that’s as simple as cloning our ppbv_display_widget function and removing the widget parts, replacing them with standard hardcoded HTML.

function ppbv_display() {
    global $wpdb, $ppbv_tablename; // call global for use in function
    
    echo "<div id='popular_by_views'>"; // create a container
        echo "<h2>Most Popular by Views</h2>"; // write the title
        echo "<ol id='popular_by_views_list'>"; // create an ordered list
            $popular = $wpdb->get_results("SELECT * FROM {$ppbv_tablename} ORDER BY views DESC LIMIT 0,10",ARRAY_N);
            foreach($popular as $post){ // loop through the returned array of popular posts
                $ID = $post[1]; // store the data in a variable to save a few characters and keep the code cleaner
                $views = number_format($post[2]); // number_format adds the commas in the right spots for numbers (ex: 12543 to 12,543)
                $post_url = get_permalink($ID); // get the URL of the current post in the loop
                $title = get_the_title($ID); // get the title of the current post in the loop
                echo "<li><a href='{$post_url}'>{$title}</a> - {$views} views</li>"; // echo out the information in a list-item
            } // end the loop
        echo "</ol>"; // close the ordered list
    echo "</div>"; // close the container
}

Conclusion

That’s it guys, you’ve successfully made your very own “Most Popular by Views” WordPress plugin. Not too hard, was it?

When you’ve mastered the art of WordPress plugin development, stop by CodeCanyon.net and begin selling your plugins for profit!

View Final Source Code with Commenting?

<?php
/**
 * Plugin Name: Popular Posts by Views
 * Plugin URI: http://net.tutsplus.com
 * Description: Create a widget to show your most popular articles bassed on views.
 * Version: 1.0
 * Author: Jonathan Wolfe
 * Author URI: http://fire-studios.com
 * License: GPL2
 * .
 * This plugin and it's accompanying tutorial are written for NETTUTS at http://net.tutsplus.com
 * .
 */

global $wpdb; // call global so we can get the database prefix
$ppbv_tablename = $wpdb->prefix.'popular_by_views'; // combine the prefix with our tablename

function ppbv_create_table(){
    global $wpdb, $ppbv_tablename; // call global so we can use them within the function
    $ppbv_table = $wpdb->get_results("SHOW TABLES LIKE '{$ppbv_tablename}'" , ARRAY_N); // returns null if no results
    if(is_null($ppbv_table)){ // if we don't have a table
        $create_table_sql = "CREATE TABLE {$ppbv_tablename} (
            id BIGINT(50) NOT NULL AUTO_INCREMENT, 
            post_id VARCHAR(255) NOT NULL, 
            views BIGINT(50) NOT NULL, 
            PRIMARY KEY (id), 
            UNIQUE (id)
        );"; // be careful with SQL syntax, it can be VERY finiky
        $wpdb->query($create_table_sql); // run the SQL statement on the database
        $wpdb->flush(); // clense the DB interface
    }
}
register_activation_hook(__FILE__,'ppbv_create_table'); // run the function 'ppbv_create_table' at plugin activation

function ppbv_page_viewed(){
    if(is_single() && !is_page()){ // only run on posts and not pages
        global $wpdb, $post, $ppbv_tablename; // call global for use in funciton
        $wpdb->flush(); // clense the DB interface
        $data = $wpdb->get_row("SELECT * FROM {$ppbv_tablename} WHERE post_id='{$post->ID}'", ARRAY_A); // get the data row that has the matching post ID
        if(!is_null($data)){ // if we have a matching data row
            $new_views = $data['views'] + 1; // increase the views by 1
            $wpdb->query("UPDATE {$ppbv_tablename} SET views='{$new_views}' WHERE post_id='{$post->ID}';"); // update the data row with the new views
            $wpdb->flush(); // clense the DB interface
        }
        else { // if we don't have a matching data row (nobody's viewed the post yet)
            $wpdb->query("INSERT INTO {$ppbv_tablename} (post_id, views) VALUES ('{$post->ID}','1');"); // add a new data row into the DB with the post ID and 1 view
            $wpdb->flush(); // clense the DB interface
        }
    }
}
add_action('wp_head','ppbv_page_viewed'); // attach ppbv_page_viewed to the wp_head hook

function ppbv_admin_widget(){
    echo "<ol id='popular_by_views_admin_list'>"; // create an unordered list
        global $wpdb, $ppbv_tablename; // call global for use in function
        $popular = $wpdb->get_results("SELECT * FROM {$ppbv_tablename} ORDER BY views DESC LIMIT 0,10",ARRAY_N); // Order our table by largest to smallest views then get the first 10 (i.e. the top 10 most viewed)
        foreach($popular as $post){ // loop through the returned array of popular posts
            $ID = $post[1]; // store the data in a variable to save a few characters and keep the code cleaner
            $views = number_format($post[2]); // number_format adds the commas in the right spots for numbers (ex: 12543 to 12,543)
            $post_url = get_permalink($ID); // get the URL of the current post in the loop
            $title = get_the_title($ID); // get the title of the current post in the loop
            echo "<li><a href='{$post_url}'>{$title}</a> - {$views} views</li>"; // echo out the information in a list-item
        } // end the loop
    echo "</ol>"; // close out the unordered list
}
function ppbv_add_admin_widget(){
    wp_add_dashboard_widget('popular_by_views', 'Most Popular Posts by Views', 'ppbv_admin_widget'); // creates an admin area widget || wp_add_dashboard_widget([id of div],[title in div],[function to run inside of div])
}
add_action('wp_dashboard_setup','ppbv_add_admin_widget'); // attach ppbv_add_admin_widget to wp_dashboard_setup

function ppbv_display_widget($args){
    global $wpdb, $ppbv_tablename; // call global for use in function
    extract($args); // gives us the default settings of widgets
    
    echo $before_widget; // echos the container for the widget || obtained from $args
        echo $before_title."Most Popular by Views".$after_title; // echos the title of the widget || $before_title/$after_title obtained from $args
        echo "<ol id='popular_by_views_list'>"; // create an ordered list
            $popular = $wpdb->get_results("SELECT * FROM {$ppbv_tablename} ORDER BY views DESC LIMIT 0,10",ARRAY_N); // Order our table by largest to smallest views then get the first 10 (i.e. the top 10 most viewed)
            foreach($popular as $post){ // loop through the returned array of popular posts
                $ID = $post[1]; // store the data in a variable to save a few characters and keep the code cleaner
                $views = number_format($post[2]); // number_format adds the commas in the right spots for numbers (ex: 12543 to 12,543)
                $post_url = get_permalink($ID); // get the URL of the current post in the loop
                $title = get_the_title($ID); // get the title of the current post in the loop
                echo "<li><a href='{$post_url}'>{$title}</a> - {$views} views</li>"; // echo out the information in a list-item
            } // end the loop
        echo "</ol>"; // close the ordered list
    echo $after_widget; // close the container || obtained from $args
}
wp_register_sidebar_widget('popular_by_views', 'Most Popular Posts by Views', 'ppbv_display_widget'); // add the widget to the select menu || wp_register_sidebar_widget([id of the option],[title of the option],[function to run from the widget]))

function ppbv_display() {
    global $wpdb, $ppbv_tablename; // call global for use in function
    
    echo "<div id='popular_by_views'>"; // create a container
        echo "<h2>Most Popular by Views</h2>"; // write the title
        echo "<ol id='popular_by_views_list'>"; // create an ordered list
            $popular = $wpdb->get_results("SELECT * FROM {$ppbv_tablename} ORDER BY views DESC LIMIT 0,10",ARRAY_N);
            foreach($popular as $post){ // loop through the returned array of popular posts
                $ID = $post[1]; // store the data in a variable to save a few characters and keep the code cleaner
                $views = number_format($post[2]); // number_format adds the commas in the right spots for numbers (ex: 12543 to 12,543)
                $post_url = get_permalink($ID); // get the URL of the current post in the loop
                $title = get_the_title($ID); // get the title of the current post in the loop
                echo "<li><a href='{$post_url}'>{$title}</a> - {$views} views</li>"; // echo out the information in a list-item
            } // end the loop
        echo "</ol>"; // close the ordered list
    echo "</div>"; // close the container
}
?>
Note: Want to add some source code? Type <pre><code> before it and </code></pre> after it. Find out more
  • Melissa joyce

    such a useful tutorial. it discloses the every steps in a simple manner .i like it very much

  • http://www.scottcorgan.com Scott Corgan

    Looks handy to me. Stoked now that WordPress 3.0 is out!

    • http://www.code-pal.com Sumeet Chawla

      OMG Thanks Scott for that ground breaking news… lol.. I downloaded wordpress around 4 hours ago and there wasn’t any 3.0 then… now it is! yay :D

  • http://www.code-pal.com Sumeet Chawla

    Ah ha! Finally this comes out… I have been waiting for this one for a very long time.. The last I managed to do was how to display the most popular posts using the number of comments feature but not views… A very useful article (to me) after ages!! :D Thanks for sharing…

  • http://www.movieviews.be Dennis

    Thank you !
    Very interesting !

  • http://d4b.com.pl d4b

    Counts custom post types ?

  • http://bentrem.sycks.net Ben Tremblay

    Fabulous … foundational … great to see folk writing such solid tutorials.
    –@bentrem

    p.s. we should agree on a HastTag … something like #StokedOnWP3 *g*

  • http://magplazza.com Mike

    Now I knows how to set up a basic WordPress plug-ins. Thank you for the post :)

  • http://solith.com.pl Krzysiek Dróżdż

    Nice, but… How about some db transactions and speed? Isn’t it so, that every child knows that incrementing in SQL should be done like this:

    $wpdb->query(“UPDATE {$ppbv_tablename} SET views=views+1 WHERE post_id=’{$post->ID}’;”);

    ?

    And… Wouldn’t it be nicer, if you insert some row into this table every time you add new post. In such case you could assume that this row exists in this table and you wouldn’t have to check that. You would use only one query instead of two. But who cares, right?

  • http://www.quizzpot.com Crysfel

    Thanks for share! this is good :)

  • http://wpcanyon.com Boba

    Two weeks ago a client needed the same thing. But i made it using a custom field for the number of views, creating a special table just to count number of views seems kind of unnecessary (anybody agrees?).

    Nice tut anyway, thanks :)

  • http://www.obenlands.de Konstantin

    Do you really need to create a table for this? Can’t you use post_meta??
    This is what the API is for!

  • http://somadesign.ca/ Matt Wiebe

    As Konstantin said, this example plugin is taking a wrong approach for working with WordPress. Use the native API wherever possible. In this case, the post_meta API should be used rather than creating a completely unnecessary table.

    • http://fire-studios.com Jonathan Wolfe
      Author

      The table is needed for the later tutorial.

      • http://somadesign.ca/ Matt Wiebe

        The table is only needed because you use it, not because it’s necessary. You should be using update_post_meta() and get_post_meta() instead.

      • http://frankiejarrett.com Frankie

        I love the concept of this plugin but it’s true…using the API is the preferred method.

        Can anyone give us an example of this tut modified to use the post_meta API?

        //Frankie

  • http://tipsforwordpress.com weston deboer

    as everyone above has said, unnecessary need for a table. This could be done much easier with an update_post_meta http://codex.wordpress.org/Function_Reference/update_post_meta which makes it easier to grab said information also.

  • http://www.onyxsolution.com OnYx

    Pretty interesting approach.. would have to give it a try and see how to take it to another level..

  • http://www.privilegedsoftware.com Website Design Lincolnshire

    This is a great contribution to the WordPress community, thank you for sharing.

  • http://pariwar.info Bali

    Nice article….

    Is there any script which remove table when we uninstall or remove this plugins from blog…… I just need a information or tricks or tips…. :)

  • pat

    Nice Tutorial, Cheers!

    However I couldn’t get the table to be created. Once I did it manually everything worked fine. Anyone else have issues with this? Checked my db privileges and everythings fine there.

    Does anyone have tips for troubleshooting this sort of thing? eg how can you echo out an sql query or check if a function call has been made when using hooks and actions?

    Anyways,

    Thanks again for a great tutorial!

    • http://twitter.com/netjunky88 Eugene

      +1. Same problem here. Script doesn’t create table and gives error on dashboard panel. Don’t know how to debug this sort of thing.

      Tutorial is great by the way.

    • http://twitter.com/netjunky88 Eugene

      I even tried to comment everything out and change CREATE statement to CREATE TABLE IF NOT EXISTS. Still didn’t help.

  • http://www.blim.us Marcel Rieger

    I think I just like to use the Custom Fields than create another table…

  • http://www.blogmi.be Ruben

    Attention:

    Who uses this plugins or something like this and WP Super Cache => Super Cache stores the views and after a certain time the views are send through the super cache script and inserted into the database.

    A lot of hosting is limited (php scripts) to 8 MB (buffer memory).
    When the load for the views in this script is too high, the website will crash.

  • http://www.kapkoi.tk aziq

    This looks cool.Gonna try it with my new theme.Nice post btw.

  • http://www.designfromwithin.com ThaClown

    mmm, doenst seem to work for me, the plugin & widgest is showing but I do not see any posts there..

    Should I do anything in the database or change any code?

  • http://www.designfromwithin.com ThaClown

    Do I need to change the
    global $wpdb;
    ??

  • http://www.cere.be Cerebral

    Or just use the existing Top 10 plugin http://wordpress.org/extend/plugins/top-10/

  • http://wordpress.tempelatos.com xychazs

    mmm.. @Thaclown. Does not seem to work for me too. I allready installed and activated the plugin and put it (as widget) on sidebar. Only titles which appear on the main page and the admin panel.

    What’s wrong with my..?

  • http://www.cairnslogo.com.au Cairns Logo

    I like these articles, I am just starting to learn how to program in wordpress. I think it is always good to know how these things work instead of just using other plugins all the time.

  • Brian

    But don’t all these post views solutions mentioned, (this tutorial, using post_meta, a plugin like Top-10) all have the same shortcoming?? The issue that someone could potentially sit there and refresh their browser over and over skewing the results??

  • Andy

    Very use full tutorial.

  • http://r6media.com ravi

    Thanks for sharing this great post!

  • http://www.johnathoncorbin.com Johnathon

    Very nice tutorial on writing a plugin; definitely one of the most comprehensive in terms of SQL administration in WP development. Very, very nice addition to the tutsplus series.

  • http://wedesignapps.com/register Christopher Chance

    I agree that someone could refresh the page over and over and make the number of pageviews higher. But what is the point in doing that. Google and other search engines regularly index every page and do not care much about pageviews – more emphasis is laid on incoming and outgoing links. Thsi is just a fancy thing we can do to extend the database features of WordPress. How useful this plugin will be is entirely debatable.

    I installed the plugin in one of my sites via ftp and it seems to be working (looks like I don’t have enough page views yet). Check it out here:

    http://wedesignapps.com

  • http://eyoosuf.com Yoosuf

    awesome post as well as cool plugin

  • http://www.illogicdesign.com Seth Etter

    Great post! Plugin development is the next stage in the WordPress universe that I’m venturing into, so this tutorial was a great help. Thanks as always!

  • Nick

    In WP3, line 21 doesn’t work correctly. $wpdb->get_results(“”, ARRAY_N) returns an empty array on no results, not null. So line 21 will always return “FALSE” and the table will never be created.

    Perhaps using empty() would work better, unless I’m mistaken.

    • http://www.zhkzyth.com zhkzyth

      ye…the statement doesn’t work…does anyone know how to fix it?

      • http://www.e-mex.nl Fynn

        Late response, but I’m just doing this right now tut :p

        Anyway, for people who still are doing this tut;

        - At the first line of the script, change:
        global $wpdb; into global $wpdb, $ppbv_tablename;

        Now it should work :)

  • dan

    great tut.

  • http://screamwork.hostzi.com scw

    Hi,
    @ ThaClown:
    i declared ‘$ppbv_tablename’ outside the function global too.
    and behind the create-syntax is one ‘;’ too much..
    also changed ‘is_null’ to ‘!’ don’T know if this is necessary, anyway,
    now it works…

  • http://sandacreative.com Anoop D

    Hi,
    Thanks a lot for such a great tutorial….. was trying to get a solution for popularity based on number of views .. this was so timely thing for me .. thank you once more

    • http://sandacreative.com Anoop D

      Seems there is some problem with latest wordpress (3) … it is not working … anyway i am going through it …:)

  • http://www.praveeng.com/ arjun

    really great post…………..

  • nimesh

    really good one. hope you will do advanced version of plugin creation post.thanks

  • http://www.wealthcity.in Ajmal

    Its wonderful to find this simple tutorial… But I am stuck with one issue now..

    This plugin ” most popular by views ” in other words most viewed show most read ages in a site

    In a news site, where content is udated every day, usually what we would need is ” most read on a weekly / monthly basis ”

    Would want guidance a bit of code on how it can be achieved.. thanks a lot..

  • http://giacaphe.com/ Y5cafe

    I have got a problem with caching :(

  • http://bloggertemplateshub.com Franklin Manuel

    A well explained tutorial. I was searching for it from the last week and finally I got it here.

  • cardsmoney

    in WP3 plugin doesnt work..
    I used readers receipts, but its still doesn’t work..
    see first function

    global $wpdb, $ppbv_tablename;
    $ppbv_tablename = $wpdb->prefix.’popular_by_views’;
    function ppbv_create_table(){
    $ppbv_table = $wpdb->get_results(“SHOW TABLES LIKE ‘{$ppbv_tablename}’” , ARRAY_N);
    if(!($ppbv_table)){
    $create_table_sql = “CREATE TABLE {$ppbv_tablename} (
    id BIGINT(50) NOT NULL AUTO_INCREMENT,
    post_id VARCHAR(255) NOT NULL,
    views BIGINT(50) NOT NULL,
    PRIMARY KEY (id),
    UNIQUE (id)
    )”;
    $wpdb->query($create_table_sql);
    $wpdb->flush();
    }
    }
    register_activation_hook(__FILE__,’ppbv_create_table’); // run the function ‘ppbv_create_table’ at plugin activation

    …..

    what is my mistake?

  • http://www.mexzhouse.com max

    nice most. is there a way write most popular post without plugin?

  • http://www.yeahthatapp.com Bioshox

    Nice tutorial, I’ll have to look into trying it and customizing it a little, see what I can come up with!

  • Dejan

    Yeap, just another notice – this plugin isn’t working on WP3+

  • Jordan

    Hi, the plugin looks nice and clear. But i think it doen’s work for WordPress v3.0.5
    Seems can’t create database table…
    Wish you all the best!

  • http://www.wpfixes.com wpfixes

    Database fix for WP 3.x

    global $wpdb, $ppbv_tablename; // call global so we can get the database prefix
    $ppbv_tablename = $wpdb->prefix . ‘popular_by_views’; // combine the prefix with our tablename

    function ppbv_create_table(){
    global $wpdb, $ppbv_tablename; // call global so we can use them within the function
    if ($wpdb->get_var(“show tables like ‘$ppbv_table’”) != $ppbv_table) {
    $create_table_sql = “CREATE TABLE {$ppbv_tablename} (
    id BIGINT(50) NOT NULL AUTO_INCREMENT,
    post_id VARCHAR(255) NOT NULL,
    views BIGINT(50) NOT NULL,
    PRIMARY KEY (id),
    UNIQUE (id)
    );”; // be careful with SQL syntax, it can be VERY finiky
    $wpdb->query($create_table_sql); // run the SQL statement on the database
    $wpdb->flush(); // clense the DB interface
    }
    }
    register_activation_hook(__FILE__,’ppbv_create_table’); // run the function ‘ppbv_create_table’ at plugin activation

    • http://twitter.com/milanstosic Milan Stošić

      Thanks!

  • Hiren

    It is very useful and in very proper format, i am really thankful………..

  • http://kovshenin.com Konstantin

    Sweet, but hey, this might break together with a caching plugin, and you’re creating a table to store views, I’d rather store them in my post meta and get rid of the nasty SQL. It’ll be very easy to fetch using the new meta_query feature in 3.1 for WP_Query, but anyways, nice tutorial! Well done!

    Also, consider using the Google Analytics API to gather your most popular posts, daily, monthly, weekly or whatever.. Just a theory, never tried it myself but I know you can, ’cause I got an app on my Android showing my stats as a widget on my home screen ;)

    Cheers!
    ~ @kovshenin

  • http://myafternoontea.com David

    I think the SQL is good for catching the data. I read another tutorial using get_post_meta at http://wpsnipp.com/index.php/functions-php/track-post-views-without-a-plugin-using-post-meta/.
    But it has a problem for catching the data.

  • http://worldcruiseholidays.com David

    Oops… I meant caching not catching :)

  • http://www.lvzidan.org/ 绿子弹

    great tutorial. i’ve installed the plugin in WordPress but i got nothing, seems that someting is wrong.i guess the “creating table” is not working.

  • http://teenvip24h.com hieu

    thanks ! very much

  • http://thisismyurl.com Christopher Ross

    A wonderful and very straight forward tutorial but creating a custom table for this seems rather against the grain, especially when WordPress gives so many excellent options for saving the data internally.

    Wouldn’t it have been better to use either the set_options() with a JSON’d array or even to store it in the post table as a Custom Post Type? That’s what I did with the Easy Popular Posts plugin and it’s always worked well.

  • http://adthomesecuritysystemshainescity| Delmar Scholin

    Right now it looks like Drupal is the preferred blogging platform out there right now. (from what I’ve read) Is that what you are using on your blog? Thanks!

  • http://ulife.com Jim Cordova

    I have a question regarding this plugin, how to I add thumbnail(has_post_thumbnail) into the code.

    Thanks

  • http://hinok.net hinok

    If you use plugin, add this lines of code for remove row from ppbv_table, when post will be removed.

    add_action( ‘delete_post’, ‘ppbv_remove_row’, 10 );
    function ppbv_remove_row( $post_id ) {

    global $wpdb, $ppbv_tablename;

    return $wpdb->query(
    $wpdb->prepare( “DELETE FROM {$ppbv_tablename} WHERE post_id = ‘%d’”, $post_id )
    );

    }

    • http://twitter.com/milanstosic Milan Stošić

      This is great but this only deletes post from table when post is permanently deleted, if it’s in the Trash it is not deleted and can be still clicked in popular articels list.

      Is there any WP function that can change status on trash action? Maybe altering table with some status field (0 – active and 1 – deleted), but this requires changes to all previous queries and adding this param in where clause.

  • Phill

    It doesnt work on wp3.3. comment can’t help , too

    • http://www.slowmedia.it Mattia

      I have the same problem. Perhaps someone can help us… Thanks

  • http://klik-sekali.blogspot.com Kando

    nice widget..
    but could it work in blogspot…
    can you convert it to blogspot?

  • Adrian Gudra

    Hey, we need a plugin that orders posts by popularity and therefore are looking for a freelance developer. If interested, give me an email on a.gudra@lse.ac.uk.

    Best,
    Adrian

  • http://www.geoffreyhale.com/ Geoffrey Hale

    Yikes, too tech-heavy for me at the moment. Maybe someday. Thanks for the brain food.

  • http://www.webrewired.com/ Gravity

    Thank you so much guys, I was working on a theme job and wanted to add a widget for popular posts and this tut did a fantastic job. Great!

  • http://feed2.me David

    You’re setting `id` as the primary key then you assign it as unique? Isn’t that redundant since the primary key never gets repeated.

  • http://www.ariona.net Rian Ariona

    What if I want to show most popular post by views that based on Jetpack Stats?

  • http://www.facebook.com/shala.burim Burim A. Shala

    I would rather do that, i think the optimal and the best way is to use POST Meta.On each post request you can store a meta and than you can use WP QUERY and sort posts based on that Meta.And it does not need to create another Database + The user can import posts and their Views also on another WordPress Installation.

  • arie suma

    how to display this shot view cont for specific member/author post?? this possible?
    thank..