Create A WordPress Bookshelf Plugin

About The Author

Kailan Wyatt is a Web Developer that focuses on Opensource technology. With a love for WordPress and Joomla, he spends his time developing Web Applications on … More about Kailan ↬

Email Newsletter

Weekly tips on front-end & UX.
Trusted by 200,000+ folks.

This tutorial explains how to create a WordPress bookshelf plugin that displays books on a shelf like Smashing Magazine’s eBook page.

Some key WordPress functionality will be showcased throughout the tutorial that could benefit your own project.

The article covers how to create post types, shortcodes and meta fields using WordPress’ functionality and how to combine them to make a fully configurable plugin. To begin, we’ll explain how to register the plugin, develop the back-end functionality and then create the front-end display using shortcodes.

Setting Up The Plugin

The standard method of registering a plugin in WordPress is to add some information to the header of the file. Create a file named sm_books.php, and add the information below to it. Note that the information being registered is “Plugin Name,” “Author,” “Version,” etc. This information will be used to tell WordPress about the plugin so that the plugin can be activated and displayed in the plugin management screen.

Plugin Name: SM Books
Plugin URI:
Description: Displays Books and books
Author: B4uCode
Version: 1.0.0
Author URI:

Book Plugin

To learn more about creating a plugin, check out “WordPress Essentials: How to Create a WordPress Plugin.”

Register The Post’s Type

In order to add the new book system, we will register a new custom post type using the register_post_type function. To access this function, we will trigger it using the add_action function. Add the following to the sm_books.php file:

//Register Book Post Type
add_action( 'init', 'create_sm_book_type' );
function create_sm_book_type() {
   register_post_type( 'sm_books',
         'labels' => array(
            'name' => __( 'Books' ),
            'singular_name' => __( 'Book' )
      'public' => true,
      'has_archive' => true,
      'supports' => array('title','editor','thumbnail')

This snippet is a basic way to create a post type. The register_post_type( $post_type, $args ) function takes two parameters: $post_type and $args. The first parameter is a 20-character string that will be used for the name of the new type. The default post types in WordPress are “Post,” “Page,” “Attachment,” “Revisions” and “Navigation Menus.” These default names cannot be used when creating a custom type, so we will use sm_books. The second parameter is an optional array that stores a multitude of options for the post type. The array accepts “labels” that will be used and seen while using sm_books, as well as options available for the post type, such as exclude_from_search, show_ui and much more.

Add Books Category

For this tutorial, we will add a custom set of categories for the books. This set is referred to as a “taxonomy,” and we will create it with the register_taxonomy function, which we will call sm_book_category. The categories enable us to assign our entries to different categories for displaying on the screen. Just as with our previous snippet in the file, we will use add_action to trigger our function. Also, register_taxonomy($taxonomy, $object_type, $args) is very similar to the register_post_type function, with its three parameters:

  1. $taxonomy A string with no capital letters or spaces.
  2. $object_type Defines the post type that this new taxonomy will be attached to.
  3. $args An optional array that holds options and labels similar to what we see in the register_post_type function.
//Add Book Categories
add_action( 'init', 'sm_book_taxonomies', 0 );
function sm_book_taxonomies(){
   register_taxonomy('sm_book_category', 'sm_books', array(

Add Meta Fields

Meta Data Fields

As you may have noticed, each book has different attributes, consisting of prices and links. We will add these attributes as custom meta data fields using the add_meta_boxes action in WordPress. At the moment, we will also add the save_post action to save these fields. Once we’ve triggered our function, the add_meta_box( $id, $title, $callback, $post_type, $context, $priority, $callback_args ) function will establish the “ID,” “Name” and “Description” of the meta box area. The other $post_type parameter determines what post types the meta box should appear in; and for the $callback, we will use the sm_bk_info_box function, which will render the HTML output of form fields.

add_action( 'add_meta_boxes', 'sm_book_extra_box' );
add_action( 'save_post', 'sm_books_save_postdata' );

function sm_book_extra_box() {
      __( 'Book Information', 'sm_bk_info_box' ),

/* Prints the box content */
function sm_bk_info_box( $post ) {

   $price = get_post_meta( $post->ID, 'price', true );
   $sale_price =  get_post_meta( $post->ID, 'sale_price', true );
   $link_amazon =  get_post_meta( $post->ID, 'link_amazon', true );
   $link_google =  get_post_meta( $post->ID, 'link_google', true );
   $link_apple =  get_post_meta( $post->ID, 'link_apple', true );

   // Use nonce for verification
   wp_nonce_field( plugin_basename( __FILE__ ), 'sm_book_noncename' );

  <label for="price">Price
  <input type="text" name="price"
   id="price" size="10" value="<?php echo $price; ?>" />
  <label for="sale_price">Sale Price
  <input type="text" name="sale_price"
   id="sale_price" size="10" value="<?php echo $sale_price; ?>" />
  <label for="link_amazon">Amazon Link
  <input type="text" name="link_amazon"
   id="link_amazon" size="25" value="<?php echo $link_amazon; ?>" />
  <label for="link_google">Google Link
  <input type="text" name="link_google"
   id="link_google" size="25" value="<?php echo $link_google; ?>" />
  </label for="myplugin_new_field">
  <label for="link_apple">Apple Link
  <input type="text" name="link_apple"
   id="link_apple" size="25" value="<?php echo $link_apple; ?>" />

To save the meta data fields that we created previously, we will create the sm_books_save_postdata function that we defined in our save_post action. Within this function, we will check for submitted post data and update the post meta data using the update_post_meta function. Add the following snippet to the sm_books.php file to give the plugin an update-able set of custom fields:

function sm_books_save_postdata($post_id){
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE )

   if ( !wp_verify_nonce( $_POST['sm_book_noncename'],
   plugin_basename( __FILE__ ) ) )

    if ( !current_user_can( 'edit_post', $post_id ) )

    if( isset( $_POST['price'] ) ){
      update_post_meta( $post_id,'price',
      esc_attr( $_POST['price'] ) );
     if( isset( $_POST['sale_price'] ) ){
      update_post_meta( $post_id,'sale_price',
           esc_attr( $_POST['sale_price'] ) );
   if( isset( $_POST['link_amazon'] ) ){
      update_post_meta( $post_id,'link_amazon',
           esc_attr( $_POST['link_amazon'] ) );
   if( isset( $_POST['link_google'] ) ){
      update_post_meta( $post_id,'link_google',
           esc_attr( $_POST['link_google'] ) );
   if( isset( $_POST['link_apple'] ) ){
      update_post_meta( $post_id,'link_apple',
           esc_attr( $_POST['link_apple'] ) );

The update_post_meta takes the post’s ID as the first argument, the key to update as the second argument and the value to be saved as the third argument.

Add Featured Post

For our custom book system, we will add an option for a thumbnail, which will be used to show the book cover on our shelf. We will use the featured post’s thumbnail to accomplish this, and we’ll set the image size that we intend to use with the add_image_size function.

//Enable Thumbnail
if ( function_exists( 'add_theme_support' ) ) {
   add_theme_support( 'post-thumbnails' );
      set_post_thumbnail_size( 150, 150 );
      add_image_size( 'book-thumb', 84, 107, true );

The name of the thumb that we will be referencing is book-thumb, and the size that we will try to resize to is 84 × 107 pixels. These are optional, but based on what we’re going for, the numbers suit our needs.

Further Reading on SmashingMag:

Add Shortcode

Now that we’ve created the administrative side of the plugin, we will create the front-end design. For this tutorial, we will use a WordPress shortcode to add our book listing to the page. Our shortcode will look like the following on any page:

[sm_books category="coding"]

The shortcode above will be used to display the list of books in the category of “coding.” Note that “coding” is the slug of the custom taxonomy that we created. In the end, the plugin will be able to list all of the books if we leave out the category attribute of the shortcode.

Now, let’s move on to making the shortcode work. Add the following code to the sm_books.php file:

function sm_display($atts) {
   extract( shortcode_atts( array('category' => ’), $atts ) );
   $args = array('post_type'=>'sm_books', 'sm_book_category'=>$category);
   $posts = new WP_Query( $args );
   $html = '<div class="sm_holder"><div class="shelf"><div class="innerDiv" id="sm_book_1">';

   // Book Loop
   if ( $posts->have_posts() ) : while ( $posts->have_posts() ) : $posts->the_post();
      $book_cover = get_the_post_thumbnail(
   $html .= '<a href="'.get_permalink().'" class="books">'.$book_cover.'</a>';
   endwhile; endif;

   $html.='</div></div><table class="sm_book_tbl" cellspacing="0" cellpadding="0">';

   // The Loop
   if ( $posts->have_posts() ) : while ( $posts->have_posts() ) : $posts->the_post();

      $price =  get_post_meta( get_the_ID(), 'price', true );
      $sale_price = get_post_meta( get_the_ID(), 'sale_price', true );
      $link_amazon = get_post_meta( get_the_ID(), 'link_amazon', true );
      $link_google = get_post_meta( get_the_ID(), 'link_google', true );
      $link_apple = get_post_meta( get_the_ID(), 'link_apple', true );
      $html.='<tr><td class="title"><a href="'.get_permalink().'">'.get_the_title().'</a><br>';
      if ($link_amazon):
         $html .= '<small><a style="color:#999" href="'.$link_amazon.'">Amazon</a>';
      if ($link_google || link_apple):
         $html .=' | ';
         $html .='<a style="color:#999" href="'.$link_google.'">Google</a></small>';
         $html .=' | ';
         $html .='<a style="color:#999" href="'.$link_apple.'">Apple</a></small>';
      $html .= '</td><td>';

      if ($sale_price && $price) {
         $html .= $sale_price.'<br />';
         $html .= '<span class="old_price">'.$price.'</span>';
      } elseif ($price) {
         $html .= $price;
      } else {
         $html .= ’;
      $html .= '</td>
      <td class="cart">
         <a style="margin:0px" class="sm_cart_button" href="'.get_permalink().'">Add to Cart</a>

   endwhile; endif;

   $html .= '</table>';
   $html .= '</div>';
   return $html;

In the snippet above, we have created a couple of loops that will be rendered when the shortcode is entered. By instantiating the WP_Query class, we are creating a couple of loops to display the books. The arguments that we will use are post_type of sm_books; then, we will use the argument of sm_book_category, which is querying a taxonomy. The value we add will be derived from the shortcode.

The first loop renders the book’s cover in a div where the shelf image will be displayed. The second loop places a set of rows below the shelf and outputs some information about each book. The template tags are used as follows:

  • get_permalink() Fetches the permalink.
  • get_the_ID() Fetches the post’s ID, which is combined with get_post_meta to get the meta fields.
  • get_the_title() Fetches the title.

The final bit for the shortcode is the action that actually registers the shortcode. The first argument is the string that will be written to call the shortcode. The second is the function that will be executed. Add the following below your function:

add_shortcode( 'sm_books', 'sm_display' );

Styling Our Listing

Looking at what we have so far, you can imagine how out of place everything looks. Therefore, at this stage, we will add some CSS to style our output. Create a folder named sm_books. Then, create a file named style.css, and add the following code:

.sm_holder {
   padding: 0px;
   border-bottom: 5px solid #41B7D8;
   width: 630px;
div.shelf {
   background-image: url(shelf_bg.jpg);
   display: block;
.shelf div.innerDiv {
   padding: 0px 34px;
   width: 100%;
.shelf .books img {
   margin-right: 10px;
   padding-top: 15px;
   margin-bottom: 11px;
span.old_price {
   color: #E53B2C;
   text-decoration: line-through;
.sm_book_tbl {
   margin: 0px 20px 0px 0px !important;
   width: 100%;
   background-color: #f3f3f3;
   border: 1px solid #e5e5e5
.sm_book_tbl td.title {
   height: 60px;
   width: 70%;
   padding-left: 20px;
   padding-right: 20px;
   color: #999
.sm_book_tbl td.cart {
   padding: 10px 20px;
   color: #999;

In our style sheet, we have added a background image to our shelf div, as seen in the declaration for the div.shelf class. This image will be located in the sm_books folder. Attached to this tutorial is the source file; add the shelf_bg.jpg file to that folder.

Once completed, we will attach the style sheet to our plugin. Add the following snippet to the bottom of the sm_books.php file. Using some WordPress functions, we will register the style sheet from our folder with the WordPress system.

function sm_add_styles() {
   wp_register_style( 'sm_add_styles',
   plugins_url('sm_books/style.css', __FILE__) );
   wp_enqueue_style( 'sm_add_styles' );
add_action( 'wp_enqueue_scripts', 'sm_add_styles' );

Book Preview

Download the plugin

You can download the B4uCode Smashing Books plugin, which contains everything covered in this tutorial.


Having done this tutorial, you should be able to create a nice shelving plugin for your books. The plugin might serve your needs if you need an online book archive or library. The options aren’t limited to books either; you could create a similar system for CDs, DVDs and records, and you could tweak it to show videos. The possibilities are endless.

Resources From the WordPress Codex

Smashing Editorial (al)