Posted by & filed under WordPress.

Stuck in the Tree is powered by WordPress and most of the various sections including things like our Quizzes are powered by WordPress Custom Post types behind the scenes. In this post we are going to explore the world of custom post types and look at how our Bingo Sites section has been created.

Custom Post types

Out of the box WordPress has two different post types: posts & pages. Which due to unfortunate naming strategy can lead to confusion, a Page is actually a post type, that is static in nature while posts, are a post type which are based on a time loop. Did I mention naming everything posts was confusing?

You can extend WordPress to have any number of “custom post types” in fact if you are using popular plugins, there is a chance you might have some custom post types already and not even know it. Custom post types work in a similar way to posts and pages, providing a location to add/edit individual posts and normally a method to display them on the front end.

Common examples of Custom Post Types in action are books or movie databases, or products in a shop and we’re going to take a look at how we use custom post types, fields and taxonomies to manage our Bingo Site section which is a collection of reviews of sites, with each site having its own post.

Creating Post Types

Custom Post types are normally generated in code as part of a theme or plugin. It’s recommended you use a plugin rather then your theme, especially if its not a custom built theme. Even though it’s recommended to create them using code, plugins do exist to add post types including the Custom Post type UI plugin.

Adding a post type in code is relatively easy and is done through the


function. If you are ensure where to begin, then this automated wizard will help from generatewp.

Our Bingo Site custom post type looks like:

$labels = array(
		'name'                => _x( 'Bingo Sites', 'bingo-sites', 'stuckinthetree' ),
		'singular_name'       => _x( 'Site', 'Post Type Singular Name', 'stuckinthetree' ),
		'menu_name'           => __( 'Bingo Sites', 'stuckinthetree' ),
		'parent_item_colon'   => __( 'Parent Site:', 'stuckinthetree' ),
		'all_items'           => __( 'All Sites', 'stuckinthetree' ),
		'view_item'           => __( 'View Site', 'stuckinthetree' ),
		'add_new_item'        => __( 'Add New Site', 'stuckinthetree' ),
		'add_new'             => __( 'Add New', 'stuckinthetree' ),
		'edit_item'           => __( 'Edit Site', 'stuckinthetree' ),
		'update_item'         => __( 'Update Site', 'stuckinthetree' ),
		'search_items'        => __( 'Search Sites', 'stuckinthetree' ),
		'not_found'           => __( 'Not found', 'stuckinthetree' ),
		'not_found_in_trash'  => __( 'Not found in Trash', 'stuckinthetree' ),
	$rewrite = array(
		'slug'                => 'bingo-sites',
		'with_front'          => true,
		'pages'               => true,
		'feeds'               => true,
	$args = array(
		'label'               => __( 'Bingo Sites', 'stuckinthetree' ),
		'description'         => __( 'Bingo Sites and reviews', 'stuckinthetree' ),
		'labels'              => $labels,
		'supports'            => array( 'title', 'editor', 'excerpt', 'author', 'comments', 'trackbacks', 'revisions', 'custom-fields', 'page-attributes', 'post-formats', ),
		'taxonomies'          => array( 'category', 'post_tag' ),
		'hierarchical'        => true,
		'public'              => true,
		'show_ui'             => true,
		'show_in_menu'        => true,
		'show_in_nav_menus'   => true,
		'show_in_admin_bar'   => true,
		'menu_position'       => 2,
		'menu_icon'           => '',
		'can_export'          => true,
		'has_archive'         => true,
		'exclude_from_search' => false,
		'publicly_queryable'  => true,
		'rewrite'             => $rewrite,
		'capability_type'     => 'post',
		'menu_icon'   => 'dashicons-tickets-alt',
	register_post_type( 'bingo-sites', $args );

Most of the code is describing the post types strings for describing itself for example singular and plural names, these are the labels. The rest are the capabilities and how the post behaves, will it be more like a post or a page.

Creating a modified custom template

With post type created, we need to style it to make it look how we want (or rather to be what I wanted within the limits of my design bodgeabilites), this was done by creating a new single-bingo-sites.php file in our theme. This file is used when ever one of our reviews is accessed and we are able to style them differently to a post/page.

Custom Meta Fields – and why would you want them

The first iteration of our Bingo sites was little more then a custom post type and a slightly modified version of the default single.php template with the review itself being written in the default WordPress edit box.
The main limitation of this is that it’s just echo’d out onto the page in its entirety with the_content(). So the only way we could control where elements like rating, screenshots, ad banners etc were displayed and how the body of the review was laid out was to add the layout HTML to the review.

This is what our reviewers were faced with. Yikes!

This was far from ideal and reviewers would have to be given a block of HTML to modify and edit their review into. It really wasn’t very efficient and lead to problems:

  • Load of html and layout stuff in the editor
  • Long time to create a new review or update and existing one
  • Easy to make mistakes
  • If we want to change design / layout of reviews they’d have to be altered one by one.

We’d already been using custom fields to store data for things like the value of the no deposit bonus for new customers, and the launch date of the site so we could manage whether it was listed on our New Bingo Sites page or so that it could be included on the page listing sites with No Deposit Bonuses along with details of each sites offer. But we hadn’t got round to splitting out that data from the massive text block that was the review and managing the layout in our template file rather than on each individual post. It’s probably worth mentioning that the main reason for not using custom fields and ‘doing this properly’ from the off was that we wanted to live with the site for a while to see what fields we’d actually use as we couldn’t be sure up front. Our approach to Stuck in the Tree was and still is launch quick and fix it later. Yeah of course if we were building this for a client (which isn’t what we do as I’m sure you can tell by our stellar design skillz!) or an agency was building the site for us that’s not how we’d work but this works for us and means the site is actually launched.

WordPress has built in support for custom fields if you go to screen options on posts and pages, you can add custom fields to any post. To do so once enabled you add a key and value. These are stored in your post meta table. The custom field feature is really useful but ugly. So people devised Custom Meta Boxes, these are additional components to the write/edit page which when saved, populate postmeta in the same way as custom fields.

Plugins and Fields can add fields and components, through WordPress action and filters, however it can get messy, several libraries exist that help make custom meta boxes and there are full blown plugins like Advanced Custom Fields.

The library we use is HumanMade Custom Meta Boxes, a similar WebDevStudios CMB2 exists (they were forked from the same plugin) amongst others. We decided on Human Made library as it was small and easy to use.

The CMB library provides an abstraction layer, allowing us to simply add fields, without worrying about layout, validation or saving it as post meta. We can then use WordPress own built in functions to retrieve the data.

Adding a custom meta box is as simple as:

function register_meta_boxes( array $meta_boxes ) {
$newbies_room_info = array(

					'id' => 'newbies_room_title',
					'desc' => 'Default text if not overwritten: Newbies Room',
					'name' => 'Newbies Room Title',
					'type' => 'text',

					'id' => 'newbies_room_text',
					'name' => 'Newbies Room Text',
					'type' => 'wysiwyg',
$meta_boxes[] = array(
		    'title' => 'Newbies Room',
		    'pages' => array('bingo-sites','test-type'),
		    'context'    => 'normal',
		    'priority'   => 'high',
		    'fields' => $newbies_room_info
return $meta_boxes;
add_filter( 'cmb_meta_boxes', 'register_meta_boxes' );

Because it stores it as post meta we can retrieve it with something as simple as:

$newbies_room_title = get_post_meta( get_the_id(), 'newbies_room_title', true);

Their are multiple field types to choose from including:

  • Text Field
  • Number Field
  • Textarea Field
  • Select Field
  • File Field
  • Checkbox Input Field
  • Radio Input Field

as well as specialist ones like Post, Taxonomy, Google Maps, date
It also comes with some layout capability and possibly the nicest feature out of the box the ability to make any field repeatable, which then returns an array rather then a string with the responses from post meta.

Custom Taxonomies

Like Posts we can also make our own taxonomies the default ones are Category and tags, however extending it is much the same as you do for post types with


function, similarly the Custom Post UI plugin also supports creating custom taxonomies.

		$labels = array(
		    'name' => _x( 'Software', 'taxonomy general name' ),
		    'singular_name' => _x( 'Software', 'taxonomy singular name' ),
		    'search_items' =>  __( 'Search Software' ),
		    'all_items' => __( 'All Software' ),
		    'parent_item' => __( 'Parent Software' ),
		    'parent_item_colon' => __( 'Parent Software:' ),
		    'edit_item' => __( 'Edit Software' ),
		    'update_item' => __( 'Update Software' ),
		    'add_new_item' => __( 'Add New Software' ),
		    'new_item_name' => __( 'New Software Name' ),
		    'menu_name' => __( 'Software' ),

		// Now register the taxonomy

		  register_taxonomy('software',array('bingo-sites','popup-ads'), array(
		    'hierarchical' => true,
		    'labels' => $labels,
		    'show_ui' => true,
		    'show_admin_column' => true,
		    'query_var' => true,
		    'rewrite' => array( 'slug' => 'software' ),
		  $labels = array();

Taxonomies are used to group or label posts, for example we have a taxonomy software which groups sites by the type of software they use which generates the games.

Custom Taxonomies can be tied into our custom fields, so instead of adding a field to postmeta we can select the category. This is all done seamlessly under the hood when using certain fields.