How to Make Your Own Events Listing Using Custom Post Types in WordPress

James Bruce Updated 15-04-2019

One of the advantages of using WordPress is its sheer flexibility. It’s not just for posts and pages: custom post types can extend the core features to virtually anything.


Let’s take a look today at what you could do with custom post types, as well as a quick practical example of how to create an event listing using a custom post type called Event.

Note: This tutorial should be considered for educational purposes only, so you can learn the code used to create custom post types. If you actually want a great events listing plugin for your WordPress site, try The Events Calendar, which is well developed and free.

What Are Custom Post Types in WordPress?

Typically, a WordPress site consists of two types of content: dated blog posts, and static pages. Most of us who have set up a WordPress blog Set Up Your Blog With WordPress: The Ultimate Guide Want to start your own blog but don't know how? Look to WordPress, the most powerful blogging platform available today. Read More are familiar with the fact that pages should be used for things like “About me” or “Contact information”, while regular posts go to your blog.

But beyond that, what if you want to add another special kind of content that doesn’t really fit into the chronological order of the blog and certainly isn’t static? That’s where custom post types come in.

A fairly common request for club or group sites is to have some kind of events calendar. One solution that could be applied is to create a separate Events category of posts. The problem with this is they’ll be displayed in the main blog timeline, and we really ought to separate the two concepts entirely.


For that purpose, let’s create a new post type called event, which will have its own separate section of the admin interface.

How to Create a Custom Post Type in WordPress

We’ll do this by adjusting your theme files directly. You could achieve the same effect through a plugin, but to demonstrate the concept and practice it’s just easier to write them directly. If you’re not comfortable doing this, consider using the My Custom Functions plugin, which allows you to add code non-destructively.

My Custom Functions

Open up your theme’s functions.php file, stored in the theme folder inside wp-content/themes; or use the My Custom Functions plugin, which you’ll find at Settings > PHP Inserter. At the end of the file, add this code:

add_action('init', 'events_init');

function events_init() {
	$args = array(
		'labels' => array(
			'name' => __('Events'),
			'singular_name' => __('Event'),
		'public' => true,
		'has_archive' => true,
		'rewrite' => array("slug" => "events"), 
		'supports' => array('thumbnail','editor','title','custom-fields')

	register_post_type( 'events' , $args );

Be sure to do this before the closing php (?>) tag, if there is one in your functions.php file.

Take a while to read over the code. It’s declaring some properties (like labels for the interface), and how the URLs (rewrites) should be handled, as well as what features this post-type supports. You can, for instance, add a custom field to your custom post type with the supports property.

In this case, we’ve declared our event type to support thumbnails, a content editor for the event description, an event title, and custom fields. We’ve also added has_archive, so that navigating to the events page will bring up an archive of all events, similar to a blog.

That’s it, now if you save your theme and reload your blog, assuming you don’t have any errors you should now see a new events section on your admin sidebar. Yay!


Notice how my current theme is taking full advantage of custom post types for all manner of extra features in the admin.

Add some example events now.

Two awesome parties have been added to the event list!

Then since this is an event, create a custom field called date to indicate when the event will occur. Use mm/dd/yyyy format.


Creating a custom date field to show when the event will actually occur

Note that we need to use custom fields to specify the actual date of the event rather than the date of the post, because the date of the post represents when the notice is published. Since you’d presumably be adding events that will occur in the future, setting the publishing date to the actual event date would be useless.

If you try to view the event at this point, you may get a 404 error. This is because WordPress needs to regenerate your Permalink URL structure to account for this new post type. Head over to the Settings > Permalinks page, and hit save again.

You should now be able to view the individual event post. Note that the first part of the URL, after your domain name, is /events/. We chose this in this line of code:

'rewrite' => array("slug" => "events"),

Customize the Events Listing Page

Now that you have all these fantastic events in your blog, it would be nice to actually list them somewhere. For that, we will create a special page template, so you can then add that page to your regular menu items alongside About or Contact.

Since we already specified that the Event post type should have an archive, you can go ahead and see what the default is by visiting /events/. On the standard Twenty-Seventeen theme on my test site, I got this:

Archive page showing events

Customizing this output is going to depend on what theme you’re using, and covering the entire WordPress templating system is well out of the scope of this article. However, for the sake of this tutorial, I’ll assume you’re using Twenty-Seventeen.

Start by creating a copy of archive.php, and rename it to archive-events.php. This is a standard naming convention that means WordPress will automatically use this template to display the archive for the events post type.

Upon examining the file, the Twenty-Seventeen authors have provided a post format mechanism, which is too complex for our needs:

* Include the Post-Format-specific template for the content.
* If you want to override this in a child theme, then include a file
* called content-___.php (where ___ is the Post Format name) and that will be used instead.
get_template_part( 'template-parts/post/content', get_post_format() );

Note: A child theme is recommended since any updates to the original theme will overwrite your changes. This WordPress support article describes the process of creating a child theme for Twenty-Seventeen. For brevity, I’m just going to work on the original theme and not care if my work is lost in a later update.

Cut that entire block out, and paste in the following instead. This is just a simplified copy of what’s in those post format templates, for the sake of learning:

<header class="entry-header">
<?php echo '<div class="entry-meta">'.twentyseventeen_time_link().'</div>';
the_title( '<h2 class="entry-title"><a href="' . esc_url( get_permalink() ) . '" rel="bookmark">', '</a></h2>' );?>

<?php if ( '' !== get_the_post_thumbnail() && ! is_single() ) : ?>
<div class="post-thumbnail">
<a href="<?php the_permalink(); ?>">
<?php the_post_thumbnail( 'twentyseventeen-featured-image' ); ?>
<?php endif; ?>

<div class="entry-content">
<?php the_content(sprintf('Continue reading<span class="screen-reader-text"> "%s"</span>',get_the_title()));?>


If you save and preview the Events page again, you’ll notice it now has dates. But they’re wrong. They’re currently showing the publish date instead of the event date. As a last step, let’s change that to the actual date the event will be held. Find the bit that generates the time, twenty_seventeen_time_link(), and replace it with the following:

date('l jS F Y',strtotime(get_post_meta(get_the_ID(), 'date', true)))

This is getting the date from the post meta field we set, then using the PHP date() function to format it to something more readable.

Archive with dates

Next steps?

If you’re unhappy with your current web host, we highly recommend using a managed WordPress host like WP Engine, which we ourselves use for our sister sites. Otherwise, InMotion Hosting offers affordable plans, which are even cheaper with our special discount when you use this link.

Then, note that when we created the event post type, we coded support for featured thumbnails already. Use our guide to featured images and post thumbnails The Complete Guide to Featured Thumbnails and Image Sizes in WordPress Here's everything you need to know about image sizes in WordPress and managing featured images. Read More to grab and display a featured image on the events listing archive.

Related topics: Wordpress, Wordpress Plugins.

Affiliate Disclosure: By buying the products we recommend, you help keep the site alive. Read more.

Whatsapp Pinterest

Leave a Reply

Your email address will not be published. Required fields are marked *

  1. CodeMine
    June 18, 2019 at 3:45 pm

    "You can also try our WordPress plugin Calendar Anyting.

    Calendar Anyting is an interesting WordPress calendar plugin that can show any existing custom post type in a calendar. It is an ideal tool for school, restaurant, concert, conference and similar websites. For your information, Calendar Anyting is compatible with any event plugin that you can currently get your hands on. Out of the box, you get to pick between eleven themes of which all are fully modifiable. The final layout that you will realize will also be responsive, mobile-ready and cross-browser compatible. Calendar Anyting works on any device and platform without a hitch.

    The full feature list of Calendar Anyting is vast so we will put an extra shine on only a few. Event filtering, tooltips, caching, Google Fonts, two event fetching modes and custom date range are a few of the traits of Calendar Anyting. Now go ahead and Calendar Anyting!"

  2. Tiago
    December 6, 2016 at 11:27 pm

    Thanks! <3

  3. najboss
    February 8, 2015 at 8:50 pm

    thank you every thing it's working fine on my custom template and so happy to find your site in this big result of search

  4. James Bruce
    August 23, 2011 at 9:27 am

    so sorry for the late reply lisa, your comment got lost in my daily inbox deluge. Just remove the , so it looks like:

    'rewrite' => array("slug" => "events"),

    I'm not sure how that got in there, but looks like the code in my article got broken by WordPress when I posted. good catch, will fix now. 

  5. Gort
    July 24, 2011 at 8:54 pm

    Hello, getting the following error when I add your code to functions.php:  Parse error: syntax error, unexpected ';', expecting ')' in /wp-content/themes/xtort/functions.php on line 166

    Any ideas?

    • James Bruce
      July 27, 2011 at 8:27 am

      Can you post the full file at or something Gort? Difficult to tell without seeing the whole thing. 

  6. Mark Mulder
    July 22, 2011 at 6:42 am

    One thing  you forgot to mention which I found out the hard way, is in order for you to be able to create your own listing page for your CPT as described in this manner, you MUST set 'archive' to 'false' in your definition of the CPT inside functions.php. If it's set to 'true', this listing page will NOT be found, and WP will try to look for 'archive-cpt_name.php' instead, and fall back on 'archive.php' if that is missing.

    • James Bruce
      July 27, 2011 at 8:27 am

      Hmm, I didn't have that problem in the next custom post types tutorial I wrote - I'm not sure what you mean by listings page - surely you would want to be able to customize via archive-custom.php? If you set archive to false, what template does it then use?

  7. Matt
    July 12, 2011 at 8:44 am

    Hi James,

    I was wondering could you use this same methodology to build a products information database?  For example if I run a site about cameras,  would it be possible to create a detail pages with the specifications and such?  Perhaps a follow up post expanding the custom post type concept into other areas would be good :)

    • James Bruce
      July 12, 2011 at 12:34 pm

      That's a great idea matt. It sounds like you're talking about a non-eccommerce site - just wanting to store meta-information about the cameras, right? That should be easy. I'm not sure if it warrants another post though. I guess it could be a kind of tutorial on pulling it all together - custom posts, featured images, custom fields for meta-info, and how to present that all. Good idea, I'll add it the list!

      • Matt
        July 13, 2011 at 8:49 am

        Yes it's the putting it all together that will be interesting.  These kind of simple wordpress hacks are fantastic.  Doesnt have to be Cameras could be applied to anything- car parts, pc components, mobile phones, anything really! more uses than I can think of =D

        • James Bruce
          July 17, 2011 at 6:58 am

          Matt, just to let you know I've written a tutorial and it should be published next week, keep an eye out for it on Sunday. ;) 

        • Msrog
          July 19, 2011 at 7:02 am

          Why can't I see the code in your post, only in the comments?  Makes it hard for me to follow your tutorial, LOL.  Thanks.

        • James Bruce
          July 19, 2011 at 7:56 am

          Seems fine for everyone else. Maybe you have javascript disabled, or are using an incredibly outdated browser. 

        • Msrog
          July 20, 2011 at 9:10 pm

          That's so odd.  I still just see a thin gray bar where the code should be.  I'll see how it looks using Firefox...

          aha!  Now I see it.  Thank you.

        • Matt
          July 20, 2011 at 4:51 pm

          Woop! thanky ou kindly will be on the look out for it this weekend!  Thanks!

  8. BingMeUp Scotty
    July 10, 2011 at 12:40 pm

    lol, another awesome party?? good times

    • James Bruce
      July 11, 2011 at 6:55 am

      Ahh, the hectic life of an MUO writer, I know right?

  9. Soham Chowdhury
    July 9, 2011 at 11:21 am

    Awesome post. MUO rocks as usual!

  10. JohnnyBoy
    July 9, 2011 at 4:41 am

    Thanks for the good post, I have run into the need to create an event listing system a few times. I put your solution to work and it works for me.

    One question - how could we use this solution to set up a system for displaying future, upcoming events, and hiding events that are over? The way I've set up your solution, it shows events in order of oldest to newest. However, I would like to be able to show a number of future, upcoming events, and when an event has happened and is in the past, I would like it to no longer show.

    Thanks again for taking the time to write this helpful tutorial.

    • James Bruce
      July 11, 2011 at 6:50 am

      I dont think you can use the built in query system for this, however you could somewhat easily write a custom SQL function. This *should* work, but I'm afraid I dont have time to test and debug it. 

      global $wpdb;
      $sql = "SELECT * FROM wp_posts, wp_postmeta
      WHERE wp_posts.post_status = 'publish' AND
      wp_posts.post_type = 'event' AND
      wp_postmeta.meta_key = 'date' AND
      wp_postmeta.meta_value >= CURDATE()
      ORDER BY wp_postmeta.meta_value";

      $results = $wpdb->get_results($sql);
      foreach ($results as $result){

      // display logic in here 


      Because you'll be using a custom DB query, most of the regular WP functions such the_permalink() etc wont work. Instead, access the variables directly from the $result object, like $result->post_title. Alternatively, you can pass the ID as an argument into the function if it allows, like get_permalink($result->ID)

      Hope you can do something with that, if not I'll endevour to make a part two showing the homework task and this ;)

      • JohnnyBoy
        July 11, 2011 at 4:54 pm

        Thanks for your helpful reply Bruce, I'll give that custom sql function a shot.

        From some other research I think I have found a way to do this with WP_Query, and by assigning today's date as a variable:

        $todaysDate = date('Y/m/d'); // Get today's date in the right format

        $eventsloop = new WP_Query('post_type=events&meta_key=event_date&meta_compare=>=&meta_value=' . $todaysDate . '&orderby=meta_value&order=ASC');

        have_posts()) : $eventsloop->the_post(); ?>

        So far this seems to work for me. Note that the custom field "event_date" is formatted the same as the date in the variable, Y/m/d .

        • James Bruce
          July 11, 2011 at 8:37 pm

          Oooh, good find. Yes, I didn't know there was a meta compare, but that'll do it!

        • Lisa
          August 31, 2011 at 9:41 pm

          Where would this go?  In the functions.php or in the loop?

        • James Bruce
          September 5, 2011 at 6:06 pm

          Sorry for the late reply Lisa, must have slipped through my inbox. The code Johnny posted is for the loop, so it would go just before the loop in order to customize the query. 

  11. pceasies
    July 9, 2011 at 2:08 am

    The first codebox is wrapping '&' in a span and leaving 'gt' out so it says '&gt' instead of '>'

    • James Bruce
      July 11, 2011 at 6:38 am

      thanks man, fixed