Implementing hreview in your WordPress theme

In his previous post here on Yoast, Frederick explained why you should use Microformats to get Rich Snippets showing for your site and increase the CTR from Google. In the comments of that post, people were asking if there are plugins to easily implement this in your theme. While those are probably a bit hard to do, I though it would be good to just do a tutorial on how I implemented hreview in my theme.

How I “activate” a hReview

I alluded to it in last tuesdays podcast with Dougal Campbell: When I add a custom field “rating” to a post, my theme now automatically marks up that post as an hreview microformat. So it’s as simple as this:

Rating Custom Field

The rating is between 0 and 5, because that way Google understands it best and we don’t have to give Google any extra metadata about it.

The hreview_echo function

To make this whole process easy, I’ve created a function in my functions.php file called hreview_echo. It looks like this:

function hreview_echo($val) {
  global $post;
  $rating = get_post_meta($post->ID, 'rating', true);
  if ($rating) {
    echo $val;
  }
}

We’ll use this function on the several places where we need to add extra classes to make up the hreview.

The wrapper class: hreview

The first class we should add is the wrapper for the entire microformat: the hreview class. This should be on the div surrounding the post (this div should include the title and author). In the default theme (and in mine) it looks like this:

<div <?php post_class() ?> id="post-<?php the_ID(); ?>">

In this case the class of this div is actually put out by the WordPress core post_class() function, so we’ll need to hook into that function. Luckily it allows us to easily do that using a filter, which we’ll do using the functions below, which you can drop into your functions.php too:

function hreview_post_class($classes, $class, $post_id) {
  global $post;
  $review = get_post_meta($post->ID, 'rating', true);
  if ($review) {
    $classes[] = 'hreview';
  }
  return $classes;
}
add_filter('post_class','hreview_post_class',10,3);

If your theme doesn’t use the post_class() function, it’s even easier! Let’s say your post div looks like this:

<div class="post">

You can just use our hreview_echo() function:

<div class="post<?php hreview_echo(' hreview'); ?>">

The item reviewed: the title

Next up in the line of things we have to add a class to is the post title, it needs two classnames: the item and fn classes. In my case it looked like this:

<h1><?php the_title();?></h1>

This is easily turned into the following, again using the hreview_echo function we created before:

<h1 <?php hreview_echo(' class="item fn"'); ?>><?php the_title();?></h1>

The date of the hReview

For the date we’ll have to work it a bit. The hreview microformat determines the date should be in ISO date format. Meaning the date should look like: 2010-03-01. Your theme probably has another way of showing the date, I know mine does. My date looked like this:

<span class="date"><?php the_time('d F Y');?></span>

Now to make it so that it can still look like that but we can also give the microformat the correctly formatted date, we’ll use a trick: by adding a span with a class of value-title and then adding the correct date in the title of that span, microformat parsers will ignore the other content and pick the value from that title.

So we’ll turn it into this:

<span class="date<?php hreview_echo(' dtreviewed') ?>">
  <?php
      hreview_echo('<span class="value-title" title="'.
        get_the_time('Y-m-d').'"/>');
      the_time('d F Y');
  ?>
</span>

This outputs:

<span class="date dtreviewed">
  <span class="value-title" title="2010-02-10"/>
  10 February 2010
</span>

That’s a nice, non-intrusive solution, right?

The reviewer: the author

The next class we need to add is the reviewer class, as this is the author of the review, that’s a simple one too: it’s the author of the post. In my theme, my author block looks like this:

<span class="author"><?php the_author(); ?></span>

Now you’ll get by now what we’ll do:

<span class="author<?php hreview_echo(' reviewer'); ?>">
  <?php the_author(); ?>
</span>

Easy does it, right? You can basically do something like this with any kind of showing the author’s name. Other functions that might be used in your theme are for instance the_author_link() or the_author_posts_link().

The content of the review

We’ve done more than half of it now! Let’s get going with the contents of the review, in the microformat, this needs the class description. In my theme, just like in the default kubrick theme, the content is wrapped in the following div:

<div class="entry">

You’ve guessed it by now haven’t you? Here we go:

<div class="entry<?php hreview_echo(' description'); ?>">

By the way: if you want to mark up articles on for instance your fronpage as hreview too, and you use excerpts there instead of full articles, like I do, you should use summary, instead of description:

<div class="entry<?php hreview_echo(' summary'); ?>">

Finally: the rating!

And now, finally, it’s time for us to add the rating, because that’s what it’s all about right? There’s all sorts of ways to display a rating, I have chosen to do it in HTML that looks like this:

<div class="rating">My rating:</div>
<div title="4.5 out of 5 stars" class="rating_bar">
  <div style="width:90%"></div>
</div>

Which outputs this:

My rating:



The second div (class rating_bar) displays the rating, and it contains the empty stars. The div within that contains the yellow stars, and fills the stars up to where they need to be.

The CSS for these 3 divs looks like this:

.rating {
  float: left;
  margin-right: 10px;
}
.rating_bar {
  float: left;
  width: 55px;
  background: url(images/stars.gif) 0 0 repeat-x;
}
.rating_bar div {
  height: 12px;
  background: url(images/stars.gif) 0 -13px repeat-x;
}

Download the (sprited) image of the stars here.

Now we’ll need to do two things: dynamically output the size of the inner div within rating_bar, and make the rating readable for a microformat parser.

To display the rating, because it’s a value between 0 and 5, we’ll multiply it by 20. To make the output parseable by a microformat parser, we’ll use the same value-title trick we used before. Finally, we’ll turn this all into a function to display the rating, which you can drop into your functions.php, just like the two functions before.

<?php
function display_hreview_rating() {
  global $post;
  $rating = get_post_meta($post->ID, 'rating', true);
  if ($rating) {
?>
    <div class="rating">
      My rating:
      <span class="value-title" title="<?php echo $rating; ?>"/>
    </span></div>
    <div title="<?php echo $rating; ?> out of 5 stars" class="rating_bar">
      <div style="width:<?php echo ($rating*20); ?>%"></div>
    </div>
<?php
  }
  return $output;
}
?>

So, now you can just use the display_hreview_rating() function anywhere in your post where you want to display the rating. If there is no rating, it won’t display anything.

Testing your hreview & rich snippets

Testing your hreview markup can be done with multiple tools, but I myself found the Google Rich Snippets tool to be extremely useful. If you use Quix, just type ‘snippet’ on the post you want to test! In my case it outputs a snippet like this for my review of a WordPress backup plugin:

Rich Snippet hreview

Bonus: pricerange and tags

As you can see in the above snippet, it includes something that is not documented anywhere in the official Google documentation for reviews, but that Google does support: the pricerange.

Credit where credit is due: I first found this pricerange attribute when my colleague Eduard pointed me to this post by the SEOgadget guys, which pointed to this Knol. It’s extremely useful and seems to basically allow for all sorts of text. People use it to display a pricerange in a €€ – €€€ style, or to display a “real” pricerange, like € 100 – € 150. In case of an individual review, you can just use it to tell what you paid for it.

Since what I paid for a product is not a real part of my theme, I just make it simple: when I tell that the plugin is free, I mark up that line as:

this plugin is completely <span class="pricerange">free</span>

If you do want to put the value into a custom field and display it, you could easily adapt one of the functions above to do that, I’ll leave that as an exercise to you, the reader.

Another thing I found that Google recognizes is the class tags. That’s really easy to do: I just added the class ‘tags’ around my tags. I don’t know how Google uses that though, haven’t seen it anywhere in the wild.

A final note on Rich Snippets

If you’ve modified your theme to mark up as hreview, please make sure to use this form to let Google know that you have. They might not show it if you don’t fit their test segment though, because as Google states in the Knol:

Currently, review sites and social networking/people profile sites are eligible. We plan to expand Rich Snippets to other types of content in the future.

I hope you’ve found this post useful, let me know in the comments if you’ve used it to add hreview to your (premium) theme, and feel free to post links to examples, I’d love to see them! If you’re wondering: all code examples on this site, unless specifically otherwise stated, are MIT licensed: free to distribute, free to modify. Please do add a link to where you got the original code though.

It’s my humble opinion that additions like these should make it into all the premium themes, because that’s what really makes a premium theme premium, in my opinion. Happy coding!

Tags: , , , , ,


Yoast.com runs on the Genesis Framework

Genesis theme frameworkThe Genesis Framework empowers you to quickly and easily build incredible websites with WordPress. Whether you're a novice or advanced developer, Genesis provides you with the secure and search-engine-optimized foundation that takes WordPress to places you never thought it could go.

Read our Genesis review or get Genesis now!

30 Responses

  1. Marty MartinBy Marty Martin on 28 February, 2010

    Very timely Yoast. I’m implementing a WPMU-powered city portal/magazine website with, guess what, restaurant reviews! I’ll go back in and tweak my review posts! Just need to add a conditional in there for my review category. Cheers!

    • Joost de ValkBy Joost de Valk on 28 February, 2010

      Looking forward to it Marty, I hope you’ll drop a link here once you’re done!

  2. Jami GibbBy Jami Gibb on 28 February, 2010

    This is extremely helpful, Yoast! Thanks for such a detailed explination. I’m going to give it a try on one of my review sites.

    • Joost de ValkBy Joost de Valk on 28 February, 2010

      Let us know how it goes Jami, and please do drop a link here if you succeed :)

  3. BaptisteBy Baptiste on 28 February, 2010

    Hello Yoast, nice tutorial !
    I was wondering if this technique would and could enable to use USER ratings of a given post (i use the WP-Rating extension of Lester Chan).
    I currently declare the average rating given by my visitors to my posts, as a hReview rating.
    Is it a proper use of the hReview microformat ?

    Thanks for your reply, and thanks again for the tut !

    Regards,
    Baptiste

    • Joost de ValkBy Joost de Valk on 28 February, 2010

      Hey Baptiste, if you’re aggregating scores you should be using hreview-aggregate. The info for that can be found on the same Google info page.

  4. Jay TilleryBy Jay Tillery on 28 February, 2010

    I started to implement this on one of my Mixed Martial Arts gear review websites this weekend. Awesome post, YOAST!

    • Joost de ValkBy Joost de Valk on 28 February, 2010

      Good stuff Jay, which site is it? :)

  5. BenBy Ben on 28 February, 2010

    Thanks for this, I posted my first game review, tried it on that and it works like a charm, Google even converts my review score from a % out of 100 to x out of 5.

  6. Jami GibbBy Jami Gibb on 1 March, 2010

    Yoost,

    I’m having trouble getting that final function to work. It’s not parsing correctly. Am I supposed to put that entire function plus the div’s right into my function.php?

    • Joost de ValkBy Joost de Valk on 1 March, 2010

      It should be copied straight to your functions.php indeed, although you might have to remove some php tags… What kind of error are you getting?

      • Jami GibbsBy Jami Gibbs on 1 March, 2010

        Hi Yoast! (And sorry for spelling your name wrong before. I certainly know better and it was a slip of the finger. I even spelled my own last name wrong! It was one heck of a day, I wager.)

        I did indeed removed the php opening and closing tags. The error is occurring where the first div starts. Could it be those quote marks ” that’s throwing it off? Shouldn’t those be in single quotes ‘ ?

        • Jami GibbsBy Jami Gibbs on 2 March, 2010

          Just a quick update to let you know I got it working just fine. It was simply a matter of incorrectly placing an ending php tag. Thanks for responding though and a really great tutorial! :)

  7. Dave DoolinBy Dave Doolin on 1 March, 2010

    Timely.

    Just spent all weekend working on hRecipe. It’s coming along.

    I should fork the hReview WordPress plugin and clean it up with the code in hRecipe. Maybe some other weekend.

  8. LuciBy Luci on 1 March, 2010

    Great post, Joost! Nicely explained and in detail – with a stars sprite! – as soon as I’ve put it up into a theme I’ll post it here. Can’t wait to get it cracking!

  9. RilwisBy Rilwis on 1 March, 2010

    Very impressive! I like the way you show stars ratings. Thanks for this post.

  10. Bradley DavisBy Bradley Davis on 1 March, 2010

    Awesome tutorial Joost, will have to work this into a review site in the future.

  11. CraigBy Craig on 1 March, 2010

    Very cool. Wondering if the price range function would be appropriate to use on a lead gen site for services…? (just not sure if it would add or detract from the click through). I could however definitely see reviews being appropriate for service industry pages

    and….re; “seeing the price range displayed in the wild”….perhaps this is incorporated into catalogue ecommerce feed listings (for affiliates) somehow

  12. Ali | DudutBy Ali | Dudut on 2 March, 2010

    thanks alot bro..

  13. Mladen MilentijevicBy Mladen Milentijevic on 2 March, 2010

    You just opened new horizons for me and since I’m developing an events site I’ll try to implement hCalendar based on your solution for hreview.
    Thanks.

  14. Hamilton RochaBy Hamilton Rocha on 23 March, 2010

    Nice tips, will test it.

  15. Craig LayneBy Craig Layne on 26 March, 2010

    Thanks for the great guide. I spent most of the morning implementing hreview on my movie blog (http://www.movieguys.org/). I wound up not using much of your examples though. I implemented it to work with GD Star Ratings, and to only show on certain posts, that are tagged review.

    Thanks for the great tutorial.

Trackbacks