Adding dynamic section to WordPress

There are a few approaches to this that could work. If you look around here for questions regarding “virtual pages” you might find some options that could work for you.

One quick way to implement this-

1) Create a page under Pages in WordPress admin. This will be the page that’s loaded in the main query, and will be used as the target for rewrite rules you’ll add later. The content of the page isn’t important, you don’t need to output it if you don’t want to, it’s just so that WordPress can successfully run a main query.

2) Add whatever query vars you’ll need to extract data from the URLs. For example, album_id, podcast_id, etc.. Make sure they are sufficiently unique to not clash with WordPress’s own query vars. There’s a likely not complete list of those vars on the register taxonomy codex page. Example:

function wpd_my_query_vars( $qvars ) {
    $qvars[] = 'album_id';
    $qvars[] = 'podcast_id';
    return $qvars;
}
add_filter( 'query_vars', 'wpd_my_query_vars' , 10, 1 );

3) Add the rewrite rules you need for the various requests you want to serve. Your rules will target the page you created in step 1, and set the query vars you added in step 2. Example:

function wpd_rewrite_rules(){
    add_rewrite_rule(
        '^albums/([^/]*)/?',
        'index.php?page_id=42&album_id=$matches[1]',
        'top'
    );
}
add_action( 'init', 'wpd_rewrite_rules', 10, 0 );

Note that rewrite rules need to be flushed whenever new rules are added. You can also do this by visiting the Settings > Permalinks page in admin.

4) This last step is optional. You could handle all of these types of requests with a single page template. If you want to separate the various requests into their own templates, add a filter to page_template to load a different one for each. Note that WordPress sees all of these requests as the single page you targeted, and is otherwise unable to detect any other differences on its own that you’ve created with your own rules and query vars. Example:

function wpd_page_template( $template="" ) {
    global $wp_query;
    if( ! array_key_exists( 'album_id', $wp_query->query_vars ) ) return $template;

    $template = locate_template( 'album-template.php' );
    return $template;
}
add_filter( 'page_template', 'wpd_page_template' );

You can expand this to check for the presence of various query vars you’ve added in order to load other templates. You can access your custom query vars directly from $wp_query as above, or if you’re morally opposed to globals, with get_query_var. You can also target this filter to just one page or array of pages via the is_page conditional tag.

There may be a few other bits you want to clean up in this approach. For example, you may want to remove rel_canonical from the wp_head action on these pages, and add your own function to output canonical meta tags for this content.

Leave a Comment