Custom Post Type Archive Template Page

How to Create an Archive Template for a Custom Post Type

Update!

Since this post was originally written, Genesis 2.0 was released and now includes built-in support for custom post type archives without the use of a template. Check out this tutorial for more detail on setting up those archive pages.

Ok, readers. Grab your goggles and your oxygen mask because we’re going deep into some code today! I’ve been looking for a way to create an archive template for a custom post type. There are a number of good tutorials out there, but none of them were *quite* what I wanted.

In this tutorial, I’ll show you how to create a custom archive template that meets the following criteria:

  1. It’s an archive template for a custom post type (CPT)
  2. It includes page content (to be used as archive intro)
  3. It includes a loop for spitting out any posts belonging to the CPT
  4. It includes custom fields assigned to the CPT

Still with me? Let’s dive in!

Create a Custom Post Type

There are plenty of tutorials out there for creating custom post types in WordPress (here’s a great one by Justin Tadlock) or you can use a plugin like WP Types (aff link) to do it for you, so I won’t rehash that process here.

Testimonials Custom Post TypeFor this example, I’ve created a custom post type called testimonials with the end goal to show an archive page showing all my client testimonials.

Have you created your custom post type? Let’s move on.

Create some Custom Fields

If you want to create custom fields for a post, you have three basic options:

  1. Use WordPress’ built-in support for custom fields. The interface is rather ugly, but it works. (If you don’t see a Custom Fields metabox on your post edit screen, make sure it’s turned on via your Screen Options tab in the upper right corner)
  2. Use one of the many WordPress plugins to create a neat metabox with your custom fields. (I’ve used the WP Types plugin, which is overkill for just this task but does handle groups of custom fields very nicely)
  3. Roll up your sleeves and create your own custom meta box for custom fields. Bill Erickson (along with some top-notch WordPress developers) created the Custom Metaboxes and Fields code that’s super sharp and available on Github for your free use.

I’m creating my custom fields using the third option. Since my CPT is for client testimonials, I’ll create some custom fields for the client’s name and job title. The finished metabox on my post looks like this:

Custom Metabox with Fields

Create a Custom Post Type Archive Template

I’ll assume at this point that you’ve already got some posts created. WordPress has a default archive template (archive.php), but I want to create a specific archive page with a custom loop for my Testimonials CPT.

Following the WordPress template hierarchy naming protocol, I’m going to use this structure to name my template file: archive-{post_type}.php. Since my post type is testimonials, I’ll name it archive-testimonials.php and upload that to the root directory of my child theme folder.

Now we need to fill in the page content. I’ve tried to comment the main gist of the code, but leave a comment if you have a question about anything.

<?php
/**
* Template Name: Testimonial Archives
* Description: Used as a page template to show page contents, followed by a loop through a CPT archive
*/
remove_action ('genesis_loop', 'genesis_do_loop'); // Remove the standard loop
add_action( 'genesis_loop', 'custom_do_grid_loop' ); // Add custom loop
function custom_do_grid_loop() {
// Intro Text (from page content)
echo '<div class="page hentry entry">';
echo '<h1 class="entry-title">'. get_the_title() .'</h1>';
echo '<div class="entry-content">' . get_the_content() ;
$args = array(
'post_type' => 'testimonials', // enter your custom post type
'orderby' => 'menu_order',
'order' => 'ASC',
'posts_per_page'=> '12', // overrides posts per page in theme settings
);
$loop = new WP_Query( $args );
if( $loop->have_posts() ):
while( $loop->have_posts() ): $loop->the_post(); global $post;
echo '<div id="testimonials">';
echo '<div class="one-fourth first">';
echo '<div class="quote-obtuse"><div class="pic">'. get_the_post_thumbnail( $id, array(150,150) ).'</div></div>';
echo '<div style="margin-top:20px;line-height:20px;text-align:right;"><cite>'.genesis_get_custom_field( '_cd_client_name' ).'</cite><br />'.genesis_get_custom_field( '_cd_client_title' ).'</div>';
echo '</div>';
echo '<div class="three-fourths" style="border-bottom:1px solid #DDD;">';
echo '<h3>' . get_the_title() . '</h3>';
echo '<blockquote><p>' . get_the_content() . '</p></blockquote>';
echo '</div>';
echo '</div>';
endwhile;
endif;
// Outro Text (hard coded)
echo '<div class="call-to-action">Want me to make your next web project easier? <a href="http://www.carriedils.com/contact">Let\'s Talk</a></div>';
echo '</div><!-- end .entry-content -->';
echo '</div><!-- end .page .hentry .entry -->';
}
/** Remove Post Info */
remove_action('genesis_before_post_content','genesis_post_info');
remove_action('genesis_after_post_content','genesis_post_meta');
genesis();

Create a Page and Apply the Archive Template

We’re on the downhill slide now!

Page Attributes - TemplateIn order to include some introductory text before the testimonials, I’ll create a regular page, give it the title Client Testimonies and add some text to the content editor.

The last step is to go the Page Attributes metabox and assign the custom template (when you create an archive page template and place it in the child theme directory, it’ll automatically show up in the Template list).

Save the page and view it using the page slug! Here’s the finished product!

Additional Resources:

This post required me to dig into (and better understand) WordPress queries, the default Genesis loop, and custom loops. I found the following articles very helpful:

WordPress Speed Test

80 thoughts on “How to Create an Archive Template for a Custom Post Type”

Leave a Comment

Your email address will not be published. Required fields are marked *

Carrie Dils uses Accessibility Checker to monitor our website's accessibility.