Allow users to like content

As part of my recent site redesign, I wanted users to be able to “like” content without having to leave a comment, use social media, or have a user account.

I think this will be especially useful for the Code Snippets section of the site which doesn’t have comments enabled. When viewing the Code Snippets archive, liked content has a yellow icon next to it, making it easy to see your favorite snippets.

I wanted it to be like the “+1” reaction you can leave on GitHub comments (screenshot). You can see it in action at the bottom of this post, and I’ve released the code as a plugin (BE Like Content).  It has no styling, so you can make it look however you like.

Customization with Filters

  • You can change the allowed post types and text used (zero, one, many likes) using the be_like_content_settings filter (see here).
  • You can customize the number displayed on frontend using the be_like_content_display_count filter. For instance, add commas or round to significant figures. I used this to add a thumbs up icon before the number.
  • You can disable the JS from loading with add_filter( 'be_like_content_load_assets', '__return_false' );. I moved the Javascript to my theme’s JS file (one less file to load), and I’m adding additional functionality – marking liked code snippets differently on the CPT archive.
  • A dashboard widget showing Popular Content is included. You can customize the query arguments using be_like_content_popular_widget_args

Using Cookies

I’m using the JS Cookie library to store your liked posts as a cookie. This minimizes duplicate likes, and when you load a page you’ve already liked I’m able to mark it as “liked”. Users can get around this by clearing their cache or using a private tab, but the count itself isn’t important enough that I care. I don’t recommend this approach for something that users would want to game (ex: voting on posts in a contest).

The library is very simple to use. To get a cookie you run Cookies.get( cookieName ); where cookieName is the name you’ve given to your cookie. When you’re ready to update it, run Cookies.set( cookieName, value, { expires: 365 } );. You can see I’m using it here.

One thing that tripped me up was how Javascript turns arrays with single items into strings. After liking the first post, I’d save a cookie with an array of that post ID, but on the next pageload the cookie would be a string, breaking my code. I got around it by saving the cookie as a JSON string, then parsing the JSON when retrieving the cookie.

AJAX Updating

My post on Infinite Scroll goes into a lot more detail on how to do AJAX requests. This is a really simple implementation.

On the actual “like” button I added a data attribute containing the post ID. When you click it, we check to make sure you haven’t already liked it (by looking at the cookie) and that we’re not in the process of liking it (you clicked it twice). If everything checks out, we pass the post ID and `be_like_content` action to admin ajax. That runs the update_count() method which grabs the current count, adds one, and updates post meta (see here).

Try it Out

If you like the idea, please install the plugin on your site and let me know how it works.

ajax plugin

Receive New Posts by Email

Comments

      1. I’m sorry, I’ve already shown you all the code I’m using to implement it. If you need additional help, I recommend you hire someone on Codeable.

        1. Hi Bill,

          Thanks for the snippets. Today I came around to implementing your plugin and use your snippets. The reason the hand isn’t showing when just copying the snippet you provided, is that get_template_directory() returns the parent theme’s directory, being genesis, instead of the childtheme’s that is probably used on top of it.

          Since the genesis frameworks is meant to be used in combination with a genesis child-theme, It should probably use get_stylesheet_directory() instead of get_template_directory(). Anyways, after that small change it seems to work fine.

          Thanks, as always,

          Hans

          1. Yes, if your icon is located in a child theme, you should use get_stylesheet_directory(). This website is built as a standalone custom theme so the assets go in the main (parent) theme directory.

            While I could technically use get_stylesheet_directory() as well, it would stop working whenever I make a child theme for my website, which I do often for WordPress meetup talks.

          2. I understand, Bill, why it is different when you don’t use genesis. My input was based on pii way asking the questions and stating that he was using the genesis Framework. He didn’t seem to understand why it wasn’t working.

            My install works like a charm now, b.t.w., and people are using it. Of course I gave you props and thanks in the intro-blog I wrote about it, explaining our audience what to do with this new feature.

            I choose to put a more explanatory sentence next to the hand, since it is such a new feature for websites that it might not be self-explanatory, and I used the be_like_content_settings you described to implement that. Since I wasn’t sure how to change parts of the settings array, I ended up just copying the function your code inputs in the apply_filters call and returning a new settings array.

            Perhaps it would be nice to be able to show on archive pages how much thumbs up a post has, like we show the amount of comments. Is that something you have done already and have a snippet for? Or would such an addition be ill advised and costly for page loading?

            Your plugin adds a new feature on which to score posts as being popular. Being the easiest for visitors to use, and interaction weighing more than just opening a page, I ques basing it on this likes score is useful. A more complete analyses would probably involve both the number of visits and the number of interactions (social shares, comments and likes) in some way. At this moment I’m using the top10 posts plugin for showing popular posts, but perhaps I’ll change to your widget at some point.

            There is one thing that perhaps needs some attention still, but perhaps that’s just my implementation in the theme… When someone clicks on the hand, the result is that only the new number of likes is displayed instead of the previous string from the settings. That settings-string is only shown after a refresh of the post. It is something I will probably would like to change at some point, because I would like a more clear visual reaction and probably just using the appropriate setting or perhaps a string like “Thanks for the like” or something, what might even be a nice supprice. For now I can live with it.

            Next to that small point, and with great help of your explanation, snippets and filters, it was an easy implementation even for me. So thanks for that.

            Hans

            1. Yes, you can display the total count on archive pages. It’s stored as post meta, so simply call get_post_meta( get_the_ID(), '_be_like_content', true );.

              It won’t affect the performance / page load because WP already pulls all metadata associated with a post when it queries for that post. The data is already cached.

              This is the code that runs when the like button is clicked. It calls the maybe_count() method which uses the strings you specify in the settings array.

              You could probably use the filter to check if DOING_AJAX or is_admin(), and if true you’d know this was after a “like” (as opposed to when the page first loads and builds the string showing the count). You could then change the string to “Thanks for the like”.

  1. Great Idea, Bill. Thanks so much for sharing the code including the additional snippets to implement it in genesis framework. Much appreciated.

Leave a comment