Create a Custom Post Type for Events in WordPress

Jürgen S Jan 2, 2025 Custom Post Types
How can I make a special section for events on my WordPress site?
What is the process to register a custom post type for events in WordPress using the register_post_type() function, including taxonomies and capabilities?
Andy answered Jan 2, 2025

Creating a Custom Post Type for Events

Custom Code Solution

Place the following code in your theme's functions.php file or in a site-specific plugin:

Register the Events custom post type with labels and settings:

function register_events_post_type() {
    $labels = array(
        'name'               => 'Events',
        'singular_name'      => 'Event',
        'menu_name'          => 'Events',
        'add_new'           => 'Add New Event',
        'add_new_item'      => 'Add New Event',
        'edit_item'         => 'Edit Event',
        'view_item'         => 'View Event',
        'search_items'      => 'Search Events',
        'not_found'         => 'No events found',
        'not_found_in_trash'=> 'No events found in trash'
    );

    $args = array(
        'labels'              => $labels,
        'public'              => true,
        'has_archive'         => true,
        'publicly_queryable'  => true,
        'show_ui'             => true,
        'show_in_menu'        => true,
        'show_in_rest'        => true, // Enables Gutenberg editor
        'menu_icon'           => 'dashicons-calendar',
        'supports'            => array('title', 'editor', 'thumbnail', 'excerpt'),
        'rewrite'             => array('slug' => 'events'),
        'menu_position'       => 5
    );

    register_post_type('event', $args);
}
add_action('init', 'register_events_post_type');

Add custom taxonomies for Event Categories and Tags:

function register_event_taxonomies() {
    // Event Categories
    register_taxonomy('event_category', 'event', array(
        'hierarchical'      => true,
        'labels'            => array(
            'name'          => 'Event Categories',
            'singular_name' => 'Event Category'
        ),
        'show_ui'          => true,
        'show_admin_column' => true,
        'show_in_rest'     => true,
        'rewrite'          => array('slug' => 'event-category')
    ));

    // Event Tags
    register_taxonomy('event_tag', 'event', array(
        'hierarchical'      => false,
        'labels'            => array(
            'name'          => 'Event Tags',
            'singular_name' => 'Event Tag'
        ),
        'show_ui'          => true,
        'show_admin_column' => true,
        'show_in_rest'     => true,
        'rewrite'          => array('slug' => 'event-tag')
    ));
}
add_action('init', 'register_event_taxonomies');

After adding this code, visit Settings > Permalinks and click "Save Changes" to flush rewrite rules.

Plugin Solutions

If you prefer using a plugin, here are reliable options:

  1. The Events Calendar - Free, feature-rich events management
  2. Events Manager - Flexible events and booking system
  3. Modern Events Calendar Lite - Modern interface with booking features

Additional Features

Add custom meta boxes for event details:

function add_event_meta_boxes() {
    add_meta_box(
        'event_details',
        'Event Details',
        'display_event_meta_box',
        'event',
        'normal',
        'high'
    );
}
add_action('add_meta_boxes', 'add_event_meta_boxes');

function display_event_meta_box($post) {
    // Add nonce for security
    wp_nonce_field('event_details_nonce', 'event_details_nonce');
    
    // Get existing values
    $event_date = get_post_meta($post->ID, '_event_date', true);
    $event_time = get_post_meta($post->ID, '_event_time', true);
    $event_location = get_post_meta($post->ID, '_event_location', true);
    
    ?>
    <p>
        <label for="event_date">Date:</label>
        <input type="date" id="event_date" name="event_date" value="<?php echo esc_attr($event_date); ?>">
    </p>
    <p>
        <label for="event_time">Time:</label>
        <input type="time" id="event_time" name="event_time" value="<?php echo esc_attr($event_time); ?>">
    </p>
    <p>
        <label for="event_location">Location:</label>
        <input type="text" id="event_location" name="event_location" value="<?php echo esc_attr($event_location); ?>">
    </p>
    <?php
}

function save_event_meta($post_id) {
    // Security checks
    if (!isset($_POST['event_details_nonce']) || 
        !wp_verify_nonce($_POST['event_details_nonce'], 'event_details_nonce')) {
        return;
    }
    
    if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
        return;
    }
    
    // Save meta values
    if (isset($_POST['event_date'])) {
        update_post_meta($post_id, '_event_date', sanitize_text_field($_POST['event_date']));
    }
    if (isset($_POST['event_time'])) {
        update_post_meta($post_id, '_event_time', sanitize_text_field($_POST['event_time']));
    }
    if (isset($_POST['event_location'])) {
        update_post_meta($post_id, '_event_location', sanitize_text_field($_POST['event_location']));
    }
}
add_action('save_post_event', 'save_event_meta');