Create a simple single- & archive- template router for Custom Post Types created in your WordPress plugin so you can deliver flexible, feature-ready plugins.

I’ve been writing a plugin lately that requires a single- and an archive- post template for a few custom post types. Now, I could have hard coded those into the theme, however when the plugin is delivered for integration it should has some form of template router to determine whether the single and archive templates already exist and if they don’t then deliver a default template instead.

So here is the situation: Post Type booklists is being created by my plugin. Since booklists doesn’t exist in the WordPress theme, the theme developer would have no idea to set up a single or archive template for that post type, thus the permalink structure would send those posts to the default single.php and archive.php templates – not entirely ideal. Here’s how to easily circumvent that in a plugin:


//route single- template
function booklistTpl_single($single_template){
  global $post;
  $found = locate_template('single-booklist.php');
  if($post->post_type == 'booklist' && $found != ''){
    $single_template = dirname(__FILE__).'/templates/single-booklist.php';
  return $single_template;

//route archive- template
function booklistTpl_archive($template){
    $theme_files = array('archive-booklist.php');
    $exists_in_theme = locate_template($theme_files, false);
    if($exists_in_theme == ''){
      return plugin_dir_path(__FILE__) . '/templates/archive-booklist.php';
  return $template;

The code block above is in reference specifically for the booklist post type. If we follow the function booklistTPL_single, what is happening is that we are determining if the current post is a booklist post, then we are checking to see if single-booklist.php exists in the theme. If single-booklist.php does not exist in our theme, then we are instead returning a template from our plugin, ../templates/single-booklist.php , which we are providing as a basic starting point for integration.

The same principle applies for booklistTpl_archive; we are checking if the current page is the archive for our post type booklist and from there we are seeing if archive-booklist.php exists in the theme, otherwise we are providing our own template from the plugin.

Using this conditional template routing method gives you more flexibility to provide a feature-ready plugin while still giving more savvy developers plenty of room to use WordPress’ built-in tempting functions alongside your plugin-created custom post types.


* If you’re having problems with the archive/single urls then you likely need to flush your WordPress permalinks.