Try Tuts+ Premium, Get Cash Back!
How to Create a Simple Post Rating System With WordPress and jQuery

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

Tutorial Details
  • Program: WordPress and jQuery
  • Difficulty: Intermediate
  • Estimated Completion Time: 30 min

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>
	</a>
	<span class="count">POST_LIKES_COUNT</span>
</p>

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{
	margin-top:1em
}

article footer .like{
	background:url(images/icons.png) no-repeat;
	width: 15px;
	height: 16px;
	display: block;
	float:left;
	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 = heart.data("post_id");
		
		// Ajax call
		jQuery.ajax({
			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")
				{
					heart.addClass("voted");
					heart.siblings(".count").text(count);
				}
			}
		});
		
		return false;
	})
})

Explanations

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.

Hooks

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.”

Functions

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!');
	
	if(isset($_POST['post_like']))
	{
		// 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];

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

		// Use has already voted ?
		if(!hasAlreadyVoted($post_id))
		{
			$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;
		}
		else
			echo "already";
	}
	exit;
}

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];
	
	if(!is_array($voted_IP))
		$voted_IP = array();
		
	// Retrieve current user IP
	$ip = $_SERVER['REMOTE_ADDR'];
	
	// 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">';
	if(hasAlreadyVoted($post_id))
		$output .= ' <span title="'.__('I like this article', $themename).'" class="like alreadyvoted"></span>';
	else
		$output .= '<a href="#" data-post_id="'.$post_id.'">
					<span  title="'.__('I like this article', $themename).'"class="qtip like"></span>
				</a>';
	$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:

query_posts('meta_key=votes_count&orderby=meta_value_num&order=DESC&posts_per_page=10');

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!

Note: Want to add some source code? Type <pre><code> before it and </code></pre> after it. Find out more
  • UUgee

    I haven’t looked through the code in a proper manner yet, but do you think it would be easy to customize this code to be a 5 star rating instead?

    It seems to be really hard to find an easy solution for a star rating, that isn’t a complete overkill.

    • http://www.guillaumevoisin.fr/ Guillaume
      Author

      Yes UUgee, it won’t be too complicated, you’ll just have to replace the heart shaped button with a 5 stars rating plugin, then edit the php code to save and return the average value for the post and eventually change the view to display average value with the jQuery plugin.

      • Christian Philippsen

        Please do share a Star solution as well as this nice Like tutorial.

      • http://niallm1.com Niall

        I commented below but yeah, would be good, especially for a review type site so you can add Google Rich Snippets that will show the rating in a Google search.

      • UUGee

        I would really like to see a star rating based on this on wp.tuts, it would be awsome! And not a complicated plugin, just an easy way to get the ratings as custom fields, where the developer then could continue and show them as he wishes.

      • http://www.guillaumevoisin.fr/ Guillaume
        Author

        Allright ! I’ll try to take some time to provide a 5-star system ! It could indeed be very nice if it meets Google search requirements !

      • http://www.guillaumevoisin.fr/ Guillaume
        Author

        Here are the quick steps to follow to add a 5-star system.

        I downloaded and enqueued the great jQuery Star Rating Plugin.

        Then I edited the post_like function like so :

        function post_like()
        {
        	...
        	
        	if(isset($_POST['post_rate']))
        	{
        		// Retrieve user IP address
        		$ip = $_SERVER['REMOTE_ADDR'];
        		$post_id = $_POST['post_id'];
        		$vote_value = $_POST['post_rate'];
        		
        		// Get voters'IPs for the current post
        		$meta_IP = get_post_meta($post_id, "voted_IP");
        		$voted_IP = $meta_IP[0];
        
        		if(!is_array($voted_IP))
        			$voted_IP = array();
        		
        		// Get votes count for the current post
        		$meta_count = get_post_meta($post_id, "votes_count", true);
        		$meta_votes_values = get_post_meta($post_id, "votes_values", true);
        
        		$meta_votes_values[] = $vote_value;
        		
        		// Use has already voted ?
        		if(!hasAlreadyVoted($post_id))
        		{
        			$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);
        			update_post_meta($post_id, "votes_values", $meta_votes_values);
        
        			
        			// Display average rating value
        			echo round(array_sum($meta_votes_values) / $meta_count);
        		}
        		else
        			echo "already";
        	}
        	exit;
        }
        

        I added a third post_meta information to store all the votes values and return an average value.

        Then in the function that generates the markup, I replaced the heart shaped button with the 5-star system :

        function getPostLikeLink($post_id)
        {
        	$themename = "twentyeleven";
        
        	$vote_count = get_post_meta($post_id, "votes_count", true);
        	$meta_votes_values = get_post_meta($post_id, "votes_values", true);
        	
        	if(is_array($meta_votes_values))
        		$avg = round(array_sum($meta_votes_values) / $vote_count);
        	else
        		$avg = 0;
        	
        	$output = '
        	
        	';
        		for($i=1; $i<=5; $i++)
        		{
        			$output .= '';
        		}
        	$output .= '';
        	
        	return $output;
        }
        

        I get all values from post_meta and use the average value to get the good radio button checked.

        Eventually, I changed the JS file :

        jQuery(".post-like input").rating({
        	
        	callback: function(value, link){
        		postID = $(link).parents(".post-like").data("post_id");
        		
        		jQuery.ajax({
        			type: "post",
        			url: ajax_var.url,
        			data: "action=post-like&nonce="+ajax_var.nonce+"&post_rate="+value+"&post_id="+postID,
        			success: function(){
        				// Disable vote
        				// Set the average value
        				// ...
        			}
        		}); 
        	}
        
        });
        

        It uses the jquery plugin to submit via ajax the value to be stored in post metas.

        And that’s it !

        It should be compliant with Google rating system. (see here for more information).

        Hope it helps !

        • UUGee

          Thank you for providing a start! This isn’t as far developed as the original article, at least looks that way. Did you get this to fully function?

          Really nice of you to provide this much help to the community, envanto should pay you double for this article :)

        • Pabagan

          Thanks for the tuto!!! I had no problem getting work the first part but since I started I was missing the five star system..It was a great surprise to find it on commnets but I can do it work..

          I followed the steps:
          1. Enqueue the five stars scripts

          wp_enqueue_script('five-stars-rates', get_template_directory_uri().'/js/five-stars-rates.js', array('jquery'), '1.0', true );
          

          2. Edit post_like function with that result:

          function post_like()  
          {  
              // Check for nonce security  
              $nonce = $_POST['nonce'];  
            
              if ( ! wp_verify_nonce( $nonce, 'ajax-nonce' ) )  
                  die ( 'Vetarcarahoo!');  
            
              if(isset($_POST['post_like']))  
              {  
                  // 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];  
            
                  if(!is_array($voted_IP))  
                      $voted_IP = array();  
            
                  // Get votes count for the current post  
                  $meta_count = get_post_meta($post_id, "votes_count", true);  
            
                  // Use has already voted ?  
                  if(!hasAlreadyVoted($post_id))  
                  {  
                      $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;  
                  }  
                  else  
                      echo "ya votaste!";  
              }  
              exit; 
              if(isset($_POST['post_rate']))  
              {  
                  // Retrieve user IP address  
                  $ip = $_SERVER['REMOTE_ADDR'];  
                  $post_id = $_POST['post_id'];  
                  $vote_value = $_POST['post_rate'];  
            
                  // Get voters'IPs for the current post  
                  $meta_IP = get_post_meta($post_id, "voted_IP");  
                  $voted_IP = $meta_IP[0];  
            
                  if(!is_array($voted_IP))  
                      $voted_IP = array();  
            
                  // Get votes count for the current post  
                  $meta_count = get_post_meta($post_id, "votes_count", true);  
                  $meta_votes_values = get_post_meta($post_id, "votes_values", true);  
            
                  $meta_votes_values[] = $vote_value;  
            
                  // Use has already voted ?  
                  if(!hasAlreadyVoted($post_id))  
                  {  
                      $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);  
                      update_post_meta($post_id, "votes_values", $meta_votes_values);  
            
                      // Display average rating value  
                      echo round(array_sum($meta_votes_values) / $meta_count);  
                  }  
                  else  
                      echo "already";  
              }  
              exit;  	
          }
          

          2. Edit getPostLikeLink function with that result:

          function getPostLike($post_id)  
          {  
              $themename = "flamenco";  
            
              $vote_count = get_post_meta($post_id, "votes_count", true);  
              $meta_votes_values = get_post_meta($post_id, "votes_values", true);  
            
              if(is_array($meta_votes_values))  
                  $avg = round(array_sum($meta_votes_values) / $vote_count);  
              else  
                  $avg = 0;  
            
              $output = ' 
           
              ';  
                  for($i=1; $i<=5; $i++)  
                  {  
                      $output .= '';  
                  }  
              $output .= '';  
            
              return $output;  
          }
          

          4. and finally edit my JS file with that result:

          jQuery(".post-like input").rating({  
            
              callback: function(value, link){  
                  postID = $(link).parents(".post-like").data("post_id");  
            
                  jQuery.ajax({  
                      type: "post",  
                      url: ajax_var.url,  
                      data: "action=post-like&nonce="+ajax_var.nonce+"&post_rate="+value+"&post_id="+postID,  
                      success: function(){  
                          // Disable vote  
                          // Set the average value  
                          // ...  
                      }  
                  });  
              }  
            
          }); 
          

          Please some help…I want my five stars hotel ;)
          Thanks!!

        • Jared

          Having trouble getting this to work. In ‘getPostLikeLink’ I was able to check for the value of $avg and echo out the appropriate input tags based on that value. Everything displays correctly, but for whatever reason the data is not getting saved to the custom field. The heart version worked perfectly, but as soon as I augmented that code with what you have above, nothing gets saved when I click on the carting. Please advise. Thanks!

        • http://mauricenaef.ch Marcel Maurice Naef

          Hi Guillaume

          Thanks for the great tutorial. Getting back on the five star rating update you have posted, it seems as the getPostLikeLink function hasn’t copied over fully! Looks as if there is some code missing!?

          Would you mind reposting the full function? Thanks a lot and kind regards in advance! :-)

        • http://www.guillaumevoisin.fr/ Guillaume
          Author

          Hey, sorry for the delay, I’ve been busy !

          I didn’t see that the hasn’t got pasted well. The problem is with the getPostLikeLink() function, markup should have been :

          $output = ‘
          <div class="post-like" data-post_id="’.$post_id.’">
          <form action="" method="post">’;
          for($i=1; $i<=5; $i++)
          {
          $output .= ‘<input’;
          if($i == $avg)
          $output .= ‘ checked="checked"’;
          $output .= ‘ name="star1" class="rating" title="’.$i.’ Star Rating" type="radio" value="’.$i.’" />’;
          }
          $output .= ‘</form></div>’;

          Hope it’s gonna be posted well.

          • Spiderpig

            2 typos to make to work!

            1) post-like.js

            postID = $(link).parents(“.post-like”).data(“post_id”);

            should by in my case

            postID = jQuery(link).parents(“.post-like”).data(“post_id”);

            2) from function post_like()

            remove this line
            if (isset($_POST['post_like'])) {

            and bracket which close it
            }

            After those changes, its working for me :)

        • http://www.guillaumevoisin.fr/ Guillaume
          Author

          I think it should be OK. Let me guys know ;)

          • jason

            works great!

            Only thing I’m struggling with here now is how to get posts by average rating?

            Is that a query I could handle with WP_Query?

  • http://www.vaultstudios.co.uk Martin Harvey

    Great stuff. I was just about to tackle this myself and I’ve spent some time scouring Google for a solution to this but all I could find was super duper plugin this and 2million options plugin that. Thanks ;)

  • Rened

    wow i was looking something like this days ago and here it is, thanks for the great article Guillaume

  • Simon

    This is a great little feature and a good tutorial, so it is a shame that you mislead people by claiming that adding a plugin is “slowing down WordPress” – there is no difference between putting code in a plugin and putting the same code into your theme file. Plugins are simply files that WordPress includes. A few lines of badly written code in a theme file can slow WordPress down much more than 10 well-written plugins.

    Using plugins is very good practice, not the negative thing you portray it to be: updating your code or using it across different websites becomes much easier, and you give end users the option to easily turn something on or off with one click.

    • http://www.guillaumevoisin.fr/ Guillaume
      Author

      I didn’t mean using plugin is bad, It’s one of the coolest WordPress’ feature. I just pointed out that is you use this code as a plugin, you’ll have to enqueue separate javascript, stylesheets and images whereas you could simply add this to your themes’s template files. This will save you external server requests so it won’t reduce page load.

      You could totally make a plugin out of it, the question is, is it really worth it ?

      • http://wpconsult.net Paul

        the advantage of using a plugin is that if the user changes the theme, then they’ll still see the post ratings

  • http://redstarwebdevelopment.com Dave

    Oh man, I’ve got to try this out!

  • http://www.yousellquick.co.uk sell

    Wow, didn’t know about the post_meta() shortcuts, I’ve always used raw MySQL queries.
    Thanks Guillaume!

    The post meta gets stored in the ‘wp_postmeta’, will there be any issues when changing themes? (I guess you will need to code as a plugin or copy-paste into the functions.php).

    Also, what if I delete a post? Does the post meta get cleaned or will I end up with loads of old data in the DB?

  • http://www.creativemanner.com ozgur coruhlu

    Awesome one as always thanks.

  • Pingback: WordPress Temanızı Zenginleştirecek İpuçları | + Web Design

  • http://radiumthemes.com frank

    Wow. This came in just in time. I’ve been working on a similar implementation for the last couple of days. Good job.

  • http://learneveryday.net arifur rahman

    I have question. IF same code is converted to plugin. Is that become performance issue. As plugin and theme run same code. So how the performance issue. which you told.

    “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.”

    Please a clear idea how it happen.

    • http://www.guillaumevoisin.fr/ Guillaume
      Author

      See my answer to Simon ;)

  • http://niallm1.com Niall

    Thanks! I guess to enhance it someone could change the rating system to a 5-star type system so that you could change it for Google Rich Snippets in order for the rating to show up in Google’s search.

  • http://baroquedub.co.uk/ baroquedub

    I really like the idea of not bloating things with a plug-in but the problem is then having to hard-code the getPostLikeLink(get_the_ID()) function into my theme.

    In Step2 you say “add markup in the content-single.php file (within the Twenty Eleven theme).” but I’m using a child theme (Graphene with slightly altered CSS) and I don’t want to alter the parent theme’s php code as this would make updates difficult to implement (i.e. having to remember to add the custom code every time)

    Is there a way around this?

    • http://baroquedub.co.uk/ baroquedub

      In an attempt to answer my own question, I’ve been finding out about WordPress Action Hooks (http://www.nathanrice.net/blog/an-introduction-to-wordpress-action-hooks/)

      I’ve found that Graphene provides a number of these:
      http://www.khairul-syahir.com/wordpress-dev/graphene-theme/graphene-action-hooks

      So I’ve tried adding the following at the end of function.php

      function insert_postlike_code() {
      echo ‘getPostLikeLink($post_id);’;
      }

      add_filter(‘graphene_after_post_content’,'insert_postlike_code’);

      But what gets echoed out at the bottom of each post is just the string literal, i.e. “getPostLikeLink($post_id);”

      If I change my function to
      function insert_postlike_code() {
      echo ‘eval(“getPostLikeLink($post_id);”);’;
      }
      then the same, just the string “eval(“getPostLikeLink($post_id);”);” appears.

      Finally in desperation I tried printing the code from Step 2, and tried:
      function insert_postlike_code() {
      echo ‘<p class=”post-like”>’.”\n”;
      echo ‘ <a data-post_id=”POST_ID” href=”#”> ‘.”\n”;
      echo ‘ <span class=”qtip like” title=”I like this article”></span> ‘.”\n”;
      echo ‘ </a> ‘.”\n”;
      echo ‘ <span class=”count”>POST_LIKES_COUNT</span> ‘.”\n”;
      echo ‘</p> ‘.”\n”;
      }

      add_filter(‘graphene_after_post_content’,'insert_postlike_code’);

      But that just displays “POST_LIKES_COUNT”, although when I view source I see that the HTML is:
      <p class=”post-like”>
      <a data-post_id=”POST_ID” href=”#”>
      <span class=”qtip like” title=”I like this article”></span>
      </a>
      <span class=”count”>POST_LIKES_COUNT</span>
      </p>

      I’ve check that post-like.js is indeed being loaded, so that’s not the problem… Anyone have any ideas how I can get this to work?

  • http://www.graphismeo.com Graphismeo

    Yeah ! Just what I needed ! Thank you so much :)

  • http://www.harishchouhan.com Harish

    Hi Guillaume,

    Thanks for the great post. I have used a modified version of the plugin http://wordpress.org/extend/plugins/i-like-this/ on my personal website http://www.harishchouhan.com.

    I have been also in the process of submitting my version on WordPress, but looking at your code found it lot simpler.

    Can you please share with me your email address as I need to ask you about few things.

    • http://www.guillaumevoisin.fr/ Guillaume
      Author

      guillaumevoisin at gmail

  • http://9gags.gr asteies eikones

    is there any way to build a post rating system like this and make most voted posts go to top page?

    • http://www.guillaumevoisin.fr/ Guillaume
      Author

      Yes you just have to insert code at step 7 into the page template or wherever you want, or use it within a shortcode function [top_posts nb=7 ... ].

      That’s what I’m doing with my own theme ;)

  • Pingback: Come creare un semplice sistema di votazione com jQuery e Wordpress - sastgroup.com

  • Pingback: Come creare un semplice sistema di votazione com jQuery e WordPress | buonaguida.com

  • Pingback: WordPress Temanız için İpuçları – Best Alanya – Bilişim Teknolojileri – Yazılım ve Donanım -

  • John Wilson

    Great article, just what I’ve been looking for & none of the plugins out there seemed to offer the right simplicity.

    However, I’ve tried it out on my localhost and it doesn’t seem to be working for me. I can click the hearts and it changes the vote count from 0 but replaces it with the HTML of the front page. When I refresh this page, it has incremented the count to one as it should. If I login to WordPress, it works fine, it increments the post counts as it should.

    In both situations, it lets me vote more than once on each post after the 60 seconds have elapsed.

    I’ve gone over the instructions twice, and simply copied & pasted your code into my own theme and it doesn’t work. Anybody else had a similar experience or am I missing something.

    Thanks!

    • John Wilson

      Hi,

      I’ve tried it in the Twentyeleven theme that comes with WordPress, and this time there’s no issue with the HTML source of the index page, when I’m logged out the count increments as it should but it still doesn’t limit me from voting more than once on the same article nor does it display any message after I’ve voted.

      I will persevere and get to the bottom of this, even if it does take me all day :-)

      John

    • http://www.guillaumevoisin.fr/ Guillaume
      Author

      Hey John,

      Is the $timebeforerevote variable still set to 120 seconds ? If it is, you may have to debug this with Firebug, just open the ajax request in a new tab and see what it says. You can print IPs array as well as your own, vote count etc…

      I’m sure you’ll figure it out. Don’t hesitate to tell us if you managed to get it to work or not.

  • Pingback: Best of Tuts+ in February 2012 | CS5 Design

  • Pingback: Best of Tuts+ in February 2012 | DigitalMofo

  • Pingback: Best of Tuts+ in February 2012 | Shadowtek | Hosting and Design Solutions

  • Pingback: Best of Tuts+ in February 2012 | HowDoDesign

  • Pingback: Best of Tuts+ in February 2012 | linuxin.ro

  • http://twitter.com/MarioGiancini Mario

    Hi Guillaume,

    Awesome post. I’ve been looking for a non-plugin solution to this as well. My question is would it be possible to have this translate into a rating system for photos in post instead of the post itself? Would I just be replacing POST_ID with an attachment ID? Any help with this would be awesome. Thanks!

    -Mario

    • http://www.guillaumevoisin.fr/ Guillaume
      Author

      Hi Mario,

      Actually, it works already ! As photos behave like posts, you can already vote for photos. If you like to restrict vote to attachments only, you could add a check in the vote function to be sure the post is an attachment. Otherwise, you’ve got nothing to do ;)

  • Pingback: Best of Tuts+ in February 2012 | Cyber Web Designs

  • http://www.newcarmodels.co.uk Alex

    Wow. This came in just in time. I’ve been working on a similar implementation for the last couple of days. Good job. Thanks tutsplus.

  • http://joshriser.com Josh Riser

    This is a great tutorial. I will definitely use this some time.

    I do have a question: Is there a way to completely remove the $timebeforerevote so that the user can only ever vote once?

    • http://www.guillaumevoisin.fr/ Guillaume
      Author

      Well, you just have to edit the if statement to only check IP address has already been saved so user can not vote anymore. That should do the trick.

  • http://matiasmancini.com.ar Matias Mancini

    This is great!!!
    I dint know about wp_localize_script() and wp_ajax Hooks, very helpful.
    Thank You =)

  • http://twitter.com/MichealKennedy Mike Kennedy

    Could you also add Dislike, too? Can’t find a good plugin to do both Like and Dislike anywhere! :(

  • Pingback: Как создать систему рейтинга записей WordPress на jQuery | Wordpresso

  • Pabagan

    Any way to show the favorites post from a loged user??

    • http://www.guillaumevoisin.fr/ Guillaume
      Author

      I guess you could, the code isn’t suited well for that, but you could prevent non logged users to vote and store logged in users’ID and IP so that you could then get all favorite posts from a particular user.

  • DJ

    $voted_IP = $meta_IP[0]; (the one in function hasAlreadyVoted($post_id) {) gives a ‘Notice: Undefined offset’ when running WP in debug mode! Is there a fix for this?

    • http://www.guillaumevoisin.fr/ Guillaume
      Author

      Well you just have to check (isset) if post meta has already been saved once to get its value, otherwise you know that user hasn’t already voted.

      • Jason

        Hi,

        I’m getting the exact same error. And have no idea how to solve it…

  • DJ

    Thanks for replying, apriciated!

    Any chance you could point me in the right direction on how to implement this in the code?

    • Pascal

      I have the same issue and don´t get it working :/

  • expo

    I guess i did all the steps but it doesnt work. im using the object theme from woothemes. can you help me with that ?

  • qbauer

    How difficult would it be to adapt this to like comments?

  • http://www.wasrizmachinery.com Hassan Ahmed Khan

    hello, can you please tell me that how can i use that downloaded file into my website? i am new in wordpress please help me..
    Thank you

  • Dan

    Could you please explain how you enqued the jquery star rating script?

    Thanks very much.

  • Jimmy Quintos

    Thanks for the great tutorial.
    Could you tell me about the license? Can I use for my commercial projects?

    Thank you very much.

  • Thad

    Is there an easy way to manipulate this function so that a user may only vote once, on any post?

  • Thinkwell

    Fantastic tutorial. I was able to get the rating system to work on normal posts, however, when I place the code on a page of a custom post type, It does not work.

    Anyone tips on how to get the following code working with custom post types ?

    • Thinkwell

      I figured it out. I simply started from a fresh, new twentyeleven theme and added my custom post types to it.

  • Jason

    Hi,

    I’ve followed every step in this article multiple times, but I’m still getting this error:

    wp_enqueue_script was called incorrectly. Scripts and styles should not be registered or enqueued until the wp_enqueue_scripts, admin_enqueue_scripts, or init

    What am I doing wrong?? Thanks in advance.

    • Jason

      Fixed it by wrapping it inside an add_action(‘wp_enqueue_scripts’, ”);

      • Jason

        Not fixed it.
        Suddenly the script stops working when I put it into add_action(‘wp_enqueue_scripts’)……

  • http://devilzerotica.com Devil

    I am trying to use this with the Themify Pinboard theme. It has infinite scrolling. Works smoothly on the first few images but when scrolled down to load more images it fails to work. Also I was wondering if some message could be given if an user tries to click twice like “already liked”.

    Does someone know if it can be made to work with infinite scrolling?

  • F2

    I was hoping to put a speech bubble/box around the counter, but new to this. Managed to get it working which is good for me :)

    Any pointers or tutorials would be great, thanks

  • Anatoly

    I followed all steps, but I got error “ajax_var is not defined”.

    What can cause this?

    P.S. Anyway, thanks for this great tutorial! :)

    • Anatoly

      Oh, fixed it by myself! Just a stupid mistake – I forgot “wp_footer();” in my theme!

  • louis

    thanks it works ! but it won’t if i put it anywhere else than the footer.. why ?

  • mohamed khafagy

    instead of

    echo $meta_count;
    use
    die($meta_count);

    this will increase the speed and save more bandwidth

  • http://twitter.com/nbolton00 nbolton00

    This is great! Whats the simplest way of display 0 next to the icon if no votes. Thanks

  • DeAndre Johnson

    Thanks. Now how can I take this and create another vote option to use along with it? I’m trying to give my users the ablity to vote videos as funny and hilarious. Each with their own vote counts. Any help would be appreciated

  • Aliyan

    put an underline before your custom field name to make it hidden: ‘voted_IP’ to ‘_voted_IP’

  • Jacobi Ojera

    If I were to attempt a solution like this, how could I give the user immediate feedback after their ‘Like’, without them having to refresh the page?

  • Dan Gavin

    What would it take to make this work as a “Like this site” system, rather than Like this post?

  • http://www.facebook.com/michiel.bruggenwirth Michiel Bruggenwirth

    Is there a way that is can display the post that i have liked per user?
    For example i liked Post 1 and Post 3 out of 5 posts and in my profile it would say :
    – You liked Post 1
    – You liked Post 3

  • http://moviedvdrips.com/ Free movie download

    Have somebody star rating which work?

  • http://www.facebook.com/mikevandinther Michael van Dinther

    Is not working for non-logged in users. Just receive an output of the entire page HTML inside the tag.

    Any ideas what might be happening here?

  • http://hannawerner.no/ Sinopa

    WOW! I really love this. I’ve implemented it now and it works like a charm :)

    Does anyone know how I can add a ’0′ if no votes are given yet?

  • http://www.facebook.com/joe.mexican Joe Mexican

    Can this be used on the twenty twelve theme? if so how because i cant get it to work.

    thank you in advance

  • http://www.facebook.com/guillermo.suarez.9849 Guillermo Suárez

    Absolutely perfect. Just what i was trying to achieve.
    Thanks for a great tutorial!