internet love

Everyone is familiar with the “Like” button from Facebook, as well as many of its spin offs from other social networks. In this tutorial, we’re going to create our own version of the “like” button, but it is going to be a “love it” button and also specific to our website. Our plugin is going to use ajax to process the “love it” button clicks, it will display the total number of loves, and it will also have a widget to display the most loved items.

Demo of What We are Creating

A Pro version of this plugin is available for download and purchase.

The plugin itself is not overly complicated, but it may appear that way if you’re not really familiar with some of the methods I’m going to use. There are two primary methods I’m going to use in this tutorial that can seem complex, but are really pretty simple. One, I will use the post meta options and the user meta options to store information about “loves”. Two, since all of our processing is done via ajax when a “love it” button is clicked, we are going to be using the WordPress ajax API, which can be very confusing if you don’t know how it works.

As with all my plugins, the plugin will be broken up into individual files. Each file will serve a specific purpose. The files we will create are as follows:

  • love-it.php – main plugin file
    • display-functions.php – for displaying the love it button
    • love-functions.php – for processing loves and similar actions
    • scripts.php – for loading our jQuery scripts
    • love-it.js – jQuery for sending ajax requests
    • widgets.php – for registered our “most loved” widget

We will start with the main plugin file, which lives inside of the folder called “love-it”.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<?php
/*
Plugin Name: Love It
Plugin URI: https://pippinsplugins.com/write-a-love-it-plugin-with-ajax
Description: Adds a "Love It" link to posts, pages, and custom post types
Version: 1.0
Author: Pippin Williamson
Contributors: mordauk
Author URI: https://pippinsplugins.com
*/
 
/***************************
* constants
***************************/
 
if(!defined('LI_BASE_DIR')) {
	define('LI_BASE_DIR', dirname(__FILE__));
}
if(!defined('LI_BASE_URL')) {
	define('LI_BASE_URL', plugin_dir_url(__FILE__));
}
 
/***************************
* language files
***************************/
load_plugin_textdomain( 'love_it', false, dirname( plugin_basename( __FILE__ ) ) . '/languages/' );
 
/***************************
* includes
***************************/
include(LI_BASE_DIR . '/includes/display-functions.php');
include(LI_BASE_DIR . '/includes/love-functions.php');
include(LI_BASE_DIR . '/includes/scripts.php');
include(LI_BASE_DIR . '/includes/widgets.php');

This file simply defines our plugin name, the author, plugin URL, etc; all of that stuff we are so used to creating by this time 😉

We also take a moment to define a couple of constants: one for the directory path to our plugin folder, and one for the URL to our plugin folder. The LI_BASE_DIR constant will be used for including our other plugin files into our main plugin file, and LI_BASE_URL will be used for loading script files (and CSS if you decide to add them).

After we define our constants, we load our language files. This is for our non-English speaking friends. If you’re not familiar with how to translate your plugins, read through my tutorial on the subject.

Lastly, we include each of our other plugin files into the main file using include().

That’s it for the main file.

Displaying the “Love It” Button

We are going to write one function now that will display the “love it” link after our item content when we are viewing a singular post, page, or custom post type. This function goes in display-functions.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
// adds the Love It link and count to post/page content
function li_display_love_link($content) {
 
	global $user_ID, $post;
 
	// only show the link when user is logged in and on a singular page
	if(is_user_logged_in() && is_singular()) {
 
		ob_start();
 
		// retrieve the total love count for this item
		$love_count = li_get_love_count($post->ID);
 
		// our wrapper DIV
		echo '<div class="love-it-wrapper">';
 
			// only show the Love It link if the user has NOT previously loved this item
			if(!li_user_has_loved_post($user_ID, get_the_ID())) {
				echo '<a href="#" class="love-it" data-post-id="' . get_the_ID() . '" data-user-id="' .  $user_ID . '">' . __('Love It', 'love_it') . '</a> (<span class="love-count">' . $love_count . '</span>)';
			} else {
				// show a message to users who have already loved this item
				echo '<span class="loved">' . __('You have loved this', 'love_it') . ' (<span class="love-count">' . $love_count . '</span>)</span>';
			}
 
		// close our wrapper DIV
		echo '</div>';
 
		// append our "Love It" link to the item content.
		$content = $content . ob_get_clean();
	}
	return $content;
}
add_filter('the_content', 'li_display_love_link');

There seems to be quite a bit going on in this function, but it’s really pretty simple. First we check to make sure the user is logged-in (to make this tutorial simpler, we’re only allowing logged-in users to Love items) and that we are on a singular page. The check for the singular page prevents the Love It button from being outputted on archive and search results page.

Once we have determined that we should be displaying the Love It button, we use our li_get_love_count() function, which we will write a moment, to retrieve the total number of loves this item has, or the number of times the Love It button has been clicked.

Next, we setup a DIV wrapper for our button. This makes it easier to style and makes our markup a bit cleaner and compatible with more themes.

Inside of our DIV wrapper, we check quickly to see if the user has already loved this item or not by using the li_user_has_loved_post() function, which we will also write in a moment. If the user has not loved the item, then we display the button, but if they have, we display a message telling them they have already loved the item.

Take a good look at the anchor tag element that we create for users who have not loved the current post or page. It has several custom “data” attributes. These will be read by our jQuery so that the function that processes the ajax requests knows which post/page ID is being loved, and which user is loving the item.

At the end of the function we simply append our new link (which is contained in the output buffer) to the item’s $content.

Writing Our Processing Functions

It is now time to write the functions that will check whether a user has loved an item, will mark an item as loved, and will retrieve the total loves an item has received.

These functions all go in the love-functions.php, which is located inside of the includes/ directory.

First we will create the function to check if a user has already loved a post.

1
2
3
4
5
6
7
8
9
10
// check whether a user has loved an item
function li_user_has_loved_post($user_id, $post_id) {
 
	// get all item IDs the user has loved
	$loved = get_user_option('li_user_loves', $user_id);
	if(is_array($loved) && in_array($post_id, $loved)) {
		return true; // user has loved post
	}
	return false; // user has not loved post
}

All post/page IDs loved by a user are stored in the user meta table, and so to check whether a user has loved a post, we need to retrieve the option for our specific user ID. This is done with the get_user_option() function. Note that I am not using the get_user_meta(). This is because get_user_meta() will retrieve the meta value for the user from across the entire network, when using WordPress multi site. Since we want to make sure that we support sites that on a network install and those that are not, we use get_user_option() instead.

If get_user_option() returns a value, it will come back as an array, so we use is_array() and in_array() to check to make sure that the option is an array and that our post ID, which we passed to the function, is held in that array. If both conditionals validate as true, we return the function as true. Otherwise it is returned as false.

We are now able to detect when a user has loved a post, but now it’s time to write the function that will store a post ID as loved for the current user.

1
2
3
4
5
6
7
8
9
10
// adds the loved ID to the users meta so they can't love it again
function li_store_loved_id_for_user($user_id, $post_id) {
	$loved = get_user_option('li_user_loves', $user_id);
	if(is_array($loved)) {
		$loved[] = $post_id;
	} else {
		$loved = array($post_id);
	}
	update_user_option($user_id, 'li_user_loves', $loved);
}

This one is really simple. The function takes two parameters, just like our previous function: one for the user ID and one for the post/page ID.

We use get_user_option() again to retrieve all of the IDs the user has already loved. If the user has loved at least one item, get_user_option() will return an array, so we simply append our current post ID to the array using $loved[] = $post_id;. If the user has never loved an item, get_user_option() will not return an array, so we setup a simple array and place the $post_id as the only key in it.

Once we have added our post ID to the array, either as an additional key or as a new array, we use update_user_option() to store the array in the user’s meta.

Those are the only two functions needed for recording a post as loved for users, but now we need to store posts as loved in the meta of the post that is loved. This allows to keep track of and record “love counts”.

When a “Love It” button is clicked on a post, the total number of times the post has been loved is incremented by one, so the function we are going to write now we do a couple of things:

  1. Check if the post has ever been loved before
  2. Increase the love count by 1 if it has been loved
  3. Set the love count to 1 if it has never been loved
  4. Store the final, updated love count so it can be retrieved at any time
  5. Store the post ID in the user’s meta who loved the post with li_store_loved_id_for_user()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// increments a love count
function li_mark_post_as_loved($post_id, $user_id) {
 
	// retrieve the love count for $post_id	
	$love_count = get_post_meta($post_id, '_li_love_count', true);
	if($love_count)
		$love_count = $love_count + 1;
	else
		$love_count = 1;
 
	if(update_post_meta($post_id, '_li_love_count', $love_count)) {	
		// store this post as loved for $user_id	
		li_store_loved_id_for_user($user_id, $post_id);
		return true;
	}
	return false;
}

This function works nearly identical to the li_store_loved_id_for_user(), except we are using it with the get_post_meta() instead of get_user_option().

When a post’s love count has been successfully incremented, we also use the function we wrote just before this, li_store_loved_id_for_user(), to store the post ID in the user’s meta, ensuring that they are not able to love a post more than once.

This li_mark_post_as_loved() function will be called by our ajax function that runs when the “love it” button is clicked.

Now we need to write the function that retrieves the number of times a post has been loved. This one is really easy:

1
2
3
4
5
6
7
// returns a love count for a post
function li_get_love_count($post_id) {
	$love_count = get_post_meta($post_id, '_li_love_count', true);
	if($love_count)
		return $love_count;
	return 0;
}

If there is a record of loves, the number is returned, otherwise 0 is returned because the post has never been loved.

There is just one more function to write in this file, and that is the function that listens for our ajax requests and then calls the function that marks a post as loved.

1
2
3
4
5
6
7
8
9
10
11
12
// processes the ajax request
function li_process_love() {
	if ( isset( $_POST['item_id'] ) && wp_verify_nonce($_POST['love_it_nonce'], 'love-it-nonce') ) {
		if(li_mark_post_as_loved($_POST['item_id'], $_POST['user_id'])) {
			echo 'loved';
		} else {
			echo 'failed';
		}
	}
	die();
}
add_action('wp_ajax_love_it', 'li_process_love');

This function uses the WordPress ajax API to process the ajax request sent from our jQuery file (which we haven’t written yet).

When a request is sent from the jQuery, we check to make sure that the ID of the post being marked as “loved” is sent, and also that the nonce (for security) checks out. If everything validates, and our li_mark_post_as_loved() function returns TRUE, then we echo out “loved”. This tells jQuery that everything worked fine and it can do whatever it needs to do (such as dynamically increasing the love count displayed on the page). If something goes wrong, we echo “failed” so that jQuery can tell the user something went wrong.

If you need more help understand what we are doing here, then consult my tutorial on processing ajax requests in plugins.

We are now done with the love-functions.php file. Time to move onto our scripts.php.

Loading the jQuery Scripts

The scripts.php file only contains one function, and it is used to load our jQuery file (for sending ajax requests), and also for defining some variables that will be available to our jQuery script.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function li_front_end_js() {
	if(is_user_logged_in() && is_singular()) {
		wp_enqueue_script('love-it', LI_BASE_URL . '/includes/js/love-it.js', array( 'jquery' ) );
		wp_localize_script( 'love-it', 'love_it_vars', 
			array( 
				'ajaxurl' => admin_url( 'admin-ajax.php' ),
				'nonce' => wp_create_nonce('love-it-nonce'),
				'already_loved_message' => __('You have already loved this item.', 'love_it'),
				'error_message' => __('Sorry, there was a problem processing your request.', 'love_it')
			) 
		);	
	}
}
add_action('wp_enqueue_scripts', 'li_front_end_js');

Since our “Love It” button is only displayed on singular pages when the user is logged in, we only load our jQuery script when on singular pages and our user is logged-in. Remember, we want to be careful to only load our jQuery scripts when they are needed; no other time.

You should be familiar with wp_enqueue_script() by now, but you might not recognize wp_localize_script(). This function is used for making variables (which can be defined in PHP) readable by the jQuery. When we use wp_localize_script(), whatever we pass as the name in the second parameter will be created as an object, and then each of the elements inside of the array, passed as the third parameter, are created as items in the object. When the page is loaded, it will look like this:

love_it_vars {
	'ajaxurl' : 'http://yoursite.com/wp-admin/admin-ajax.php',
	'nonce' : 'nonce_value_here',
	'already_loved_message' : 'Message here',
	'error_message' : 'Message here'
}

This is really cool because it allows us to access each of these variables from our jQuery, but define them in the PHP. Why is this really cool? Well, for one it allows us to define the messages with localization so that any messages displayed through javascript alerts can still be translated. There are a lot of other reasons as well.

Our function is attached to the “wp_enqueue_scripts” action, which loads our files and variables onto the page.

Alright, that’s it. Time for the jQuery.

Writing the jQuery

The jQuery is going to be written in our love-it.js file, which is stored in the includes/js/ directory.

While it might look a little complex, the jQuery is really pretty straight forward. We are going to listen for when the “love it” button is clicked, then we will setup a couple of variables for the user ID and post ID (which you should recall were set with the custom “data” attributes in our display function), and then we will send the data via POST so it can be processed with PHP. There are a couple of other minor things happening, but I’ll explain them in a moment.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
jQuery(document).ready( function($) {	
	$('.love-it').on('click', function() {	
		if($(this).hasClass('loved')) {
			alert(love_it_vars.already_loved_message);
			return false;
		}	
		var post_id = $(this).data('post-id');
		var user_id = $(this).data('user-id');
		var post_data = {
			action: 'love_it',
			item_id: post_id,
			user_id: user_id,
			love_it_nonce: love_it_vars.nonce
		};
		$.post(love_it_vars.ajaxurl, post_data, function(response) {
			if(response == 'loved') {
				$('.love-it').addClass('loved');
				var count_wrap = $('.love-count');
				var count = count_wrap.text();
				count_wrap.text(parseInt(count) + 1);		
			} else {
				alert(love_it_vars.error_message);
			}
		});
		return false;
	});	
});

At the top of the jQuery, we check to see if the button has the “loved” class (meaning it has already been loved); if it does, we return false to prevent the ajax request from firing when it’s not needed.

Next, we setup the variables for the user and post IDs. These are retrieved from the custom “data” attributes. Once we have both of those, we setup a “post_data” object that contains everything that we are sending to PHP. This includes an “action”, which is required by the WordPress ajax API, an item ID (the post ID), a user ID, and a nonce value (for security). Note that the nonce value is retrieved using love_it_vars.nonce; this is how we access the variables we defined with wp_localize_script() in the previous section.

As soon as we have our “post_data” object setup, we use the jQuery $.post function to send the data to WordPress. All of the data is sent to the li_process_love() function, which was the last function we wrote in the love-functions.php file.

Recall in the li_process_love() function we echoed out “loved” or “failed”, depending on whether the “love” was processed successfully or not. This echo is interpreted by jQuery as the response (and the third parameter) of our $.post function.

We use the response to know if the post was successfully loved; if it was, then we add the “loved” class to our button and increase the count displayed in the parentheses. If “response” comes back as “failed”, then we alert the user that there was a problem processing their request.

That’s it! You should have a fully functional “love it” button that you can use to mark any post/page/custom post type as “loved”.

There is just one more thing to build: a widget to display the most loved items.

Building the Most Loved Widget

We are going to make a widget now that will allow us to display a specified number of the most loved items from our site. The most loved items will be displayed in descending order, meaning that those items with the most loves are displayed first.

The widget is pretty simple, though I’m not going to show you how to actually write the whole widget. I’m going to demonstrate how to setup the most loved query; if you need help setting up the widget itself, then consult the tutorial series I wrote on building widgets.

To query the most-loved items, we need to use the meta_key parameter to only pull in items that have been loved at least once. We also tell get_posts() to order the items by meta_value; posts with a higher love count have a higher meta value.

The query looks like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<ul class="most-loved">
<?php
	$args = array(
		'post_type' => 'any',
		'numberposts' => $number,
		'meta_key' => '_li_love_count',
		'orderby' => 'meta_value',
		'order' => 'DESC'
	);
	$most_loved = get_posts( $args );
	foreach( $most_loved as $loved ) : ?>
		<li class="loved-item">
			<a href="<?php echo get_permalink($loved->ID); ?>"><?php echo get_the_title($loved->ID); ?></a><br/>
		</li>
	<?php endforeach; ?>
</ul>

When combined with our widget code, which is placed in includes/widgets.php, everything together looks like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
<?php
 
/**
 * Most Loved Widget Class
 */
class li_most_loved_widget extends WP_Widget {
 
    /** constructor */
    function li_most_loved_widget() {
        parent::WP_Widget(false, $name = __('Most Loved Items', 'love_it'), array('description' => __('Show the most loved items', 'love_it')));	
    }
 
    /** @see WP_Widget::widget */
    function widget($args, $instance) {	
        extract( $args );
        $title 	= apply_filters('widget_title', $instance['title']);
        $number = strip_tags($instance['number']);
 
		echo $before_widget; 
            if ( $title )
                echo $before_title . $title . $after_title; ?>
					<ul class="most-loved">
					<?php
						$args = array(
							'post_type' => 'any',
							'numberposts' => $number,
							'meta_key' => '_li_love_count',
							'orderby' => 'meta_value',
							'order' => 'DESC'
						);
						$most_loved = get_posts( $args );
						foreach( $most_loved as $loved ) : ?>
							<li class="loved-item">
								<a href="<?php echo get_permalink($loved->ID); ?>"><?php echo get_the_title($loved->ID); ?></a><br/>
							</li>
						<?php endforeach; ?>
					</ul>
              <?php 
		echo $after_widget;
    }
 
    /** @see WP_Widget::update */
    function update($new_instance, $old_instance) {		
		$instance = $old_instance;
		$instance['title'] = strip_tags($new_instance['title']);
		$instance['number'] = strip_tags($new_instance['number']);
        return $instance;
    }
 
    /** @see WP_Widget::form */
    function form($instance) {	
        $title = esc_attr($instance['title']);
        $number = esc_attr($instance['number']);
        ?>
         <p>
          <label for="<?php echo $this->get_field_id('title'); ?>"><?php _e('Title:'); ?></label> 
          <input class="widefat" id="<?php echo $this->get_field_id('title'); ?>" name="<?php echo $this->get_field_name('title'); ?>" type="text" value="<?php echo $title; ?>" />
        </p>
		<p>
          <label for="<?php echo $this->get_field_id('number'); ?>"><?php _e('Number to Show:'); ?></label> 
          <input class="widefat" id="<?php echo $this->get_field_id('number'); ?>" name="<?php echo $this->get_field_name('number'); ?>" type="text" value="<?php echo $number; ?>" />
        </p>
        <?php 
    }
}
add_action('widgets_init', create_function('', 'return register_widget("li_most_loved_widget");'));

Place the newly registered “Most Loved Items” widget in a widgetized sidebar and see the effect.

Concluding Thoughts

This plugin works really, really well for tracking items that the most loved across your website. It is also really great for giving your users an easy way to provide positive feedback, without requiring that the need enter any information.

There are certainly some areas it can be improved:

  • Update the plugin so that users who are not logged-in can “love” items as well
  • Style “love it” buttons to be visually appealing, instead of plain links
  • Add options to the plugin to allow users to adjust where the “love it” button is displayed

Sometime in the coming weeks, I will be releasing an enhanced version of this plugin that includes the suggested improvements above.

Note, you can also see the exact effect created with this plugin at the bottom of this post. See the “Love It” link? Click it :)

The complete, Pro version of this plugin is now available.

Download the Plugin

Enjoy!

  1. Blanka

    Thanks, Pippin!
    It make sense, of course, but i don’t know why only i can’t see it in Firefox.
    In Chrome & IE i can’t see anything. Is not compatible?

    Thanks again!

    • Pippin

      Are you logged in in both browsers?

  2. Blanka

    No, i was logged only in Firefox.
    This means that only if you are logged on the website you can see that link?

    Thanks!

    • Pippin

      The link is only shown to logged in users. If you want to support non-logged-in users, you have to either modify the plugin or purchase the Pro version.

  3. Blanka

    OK, i understand.
    Thank you very much for your help, Pippin.

  4. Dries

    hey,

    It’s great, but for some reason the top-loved widget doesn’t show items loved more then 9 times, when it goes over 10 ‘loves’ it dissapears from the list.
    Do you know what could cause this?
    Tanks!

    • Pippin

      Did you follow the tutorial or download the complete plugin from WordPress.org?

    • Dries

      Hi, thanks for the reply, I used the plugin from the wordpress website, but the code seems the same to me.

    • Pippin

      It is nearly identical, just wanted to check to see if there was a possibility of copy-and-pate error.

      Take a look at the last code block above. Try changing line 28 to this:

      ‘orderby’ => ‘meta_value_num’,

  5. Dries

    Wonderful! That did the trick.
    Thank you a lot for the support you give for a free tutorial!
    Have a nice day.

  6. geneellis

    Hey Pippen. I copied this line by line and I can’t get it to work.I like the “love it” link and it doesn’t do anything but places an “#” in my browser bar and goes to the top of the screen. I had the same behavior with another tutorial that I copied from this website. However, if I download and install the plugin, it works fine. Is the code different or am I doing something wrong? I don’t understand how I can’t get even the simplest AJAX code to work, but if I download the plugin, it works fine.

    • Pippin

      The code in the tutorial and the plugin are nearly identical. Can you give me a live URL so that I can take a look?

    • geneellis

      Hey thanks for the response pippin. I found the problem. It had to do with the way the JS file was being loaded. If I recall correctly, it is being loaded in different between the code above and the downloaded plugin. All is working now. Thanks!

    • Pippin

      Great!

  7. Martin

    Hi
    How can I integrate an “unlove” function? I duplicated the li_mark_post_as_loved-function which now decrements the $love_count. But I don’t know where to call the function.
    Would you mind helping me? Thanks.

    • Pippin

      You will call the function via ajax. Do you see/understand how the love it function is initially called?

  8. Martin

    Well, in the love-it.js a onClick handler checks whether it’s already loved or not. If not, the js collects some data. From this point, you have to assist me, please.

    • Pippin

      In the JS, do you see where the action is defined?

    • Martin

      Yes, I do. It starts on line 16, right?

    • Martin

      I get stuck on this “All of the data is sent to the li_process_love() function” … I don’t get it in the JS.

    • Pippin

      Ok let’s see if I can clarify this for you a little bit:

      1. The action ID is set in the JS (where it says action: )
      2. This action is passed to the $.post function, which sends the data to the server
      3. The data sent in two is picked up by the PHP with the function tied to “add_action(‘wp_ajax_….'”.

      Does that help?

    • Martin

      A light dawned on me.
      I did not realize the “wp_ajax_$youraction”.
      Thanks a lot, Pippin.

    • Pippin

      Great!

  9. Martin

    I get stuck on this “All of the data is sent to the li_process_love() function” … I don’t get it in the JS.

  10. Jean-Marie

    This is really helpful- thanks for sharing. I have a couple of suggestions for anyone who wants to build on what you’ve started:

    1) The li_mark_post_as_loved() function increments the count of times an item has been loved regardless if the user can love the item or not. This is only really important given #2:

    2) Currently the li_store_loved_id_for_user() function doesn’t check if an item has been loved already. This is somewhat mitigated on the front end by not displaying the “love it” link if it has been loved by the user before, but currently it *is* possible for an item to be loved more than once via this function and for the post ID to be added multiple times to the array of loved items. Personally I would insert some logic in this function that prevents this (probably with a similar if(in_array()) evaluator).

    3) Currently the .js scripts don’t dynamically update the front-end link text on success or failure. You could add .ajaxStart and .ajaxStop handler functions here (or any of the standard jQuery Ajax event handlers) to modify the output of the front-end dynamically rather than jQuery alert() messages. (This isn’t a criticism– just ideas for anyone who wants to modify this themselves.)

    • Pippin

      Thank you for the feedback! Those are great for anyone that wants to extend the plugin created in the tutorial.

  11. Diego

    Hi, is there a way to show on the widget the most loved post but from a period of time, for example the most loved this week (from monday to sunday)? Any help would be great, excelent plugin by the way!

    • Pippin

      No, sorry.

    • captTeemo

      You may need to extend this plug-in using separate tables instead of using usermeta and postmeta stock tables from WP. Pippin wrote a series on wphub.com here

  12. VC

    Can someone please tell me if it is possible to write this type of functionality in an environment where it’s not possible to use PHP or create/write to a database on theURL’s primary server?

    For example… hosting database & PHP scripts on separate URL or by using something like sqlite and/or something based purely and/on Javascript or Ajax or JSON or Ruby… or, or or?

    Any advice on where to explore would be appreciated… Please and thank you!

    • Pippin

      Certainly possible but that goes well beyond the scope of this tutorial, sorry.

  13. Joe

    Hi Pippin.

    Thanks for this tutorial. I’ve loved modifying it to my needs! I have one small issue: When the user loves something, the love is successful but the ajax response in returning `$love_count` gives me an NaN (Not a number) error. Any idea why this would be? I’m pretty new to Ajax stuff. I’ve put my modifications on Github. I reckon it might be to do with the edits I made in display-functions.php but I’ve got a bit stuck! Any help much appreciated! Thanks.

  14. Joe

    Please disregard my last message. Some foolishness occurred where I accidentally edited the love-count span wrong. I’m now trying to implement an un-love function. I’ve got it working (unloves) but doesn’t return the right Javascript alert, and the Ajax returns twice for some reason. Anyone who’s made headway, could they kindly take a look? Github. Thanks.

Error: Please enter a valid email address

Error: Invalid email