There are many post rating system plugins out there. Most are complex and suffer from options bloat. WordPress.com sites use a Like System that can also be accessed on your local WordPress install via Jetpack. While the Jetpack solution is pretty cool, I prefer to keep things simple. In this tutorial, you’ll learn how to build your own simple and effective Post Like System, directly within your theme, without a plugin.

Check out the demo on my site or like it above besides the title:

WordPress Post Like Preview (Updated)

WordPress Post Like Preview (Updated)

DownloadDownload all the files from GitHub
» https://github.com/JonMasterson/WordPress-Post-Like-System/archive/master.zip (ca. 5KB)
 
 

How does it Work?

We will use HTML for our button, CSS for styling, jQuery for Ajax, and PHP for handling our data.

When an anonymous user clicks the like button:

  1. User’s IP address is stored in the post’s meta as an array.
    These IP addresses are utilized to prevent anonymous users from liking posts more than once.
  2. Post like count is incremented +1 and stored in post meta.

When a registered user clicks the like button:

  1. WP User ID in the post’s meta as an array.
  2. Post like count is incremented +1 and stored in post meta.
  3. Post ID is stored as user meta.
  4. User like count is incremented +1 and stored as user meta.

CSS

Add the CSS provided on GitHub to your theme or plugins’s main stylesheet (named like-styles.css). Feel free to customize it as necessary.

Button

While, technically, it is not a button (it’s really a hyperlink), this PHP snippet should be added to your single page template (typically named content-single.php). You can add the code anywhere inside the loop.

Javascript

Add the post-like.js and jQuery.fastClick.js file to your theme’s ›js‹ folder. (You’ll find the files in the GitHub repository.)

We’re using jQuery to handle our Ajax requests. Ajax enables our users to get an instant response while clicking the like button. When the user clicks the button, we retrieve the post ID with jQuery’s data method and then pass it to our PHP handler. We will create the ajax_var variable with PHP, binding or functions and hooks to admin-ajax.php in the wp-admin folder (WP core).

PHP

Add the functions located in post-like.php to your theme’s functions.php file. The Like System will not work without them.

Function (1) Enqueues the Javascript
The post-like.js file you added above is added to the <head>. This function also defines the URL to the admin-ajax.php file mentioned above and creates a nonce to prevent attacks and problems (can be seen within post-like.js as ajax_var.nonce)

Function (2) Enqueues the Font Awesome Icon Styles
WordPress Post Like Icons
We are adding these styles from a CDN, specifically for the heart symbol. You may prefer to use a different symbol/images or something a bit less robust if you only need it for one icon. I use Font Awesome with many projects at this point. The icon styles load quickly and can be used anywhere on your site’s front end when enqueued this way.

Function (3) Saves the User Data
Let’s break this function down — we start by firing up our Ajax calls with two WordPress hooks:

<?php
  
  add_action( 'wp_ajax_nopriv_jm-post-like', 'jm_post_like' );
  add_action( 'wp_ajax_jm-post-like', 'jm_post_like' );

The first hook is used for anonymous users, while the second is for registered, logged in users. You can see the jm-post-like portion of the hook within the post-like.js file. Now that all our hooks are in place, let’s get down to business:

  • Check our nonce to keep out the bad guys
  • Upon click, check if the user is logged in, and retrieve our custom metas from the user and the post
  • If the user has not liked the post, add the User ID to post meta and the Post ID to user meta
  • If the user has liked the post already, remove the User ID from post meta and the Post ID from user meta

We use the same test to determine whether anonymous users have liked the post already, and add/remove their IP address from the post’s meta accordingly (I’ve omitted the rest of the function for brevity, but it can be viewed in all its glory on GitHub).

Function (4) Checks if the user has liked the post
Similar to the post like function above, this function tests if the user has liked the post before:

  • Checks if user is logged in
  • If logged in, it searches the post’s meta for the user’s ID
  • If anonymous, it searches the post’s meta for the user’s IP address
  • Returns TRUE if it finds either the user’s ID or IP in post meta

Function (5) Adds the Button to the Template
This function retrieves two different buttons depending on whether the user already liked the post:

  • Retrieves the post’s like count. If the count is zero, it print’s “Like” instead of a number.
    If the user already liked the post, we will add an icon and classes that indicate A) the post is already liked and B) the post will be unliked if clicked again.
    If the user has not liked the post already, display the default button
  • Function (6) Adds a List of Liked Posts to the User’s Profile
    This function outputs a list of post links on the User’s Profile page in the WordPress admin:

    • Retrieve the posts that the user likes (the post IDs)
    • If there are posts, output a list of post title links, separated by dots
    • If there are no posts, tell the user
    • Function (7) Add a shortcode to your posts instead
      Simply type [jmliker] in your post to output the button

    Function (8) If the user is logged in, output a list of posts that the user likes
    Note: Markup assumes sidebar/widget usage

    One Step Beyond

    You can do a lot with these meta values — one potential solution is to do a meta query to display the top five most liked posts.

    Function (9) Outputs a list of the 5 posts with the most user likes today
    Note: Markup assumes sidebar/widget usage; check Function (10) and (11) for most user likes of the month/week and Function (12) for the most likes of all time

    That’s it! Feel free to fork it on GitHub and go crazy — I look forward to seeing how it evolves!