I have a problem where I'm trying to build a calendar plugin for a client. I'm having trouble getting a date based archive for the custom post type I'm using. I'm not too well versed in how the wordpress system for handling permalinks is set up on a low level, and I've hit a wall.


The plugin registers a custom post type, event. Each event has a meta value field called kultkal_date, holds a date in the form of 2011-09-28. (Events are limited in the sense that each event's date is unique as well, by validation on the save_post action).

I've defined a custom permalink for the post type as /kalendarie/%kultkal_year%/%kultkal_month%/%kultkal_day%, so the finished URL might look like /kalendarie/2011/09/28/my-slug. I've added rewrite tags for the custom permalink using the init action like so:


I have a function to fix the permalink that runs on the post_type_link filter:

function filter_post_type_link($link, $post){
    if ($post->post_type != 'event')
        return $link;

    if ($date = get_post_meta($post->ID, 'kultkal_date', true)) {
        $dates = explode('-', $date);
        $year = $dates[0];
        $month = $dates[1];
        $day = $dates[2];
    } else {
        return $link;
    $link = str_replace('%kultkal_year%', $year, $link);
    $link = str_replace('%kultkal_month%', $month, $link);
    $link = str_replace('%kultkal_day%', $day, $link);
    return $link;

Viewing individual posts works. So does the archive page (located at the /kalendarium/ URL: has_archive is set to kalendarium when I register the post type).

The trouble starts when I want to filter the posts by year - for instance, /kalendarium/2011/ or /kalendarium/2011/09/28/ etc. I've found an answer on how to filter based on meta value for date on built-in posts here: Archive Listings Filtered by Date Values in a Custom Field/Post Meta? - but it doesn't seem to work on custom post types. As soon as I add /year/month/day-parameters to test it, I get the archives for the built-in post type, not even a 404. (So far, I've only tried the first version in the answer above, with all the parameters (year/month/date), not the one with all the combinations + hook for posts_where etc.

Here's what the (broken) function I run on pre_get_posts looks like:

function event_pre_get_posts($query) {
    global $wp_the_query;
    if ($query === $wp_the_query && $query->is_archive()) {
        $qv = &$query->query_vars;
        if (isset($qv['kultkal_year']) && isset($qv['kultkal_month']) && isset($qv['kultkal_day'])) {
            $date = mktime(0,0,0,$qv['kultkal_month'],$qv['kultkal_day'],$qv['kultkal_year']);
            $qv['meta_key'] = 'kultkal_date';
            $qv['meta_value'] = date("Y-m-d", $date);

Any ideas on how to achieve the solution I'm looking for?

  • you need to register your query_vars and also create their rewrite rules.
    – Bainternet
    Commented Sep 27, 2011 at 21:35
  • @Bainternet Thanks, mate. I thought the purpose of add_rewrite_tag() was just that, but I guess I'll have to dig deeper, still highly confused as to how the rewrite stuff works. :-) Commented Sep 28, 2011 at 15:07

1 Answer 1


Like Bainternet said in comments, you'll need to mess with add_query_var as well as add_rewrite_rule.

We usually do something similar to:

global $wp;
$wp->add_query_var( 'some_var' );
add_rewrite_rule( 'some/path/([^/]+)/?$', 'index.php?some_var=$matches[1]' );

See this Wordpress Trac ticket, as well as documentation on add_query_var and add_rewrite_rule

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.