How do you create an archive for a custom post type from a plugin?

All we need is an easy explanation of the problem, so here it is.

So I’m creating a plugin to create buildings that list condos for sale. The simplest way to do this was to just create a custom post type for the buildings and then the listings but I’m now stuck on how to display them in an archive. I’ve done something similar while developing themes where I would just create a archive-my_post_type.php and single-my_post_type.php but I don’t know how to anticipate how themes could be developed.

I found an answer on stack overflow that allows you to hijack the chosen template but I’m afraid template files might be more than just get_header() and the_content() etc…

What is considered best practice for this sort of thing? Do I just grab get_template_part_content and replace it with my custom loop? Or hijack the chosen template like the answer above and hope for the best?

How to solve :

I know you bored from this bug, So we are here to help you! Take a deep breath and look at the explanation of your problem. We have many solutions to this problem, But we recommend you to use the first method because it is tested & true method that will 100% work for you.

Method 1

Include your template files in your plugin. I stick mine in /plugin/templates.

You need to hook into template location for that template:

add_filter('archive_template', 'yourplugin_get_custom_archive_template');

function yourplugin_get_custom_archive_template($template) {
    global $wp_query;
    if (is_post_type_archive('yourCPT')) {
        $templates[] = 'archive-yourCPT.php';
        $template = yourplugin_locate_plugin_template($templates);
    return $template;

Rinse and repeat with the appropriate checks for each template you want to implement (single, taxonomy etc).

function yourplugin_locate_plugin_template($template_names, $load = false, $require_once = true ) {
    if (!is_array($template_names)) {
        return '';
    $located = '';  
    $this_plugin_dir = WP_PLUGIN_DIR . '/' . str_replace( basename(__FILE__), "", plugin_basename(__FILE__));
    foreach ( $template_names as $template_name ) {
        if ( !$template_name )
        if ( file_exists(STYLESHEETPATH . '/' . $template_name)) {
            $located = STYLESHEETPATH . '/' . $template_name;
        } elseif ( file_exists(TEMPLATEPATH . '/' . $template_name) ) {
            $located = TEMPLATEPATH . '/' . $template_name;
        } elseif ( file_exists( $this_plugin_dir . '/templates/' . $template_name) ) {
            $located =  $this_plugin_dir . '/templates/' . $template_name;
    if ( $load && $located != '' ) {
        load_template( $located, $require_once );
    return $located;

Doing it this way means that WP will look in the theme first for your templates, but will fall back to the plugin’s templates folder if not found in your theme. If users want to modify the templates to fit their theme, they can simply copy them to their theme’s folder.

If you want to be really clever about it, you can force a check for the templates in their theme folder and load some default styles if they’re using the plugin’s copy of the templates:

add_action('switch_theme', 'yourplugin_theme_check');
add_action('wp_enqueue_scripts', 'yourplugin_css');

function yourplugin_css() {
    if(get_option('yourplugin-own-theme') != true && !is_admin()) {
    wp_enqueue_style('yourplugin-styles', plugins_url('/css/yourplugin.css', __FILE__));

function yourplugin_theme_check() {
    if(locate_template('archive-yourCPT.php') != '' && locate_template('single-yourCPT.php') != '' && locate_template('taxonomy-yourTaxonomy.php') != '' && locate_template('taxonomy-anotherTaxonomy.php') != '') {
    update_option('yourplugin-own-theme', true);
     else {
     update_option('yourplugin-own-theme', false);

Note: Use and implement method 1 because this method fully tested our system.
Thank you 🙂

All methods was sourced from or, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply