WordPress Custom Post Types Guide

Oct 5 2010 by John Gadbois | 60 Comments

WordPress Custom Post Types Guide

One of the most anticipated features of WordPress 3.0 was the ability to add your own custom post types to WordPress, which allows you to display and categorize different types of content outside of the 5 native WordPress content types (i.e. Post, Page, Attachment, and so forth). The addition of this feature is a big step forward in making WordPress a full-fledged CMS, extending outside its normal use as a blogging platform.

In this guide, we’ll go through the process of creating and using your own custom post type. More specifically, we will create an "Event" post type for your special events and dates, sort of like a calendar.

What is a Custom Post Type?

If you’re familiar with WordPress, then I’m sure you’ve already had some exposure to the default WordPress post types used for content creation: Post and Page. Almost all of the content in any WordPress site prior to 3.0 is composed of some combination of posts and pages.

Posts are generally used for content that is updated frequently (blog posts, for example), and pages are generally used for static content (such as the About page of a site).

Often, however, you may have a more specific type of data that you want to include on your site. This is where custom post types come in.

We’re going to create a custom post type that we’ll call "Event". This content type will let us add events such as birthdays, holidays, conference dates, and so forth.

We’ll be working with the default TwentyTen theme that comes with WordPress 3.0 so that we have a uniform code base, but the concepts and techniques will be applicable to any theme.

Creating a Custom Post Type

Fortunately, WordPress makes it pretty easy to create a new custom post type. Let’s look at the code first and then I’ll explain how it works:

add_action( 'init', 'create_events' );
function create_events() {
  $labels = array(
    'name' => _x('Events', 'post type general name'),
    'singular_name' => _x('Event', 'post type singular name'),
    'add_new' => _x('Add New', 'Event'),
    'add_new_item' => __('Add New Event'),
    'edit_item' => __('Edit Event'),
    'new_item' => __('New Event'),
    'view_item' => __('View Event'),
    'search_items' => __('Search Events'),
    'not_found' =>  __('No Events found'),
    'not_found_in_trash' => __('No Events found in Trash'),
    'parent_item_colon' => ''
  );
 
  $supports = array('title', 'editor', 'custom-fields', 'revisions', 'excerpt');
 
  register_post_type( 'event',
    array(
      'labels' => $labels,
      'public' => true,
      'supports' => $supports
    )
  );
}

The above code should be placed in the functions.php file of your theme.

A few notes about the code:

  • add_action tells WordPress to call our create_events() function when WordPress initializes
  • The $labels array tells WordPress how to display messages about our custom post type
  • The $supports array tells WordPress what our post type supports (Can it have an excerpt? – for instance)
  • register_post_type actually registers our new post type with WordPress
  • The register_post_type function is very customizable and has many more options than those that we are actually using; you can see all of these at the WordPress Codex.

Once we add this code to functions.php, we can see our new post type in the WordPress Admin section.

WordPress Custom Post Type

Let’s go ahead and add and publish a new Event. You can publish a new Event just like you would a regular Post.

WordPress Custom Post Type

Displaying a Custom Post Type

Now that we’ve published our event, we can view it like any other post. If you edit your event and then click on the "View Event" button, you’ll see that the event is displayed like any other post.

WordPress Custom Post Type

However, the reason we typically create a custom post type is because we want it to look and act differently from a regular post.

Again, WordPress provides a nice mechanism for customizing how our custom post looks. If you’ve done work on WordPress themes in the past, you probably know that a single blog post is displayed using the single.php theme file. WordPress 3.0 allows you to add a single-[your_post_type_name].php file to override how a custom post type is displayed. Notice the format of this file name: single- followed by the name you assigned your custom post type.

For our Event type, create a single-event.php file and copy the contents of single.php into it. To keep it simple, we’ll just change one line in single-event.php to show that it is really working. Find the line that is outputting the Event title in single-event.php; it should look like the following:

 <h1 class="entry-title"><?php the_title(); ?></h1>

Let’s change it to:

 <h1 class="entry-title">Event: <?php the_title(); ?></h1>

If we go back and look at our Event webpage now, we can see that it is showing our changes.

WordPress Custom Post Type

Any other changes that you make to single-event.php will be visible when viewing an event.

Listing Our Custom Post Type

Now that we’ve seen how to display one of our events, how do we go about listing all of our events? Displaying single events is useful, but its functionality is limited unless we can see all of our events.

There are a couple of different ways to do this, but unfortunately, none of them are particularly straightforward. The most common way (and the way we’ll do it here) is to display a list of custom post types through the use of a custom Page Template. This process isn’t too complicated once you’ve done it a couple of times, but it does require multiple steps.

First, copy the contents of page.php to a new file called page-events.php.

WordPress allows you to create as many different templates as you want for displaying pages in different manners. We’re going to use this functionality to create a template for displaying events.

In page-events.php, add the following line somewhere in the comment at the top of the file:

 
 		Template Name: Events Template
	

This line tells WordPress that the page-events.php file is a Page Template and that it is named "Events Template." The top part of page-events.php should now look something like this:

<?php
/**
 * Template Name: Events Template
 * @package WordPress
 * @subpackage Twenty_Ten
 * @since Twenty Ten 1.0
 */
 
get_header(); ?>

Next, use the following code right before the beginning of the WordPress Loop:

<?php query_posts(array('post_type'=>'event')); ?>

The Loop is the line that looks like this:

<?php if ( have_posts() ) while ( have_posts() ) : the_post(); ?>

The above code tells WordPress to find all content that has the type of event and then to loop through them.

Now that we have a custom page template that will display our events, we need to actually create an "Events" page that will display them. To do that, log back in to the WordPress admin section, create a new page with the title of Events, and then select the "Events Template" for the Template page attribute.

WordPress Custom Post Type

Now that you’ve published the Events page using the Events Template, you can go back to your site and should see the Events page. Depending on your theme, you may need to update your navigation to include this new page. If we navigate to the Events page, we see that our events are now being listed!

WordPress Custom Post Type

Since our custom page template is listing all of the events, we can edit that template if we want to change how the listing looks. We could, for instance, add a calendar icon next to each event, only show the event title, or really customize the page in any way we wanted, just by editing the page-events.php file.

Summary

If you’ve made it this far, you now know how to create, design, display, and list custom post types in WordPress. We’ve just scratched the surface of what you can do with custom post types, but I’m sure you can see that they’re very useful for extending WordPress’s CMS capabilities.

If editing theme files and coding is a little too intimidating for you, there are a couple of WordPress plugins that allow you to accomplish much of the above (see Custom Post Type UI and GD Custom Posts And Taxonomies Tools, among others).

Related Content

About the Author

John Gadbois is a 27-year-old web developer who codes and runs Domain Superstar, a domain name tools site. He also works on the online calculator site, CalculatorPro.com and enjoys working with WordPress, PHP, jQuery, and Ruby on Rails.

60 Comments

John

October 5th, 2010

Perfect, i have been looking for a tutorial on something along these lines. Not exactly on par with my idea but should only take a little editing to make it fit my needs.

Thanks a lot John for taking the time to make the post =]

- John

Jitendra

October 5th, 2010

Awesome information! A must have for every wordpress developer. Thanks for sharing. :)

Pierre

October 5th, 2010

I’m used to customize my WordPress sites, but I never knew it was possible to do ‘custom posts’. Thanks a lot for this really interesting article.

Daniel15

October 5th, 2010

Looks great :)
I have a “microblog” section on my blog, that displays posts in a slightly different format to my normal blog posts. Currently I’m just using a category and some CSS to reformat it. I wonder if I could use a custom post type instead.

Also, I’m posting to my blog via email using an extension called “Postie”. Wonder how hard it’d be to edit it to support custom post types… Any ideas?

Birgit

October 5th, 2010

Nice article, interesting new WP feature.

Would be nice to add a how-to for an alternate presentation of custom fields (e.g. a start and end date field that show up beneath the title) in the backend, wonder if that’s possible.

Thanks a lot!

Adie

October 5th, 2010

Great information.

Never knew this was even possible.

Thanks

Jacob Gube

October 5th, 2010

@Birgit: So sort of like a custom input field when creating an event? That can be done, and that’s a solid idea — if we were to do it, we’d probably extend it to something broader like “How to customize the New Post interface.” Thanks for the idea, and I’ll see what we can do.

Erik

October 5th, 2010

Good solid article, knew it was possible but always handy to have this as a reference, bookmarked it!

Thanks!

John G

October 5th, 2010

Very good stuff to know, thanks! I’m definitely going to implement this on my site -can’t wait to play around with this when I get home. I have to say, though, this is another situation where you have to dig into the code to do these kinds of things.

I’m usually a bit surprised when adding WordPress features requires a lot of (or even a little) code-wrangling. I don’t have a problem with this since I like to dig into the code on every project I do anyway, but for a system that’s supposed to be so easy compared to the rest, I don’t think a lot of users will feel comfortable pulling this off.

web guy gary

October 5th, 2010

in this specific example, how would one take it a step further and display a google map in the post for the event location?

Dominic

October 5th, 2010

Wow. That’s a long way from CCK. Without excellent guides like this it would be bewildering. I’m glad WP has opened up this feature, but there’s a lot of work ahead of them to make it as user friendly as the rest of the platform.

kumbi

October 6th, 2010

i love the subtly-offered suggestions on properly using this feature.

Marcell Purham

October 6th, 2010

What a great articles. I really didn’t understand the whole wordpress custom post type fully but know I sort of get the hang out it, which is good.

Andrew Nacin

October 6th, 2010

If you want your page template to be paginated, you’ll want to also pass the paged query variable to query_posts(). Otherwise you’ll always be displaying the first page of events regardless of the page requested.

Example:

'event', 'paged' => get_query_var( 'paged' ) ) ); ?>

Nacin

Idraki M.

October 6th, 2010

How can this be utilized to create an example for some tutorial?

Jacob Gube

October 6th, 2010

@web guy gary: That’s one step further, for sure. You’d also have to work with the Google Maps API. I can see it like this: You have a custom field in the events section that has the URI request to Google Maps. The event template has a section for your map (say a div). Inside it you have code that checks whether or not you provided a value to the custom field. If it’s null, then you just skip. If it’s not null, it takes your URI and makes a request to Google Maps API and then renders the map. That’s the concept I’m thinking (it’s still early, I haven’t had coffee, that may not be the easiest logic). This shouldn’t be too hard for a dev; and IMO not hard enough to merit using a WP plugin.

@Dominic: Glad you found this guide to be useful. Though I’d have to say that it’s unfair to compare custom post types to CCK because CCK is a module. There are WP plugins that deal with custom posts even when the feature was just recently introduced (listed in the guide); that would be a better apples-to-apples comparison. CCK is to making your own custom post types as to Ruby on Rails (web development framework) is to PHP (scripting language); a better comparison of the two would be RoR versus CakePHP (or Zend). BTW we also have a (huge and comprehensive) guide on getting started with Drupal (including a discussion on CCK).

@Andrew Nacin: Hey Andrew, thanks for the awesome tip.

Matthias

October 6th, 2010

How will these modifications be affected when you upgrade WordPress? Or if you change themes?

Sorry, noob to any custom WP mods here! This is wicked cool stuff.

Pierre

October 6th, 2010

For those who want to use the custom fields to enhance a bit your post, and customize it, here it is. I created a ‘Press’ page for my company, to list all the publications we had. I needed some custom fields like ‘date’, ‘thumbnail’ or ‘image’ …

Just follow the tutorial above, and add some custom fields of your choice in every custom post.
Then, in your template file, just use this php line to show the value of a specific custom field : echo get_post_meta($post->ID, ‘NAME_OF_YOUR_CUSTOM_FIELD’, $single = true);
Of course don’t forget to change NAME_OF_YOUR_CUSTOM_FIELD (and add the php tag before and after this code, the comment can’t show it).

Hope it’ll help !

veki

October 6th, 2010

Jacob, I think I didnt post any comment till now. But I am reading your blog passionately. One of the best in my Design+ WordPress category :))

In this article we need to see Custom Fields for Custom Posts in play, so Custom post can be truly be used in a CMS manner and not just for formating and CSS

Continue to deliver fantastic info :))

Jacob Gube

October 6th, 2010

@veki: John and I talked about a possible follow up to this one, and definitely, custom fields would be something to cover. I think this guide definitely accomplished its goal (and IMO above and beyond) of getting people familiarized with custom post types, which is a new thing in WP 3.0 — and, in my opinion, the strongest addition for developers. I hope that we’ll be able to follow this up and making more complex custom post types, exploring things like custom fields, and customizing the interface depending on the post type.

Glad that you were finally compelled to leave a comment veki, and thanks for supporting and reading Six Revisions.

Jeff

October 7th, 2010

Nice post, Its great to finally get a tutorial that give a slightly different approach on Custom Post Types in WordPress. your presentation helped me to control the labels in my Custom Post Types.

Riavon

October 7th, 2010

This isn’t working for me. I am a mere designer, not a developer, perhaps that’s why? It seems simple enough, and I’ve done my share of custom coding in WP, but…with this, I get a mess after the very first step. I added the code (I too want to do an “Events” custom post type!) by copy/pasting your code into my functions.php file (though I have no idea where to put it in there. I tried inserting at line 1 and also tried inserting at the end, but it still didn’t work.) My WP Dashboard simply shows the code along the top of the page when I load it. I also cannot find ”anywhere in the single.php (which I ‘saved as’ singe-event) page code. In fact, there is not a single instance of an H1 tag in there at all. Am I missing an important, invisible step or is this a theme issue? I’m using a new premium theme from Elegant Themes in WP 3.0.1 Any help would be appreciated!

Riavon

October 7th, 2010

I also cannot find anywhere in the single.php (which I ’saved as’ singe-event) page code.

Riavon

October 7th, 2010

I apologize for the multiple posts here. I had no idea I couldn’t edit or delete them. I’ll figure out how to figure this out, thanks!

Devin

October 8th, 2010

I did a similar post to this last month at: http://wptheming.com/2010/08/how-to-make-an-events-custom-post-type/. It also explains how to add metaboxes in case you wanted, say, event location, to be a field that you enter and display.

John Gadbois

October 8th, 2010

@Riavon
For the function.php issue, make sure you are inside of PHP tags .

As far as single.php goes, there is an h1 in the TwentyTen theme, but in yours it may be an h2 or h3. Look for the section where the_title() is being output.

James Duncombe

October 9th, 2010

I’d heard about them but it’s great to actually see an article on it.

Cheers!

Chief Alchemist

October 9th, 2010

Yes John, thanks.

Don’t get me wrong, I love WordPress. I think that in many instances it’s a great out of the box tool. That said, when it comes to this type of functionality, ExpressEngine has a commanding lead (?) over WP. While WP can be tweaked and twisted to kinda, sorta be a CMS, it’s just not a CMS in the way EE is a CMS. Well, at least not yet.

Mark

October 9th, 2010

Not really sure if this would be easier than doing it the old way, which is making custom category.php and single-name.php files which are read first in the hierarchy. Then assigning a category to all posts you want to use those templates. That is how I currently style my blog posts and my thumbnail “showcase” style posts.

Gömbszörp

October 12th, 2010

Yes, it is very good, but how can i serach this custom post types? The WP search don’t show them..

jeremy

October 12th, 2010

Is anybody else finding strange things happen with “pretty permalinks?”

I tried this on a local install of wordpress specifically for testing things. The default “ugly” permalink structure was http://localhost/wordpressTests/?p=123 …..and things worked fine. But when I tried to change to the custom structure I normally use (category/postname), things went all screwy.

Somehow its sorta working now (and I don’t honestly know what I did!), but links change between singular and plural. The events page is at the plural http://localhost/wordpressTests/events/ …. but if I link to individual posts it changes to the singular http://localhost/wordpressTests/event/testing_this_thing …. I suppose that’s easy enough to work around – just keep all the names in functions.php the same (especially for names like “news” or “stuff”)

It just seems like its going to be awkward, from a naming convention standpoint, to use custom post types on a site that’s already built around post categories. (much like Mark, i’m not seeing big advantage to custom post types over categories)

saqib sarwar

October 16th, 2010

Thanks John Gadbois,

I really enjoyed this post. keep up the good work.

Adrian

October 28th, 2010

Magnifico WordPress todo un cms.

Saludos desde México

Paul

November 2nd, 2010

Hi
Thanks for the great tutorial. I created a new custom post type and it looks great but… :) … for some reason the edit screen doesn’t allow the same control over the published date. In the publish box in the top right corner, I can only set status and visibility. The date control item in normal posts/pages is missing, and it doesn’t seem to be an option I can put into the “supports” field.

Is there a way to get this to display?

Brij

November 23rd, 2010

Nice Post!!!

I have created a project collection theme based on this custom post type feature.

See following to download:

http://www.techbrij.com/342/create-project-collection-theme-wordpress-3-custom-post-type

Vayu

December 10th, 2010

Nice article!

However, there is a problem with this when viewing a single post type. The menu doesnt add the class “current_page_parent” to the parent page menu item, but WP actually thinks its a child of the blog page and not of the custom post type page.

Any solution for this?

Cordially
Vayu

Jason

December 22nd, 2010

@Vayu, this is a problem being discussed here – http://wordpress.org/support/topic/custom-post-type-parent

I thought I found the solution here but I actually found your comment! Can’t seem to get the suggested code in the forum to work but would like to raise awareness of the issue.

Peter Luit

December 23rd, 2010

Does the ‘custom post type plug in’ (http://wordpress.org/extend/plugins/custom-post-type-ui/) do the same job without any need to copy/paste PHP/HTML code?

juroor

December 30th, 2010

Can someone tell me what i did wrong or what piece of code i need to make the permalinks work? i just see the posts lined up horizontaly but i can’t check every posts..only by inserting is manually in the adress bar.

Any ideea?

Kimbolini

January 5th, 2011

Wow thanks, this was exactly what I needed for the site I’m working on. Lovely :-)

Valerie

January 21st, 2011

For those who get a ‘Not Found’ message when trying to view your new custom-post, try resaving your permalink structure.

From http://somadesign.ca/projects/smarter-custom-post-types/:
One note that’s very, very important: your custom URLs won’t work until you go to Options → Permalink in wp-admin and re-save your current URL structure. This will flush WP’s current URL structure and add our new rewrite rules. This is computationally expensive and you don’t want it happening every time WP loads, which is why I’m leaving it as a manual operation. You’ll only need to do it once (or after changing the third plural argument).

Lenart

January 23rd, 2011

Thanks Valerie. I’ve been struggling with this for hours now.

Garrett Vogenbeck

January 25th, 2011

Hi, great article, but just wanted to suggest a slight modification. I had to add:

‘show_in_nav_menus’ => true,

to the register_post_type $args, and also open screen options and check the appropriate checkboxes to be able to add custom post types to the menus.

Just thought others might get tripped up by that, like those from this forum post, where I got this information:

http://wordpress.org/support/topic/custom-post-type-in-wordpress-30-menu

Other than that, great succinct, to-the-point tutorial. Keep up the good work.

Yen Howell

January 29th, 2011

Thank you!!! This is a great tutorial :D It works perfectly :D

Andrew

February 17th, 2011

I really didn’t realise it was that simple to add custom post types. I’m always posting relatively short posts, more like status updates that don’t really need the full post title and post revisions and the like.

I’ll look at implementing it shortly.

Ken Gary

February 23rd, 2011

Does this still all work with WordPress 3.1? I did the first step and the browser tells me that there is a problem loading the page: Firefox has detected that the server is redirecting the request for this address in a way that will never complete.

Ken Gary

February 23rd, 2011

Ah! Gotta save the permalinks again to fix that problem.

Neeraj Dhiman

April 11th, 2011

Really great article. I’ve created 2 custom post types with their own meta data types for a client. Now I have run into a roadblock that I should have thought of. I installed All In One SEO Pack and it does not support my custom post types. Big problem. Does anyone know of some similar to All In One that supports custom post types? Maybe I will need to hack into All In One, or if nothing works, I’ll have to remove the custom post types and go back to regular posts with categories.

Lars Weimar

April 11th, 2011

@Neeraj;

All In One SEO definitely supports Custom Post Types, I’ve been using it for long time now. Are you using an old version?

Go to Dashboard > Settings > All in One SEO > Look through the settings, you’ll see it there, as a checkbox.

nir

April 28th, 2011

Hi
did anyone manage to make “revisions” support to work?
i can’t see the revision box in my edit page of the new type i created.
any ideas?

Niek

April 29th, 2011

The first good article that describes how to use this. Great work!!

Gökhan

May 22nd, 2011

This is perfect. You helped me with this code :)

‘event’)); ?>

cssrex

June 27th, 2011

Amazing tutorial and its working perfectly fine.

I was just checking if we have custom fields option in this.

Please do let me know if possible.

Thanks

Garish Wasil

June 28th, 2011

I was really looking for custom post type details. Thanks for the awesome work. Well, can you please share how to delete a custom field that is already being used by many of our posts ?

Jonas

July 22nd, 2011

Great – exactly what i was looking for. thx!

javier

August 1st, 2011

The tutorial is great, thanks very much.
I was trying to implement custom post and then be searchable by custom field search plugin but I could not make it work.

If someone knows how can I make it find something posted in this way, I ill appreciate very much.

sharifex

August 8th, 2011

very much grateful to you.

vijay

August 21st, 2011

How can i delete/remove custom post type?
Can you help me plz?

Gabriel Vitor

August 28th, 2012

Nice Post, I’m here just to say, thank you a lot man…
You makes me save a much time.

Prasann

October 9th, 2012

Hey,
g8 tips..thank you very much.. everything is working g8. I am just wondering that I have total 10 post on the blog but I want to display only First 5 on front page and rest of them on second page.how can I do it ?
I have coded ‘posts_per_page’ => 5 but what about my other 5 post. how user can see it ?

Thank you very much

Leave a Comment

Subscribe to the comments on this article.