How to Create a Simple Post Rating System With WordPress and jQuery

There already are many post rating system plugins out there. Surprisingly, no one fits my needs, they either are too complicated or with too many built-in options. So, in this tutorial, you’ll learn how to build your own simple post rating functionality, directly within your theme files. There’s no need for plugin!

Step 1 Introduction

Post ratings are a good way to get feedback on what your readers really focus on. While I was searching for a simple yet efficient plugin, I realized they all come with too many options and aren’t customizable enough. That was my first issue. My second issue was that using too many plugins will slow WordPress down.

So I decided to share with you a way to build your custom post ratings system. We’ll use:

  • simple HTML markup and CSS3 so it’s easy to customize
  • jQuery to deal with Ajax calls
  • PHP and hooks to handle data

Step 2 HTML Markup

We are going to display a heart-shaped button in the footer section of an article. To do so, we’ll add markup in the content-single.php file (within the Twenty Eleven theme).

<p class="post-like">
	<a data-post_id="POST_ID" href="#">
		<span class="qtip like" title="I like this article"></span>
	<span class="count">POST_LIKES_COUNT</span>

Note that we use HTML5 custom meta attributes to store our data so it’s really easy to handle with jQuery. Then, this will be generated by PHP, as we’ll see in a next step.

Step 3 CSS3

We’ll use CSS3 animations to add some visual interactivity and CSS sprites to reduce the number of external images.

article footer  .post-like{

article footer .like{
	background:url(images/icons.png) no-repeat;
	width: 15px;
	height: 16px;
	display: block;
	margin-right: 4px;
	-moz-transition: all 0.2s ease-out 0.1s;
	-webkit-transition: all 0.2s ease-out 0.1s;
	-o-transition: all 0.2s ease-out 0.1s

article footer .post-like a:hover .like{
	background-position:-16px 0;

article footer .voted .like, article footer .post-like.alreadyvoted{
	background-position:-32px 0;

At this point, it should looks like this

Post Rating

Step 4 jQuery

We’ll use built-in jQuery to handle the ajax requests. On click, jQuery will pass some parameters to our php handler and handle the response to display suitable information.

So let’s create a new file called post-like.js and add it to the js folder. Then open it and add this code:

jQuery(document).ready(function() {

	jQuery(".post-like a").click(function(){

		heart = jQuery(this);

		// Retrieve post ID from data attribute
		post_id ="post_id");

		// Ajax call
			type: "post",
			url: ajax_var.url,
			data: "action=post-like&nonce="+ajax_var.nonce+"&post_like=&post_id="+post_id,
			success: function(count){
				// If vote successful
				if(count != "already")

		return false;


First, let’s retrieve the post ID with jQuery’s data method and then pass it to our PHP handler. The ajax_var variable is created dynamically with PHP (we’ll cover this in the next section).

The best way to use ajax within WordPress is to make calls to admin-ajax.php. It is located in the wp-admin folder and you can bind your callback functions with hooks. Let’s see how it works.

Step 5 PHP and Hooks

How are we going to proceed? We are going to bind some functions to WordPress hooks and then enqueue our script and add some PHP-generated JavaScript variables to be used by jQuery.


Let’s open the functions.php file and get started adding our functions.

First things first, we need to bind functions to WordPress hooks. So add these two lines in your file:

add_action('wp_ajax_nopriv_post-like', 'post_like');
add_action('wp_ajax_post-like', 'post_like');

The first hook is fired when a user is logged in and the other when they are not. See more information about how to implement ajax the right way here: 5 tips for using ajax in WordPress.

You can see the “post-like” part of the hook, which is the action parameter we used in the previous step with jQuery.

Now we’ll enqueue our script and declare our variables:

wp_enqueue_script('like_post', get_template_directory_uri().'/js/post-like.js', array('jquery'), '1.0', true );
wp_localize_script('like_post', 'ajax_var', array(
	'url' => admin_url('admin-ajax.php'),
	'nonce' => wp_create_nonce('ajax-nonce')

Here, we define two important parameters:

  • url: the complete URI to admin-ajax.php location
  • nonce: a security hash to prevent attacks and mistakes

You can use those parameters with jQuery this way: ajax_var.url and ajax_var.nonce.

“Using WordPress hooks and admin-ajax.php is the safer way to deal with Ajax.”


Let’s add the post_like function. It will:

  • Check nonce
  • Retrieve post ID, user’s IP and custom post metas
  • Check if the user has already voted or not
  • Save data (IP + votes count) for the current post
  • Return the count value to jQuery
function post_like()
	// Check for nonce security
	$nonce = $_POST['nonce'];

    if ( ! wp_verify_nonce( $nonce, 'ajax-nonce' ) )
        die ( 'Busted!');

		// Retrieve user IP address
		$ip = $_SERVER['REMOTE_ADDR'];
		$post_id = $_POST['post_id'];

		// Get voters'IPs for the current post
		$meta_IP = get_post_meta($post_id, "voted_IP");
		$voted_IP = $meta_IP[0];

			$voted_IP = array();

		// Get votes count for the current post
		$meta_count = get_post_meta($post_id, "votes_count", true);

		// Use has already voted ?
			$voted_IP[$ip] = time();

			// Save IP and increase votes count
			update_post_meta($post_id, "voted_IP", $voted_IP);
			update_post_meta($post_id, "votes_count", ++$meta_count);

			// Display count (ie jQuery return value)
			echo $meta_count;
			echo "already";

We are saving the user’s IP and current time into one post_meta and votes count into another one. Time will help us to check if user can revote again after a certain elapsed time.

You could ask what happens when no vote has been recorded for the current post yet? Well, WordPress helps us one more time here, because update_post_meta checks if meta exists and creates it if not (see more information about this function on WordPress codex).

We’ll define how long a user has to wait before voting again (in minutes).

$timebeforerevote = 120; // = 2 hours

This variable could be stored in theme admin panel for instance, so it’s easily editable.

Now add this code to check if the user has already voted:

function hasAlreadyVoted($post_id)
	global $timebeforerevote;

	// Retrieve post votes IPs
	$meta_IP = get_post_meta($post_id, "voted_IP");
	$voted_IP = $meta_IP[0];

		$voted_IP = array();

	// Retrieve current user IP

	// If user has already voted
	if(in_array($ip, array_keys($voted_IP)))
		$time = $voted_IP[$ip];
		$now = time();

		// Compare between current time and vote time
		if(round(($now - $time) / 60) > $timebeforerevote)
			return false;

		return true;

	return false;

“You should always ask yourself if it’s worth using a plugin and slowing down WordPress rather than adding some simple code within your theme.”

Nothing too complicated here, we are just checking if the user has already voted (i.e. his IP address is among votes IP’s list) and if he is allowed to vote again (i.e. elapsed time since he’s voted is greater than $timebeforerevote).

Step 6 Create a Function to Generate the HTML Markup

To get more control over how votes are displayed and make it easy to update if it’s used in different files, we’ll make a function that generates the markup. If the user has already voted, we don’t display the heart as a link to avoid useless ajax calls.

function getPostLikeLink($post_id)
	$themename = "twentyeleven";

	$vote_count = get_post_meta($post_id, "votes_count", true);

	$output = '<p class="post-like">';
		$output .= ' <span title="'.__('I like this article', $themename).'" class="like alreadyvoted"></span>';
		$output .= '<a href="#" data-post_id="'.$post_id.'">
					<span  title="'.__('I like this article', $themename).'"class="qtip like"></span>
	$output .= '<span class="count">'.$vote_count.'</span></p>';

	return $output;

You can replace code inserted in Step 2 with this function:

<?php echo getPostLikeLink(get_the_ID());?>

Step 7 Go Further

Now users can vote on posts, you might like to get feedback. For instance, you could display a top 10 of best rated posts.

To do so, you can use query_post with these options:


Step 7 Conclusion

That’s it! You should now be able to track your posts according to users’ votes and customize both the markup and the CSS to your convenience. This is just one way to create a post rating system, among others, so don’t hesitate to comment on this tutorial and give your feedback. Thank you for reading!

from Wptuts+


Kommentar verfassen

Bitte logge dich mit einer dieser Methoden ein, um deinen Kommentar zu veröffentlichen:

Du kommentierst mit Deinem Abmelden /  Ändern )

Google+ Foto

Du kommentierst mit Deinem Google+-Konto. Abmelden /  Ändern )


Du kommentierst mit Deinem Twitter-Konto. Abmelden /  Ändern )


Du kommentierst mit Deinem Facebook-Konto. Abmelden /  Ändern )


Verbinde mit %s