Does anyone have experience with Time.ly's Event Calendar? I've contacted Time.ly help and they informed me this sort of thing would have to be custom work. Soo, I come to the trusty WPSE!

Do you know of a way to have single events show up as sub-posts/-pages beneath the main calendar page?

For example, the current permalink structure is:

  • Main Calendar: domain.com/calendar
  • Single Event: domain.com/ai1ec_event/single-event-title

What I'd like to do, is have the permalink structure be:

  • Main Calendar: domain.com/calendar

  • Single Event: domain.com/calendar/single-event-title

    or even...

  • Single Event: domain.com/calendar/ai1ec_event/single-event-title

Either of those two single event permalinks would be fine with me, I just want to have it be under the Calendar page itself.

I'm not completely sure where to begin with this though. Just thought I'd put it out there for anyone who might be able to give me a jumping off point.


Also, if someone with 300+ rep wouldn't mind creating these two new tags and adding them to this post, that'd be great.

  • all-in-one-event-calendar
  • timely


  • 1
    i work for timely, i'll create the all-in-one-event-calendar tag Commented Jan 24, 2013 at 7:31
  • No i don not have enough rep Commented Jan 24, 2013 at 7:32
  • @NicolaPeluchetti no worries - it'll get there eventually :P I'm excited about the newest version, by the way! Cheers for a job well done!
    – joshmax
    Commented Jan 24, 2013 at 14:01

1 Answer 1


I'll preface this by saying I have no experience with or knowledge of the plugin, this answer is based entirely on a 30 second scan of the code that registers the post type for use in the plugin, so you may uncover issues with this solution that my quick clicking of a test event didn't catch. With that said...

The basic gist of this is to unset the post type registered by the plugin, and then re-register it with the same settings except for the modified rewrite slug. To understand how this works you should familiarize yourself with the register_post_type function if you're not already.

The code that registers the post type for the plugin is in the file app/helper/class-ai1ec-app-helper.php.

The following code was tested in the Twenty Eleven theme's functions.php file. You can do this in your own plugin, but you'll have to be sure it runs after the event calendar plugin's init for this to work.

Be sure to read all of the comments within the code to understand what was changed, the important detail being the rewrite argument of register_post_type which gives us our desired URL: 'rewrite' => array( 'slug' => 'calendar/event', 'with_front' => false )

add_action( 'init', 'wpa64981_event_calendar_init' );

function wpa64981_event_calendar_init() {

    // make sure the plugin is active and has set itself up
    if( defined( 'AI1EC_POST_TYPE' ) ) :

        // globalize the post types array and some plugin settings we'll need
        global $wp_post_types, $ai1ec_settings, $ai1ec_app_helper;

        // unset the original post type created by the plugin
        unset( $wp_post_types[ AI1EC_POST_TYPE ] );

        // the labels array was copied wholesale from the plugin
        // EXCEPT 'all_items' value, which originally reference $this
        $labels = array(
            'name' => _x( 'Events', 'Custom post type name', AI1EC_PLUGIN_NAME ),
            'singular_name' => _x( 'Event', 'Custom post type name (singular)', AI1EC_PLUGIN_NAME ),
            'add_new' => __( 'Add New', AI1EC_PLUGIN_NAME ),
            'add_new_item' => __( 'Add New Event', AI1EC_PLUGIN_NAME ),
            'edit_item' => __( 'Edit Event', AI1EC_PLUGIN_NAME ),
            'new_item' => __( 'New Event', AI1EC_PLUGIN_NAME ),
            'view_item' => __( 'View Event', AI1EC_PLUGIN_NAME ),
            'search_items' => __( 'Search Events', AI1EC_PLUGIN_NAME ),
            'not_found' => __( 'No Events found', AI1EC_PLUGIN_NAME ),
            'not_found_in_trash' => __( 'No Events found in Trash', AI1EC_PLUGIN_NAME ),
            'parent_item_colon' => __( 'Parent Event', AI1EC_PLUGIN_NAME ),
            'menu_name' => __( 'Events', AI1EC_PLUGIN_NAME ),
            'all_items' => $ai1ec_app_helper->get_all_items_name()

        // identical to plugin's original values        
        $supports = array( 'title', 'editor', 'comments', 'custom-fields', 'thumbnail' );

        // this is where the important change is made
        // to get our own rewrite slug:
        // 'rewrite' => true
        // changes to:
        // 'rewrite' => array( 'slug' => 'calendar/event', 'with_front' => false )
        $args = array(
            'labels' => $labels,
            'public' => true,
            'publicly_queryable' => true,
            'show_ui' => true,
            'show_in_menu' => true,
            'query_var' => true,
            'rewrite' => array( 'slug' => 'calendar/event', 'with_front' => false ),
            'capability_type' => array( 'ai1ec_event', 'ai1ec_events' ),
            'capabilities' => array(
                'read_post'               => 'read_ai1ec_event',
                'edit_post'               => 'edit_ai1ec_event',
                'edit_posts'              => 'edit_ai1ec_events',
                'edit_others_posts'       => 'edit_others_ai1ec_events',
                'edit_private_posts'      => 'edit_private_ai1ec_events',
                'edit_published_posts'    => 'edit_published_ai1ec_events',
                'delete_post'             => 'delete_ai1ec_event',
                'delete_posts'            => 'delete_ai1ec_events',
                'delete_others_posts'     => 'delete_others_ai1ec_events',
                'delete_published_posts'  => 'delete_published_ai1ec_events',
                'delete_private_posts'    => 'delete_private_ai1ec_events',
                'publish_posts'           => 'publish_ai1ec_events',
                'read_private_posts'      => 'read_private_ai1ec_events' ),
            'has_archive' => true,
            'hierarchical' => false,
            'menu_position' => 5,
            'supports' => $supports,
            'exclude_from_search' => $ai1ec_settings->exclude_from_search,

        // register the post type with our new settings
        register_post_type( AI1EC_POST_TYPE, $args );


  • Thanks for your answer, Milo! I KNEW it had something to do with register_post_types! I tried editing the plugin's code, but I guess since the plugin was already active, it didn't work. The unset/reset version is better: when the authors update the plugin, I won't have to re-edit :) Haven't had a chance to test it out, but will let you know how it goes. 2 Questions: 1) If this is in my theme's functions, how can I ensure it runs after the plugin's? 2) Would hierarchical not need to be set as true? Or, is it false because this CPT is not technically a page? Thanks again!
    – joshmax
    Commented Sep 14, 2012 at 13:30
  • 1
    the theme loads after plugins, so if priority isn't set, it will happen after plugin inits. see the add_action page and the priority argument for manipulating when your own init is fired. hierarchical gives you the ability to assign a parent for each post, like pages. it's not necessary for this particular functionality- the URL rewrite is just superficial, events aren't children of the calendar page.
    – Milo
    Commented Sep 15, 2012 at 14:39
  • Can you create the all-in-one-event-calendar tag? Commented Jan 24, 2013 at 7:32
  • This solution does not seem to work anymore, I get an error after pasting the above into theme's function file: Call to a member function get_all_items_name() on a non-object Commented May 19, 2014 at 13:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.