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:
- It’s an archive template for a custom post type (CPT)
- It includes page content (to be used as archive intro)
- It includes a loop for spitting out any posts belonging to the CPT
- It includes custom fields assigned to the CPT
If you’re already hyperventilating, it’s okay. You can skip the code and download the Genesis Custom Post Type Archive plugin by Travis Smith. It’s a great plugin and includes support for items 1-3 above. In my case, I needed support for item 4, plus I wanted to include custom styling.
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.
For 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:
- 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)
- 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)
- 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:

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.
Create a Page and Apply the Archive Template
We’re on the downhill slide now!
In 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:
- How to Create a Custom Archives Page
- Genesis Grid Style Page Template with Custom Post Type
- Customizing the WordPress Query
- A better, and easier grid loop



Don’t forget wp_reset_postdata() after the loop
Also, why set has_archive to true if you’re using a custom template? you’ll have 2 endpoints with the same content (CPT archive and page template)
Thanks Paul!
Why do you need wp_reset_postdata() if there’s not a secondary loop happening? Good point on the has_archive – I updated the post.
Because widgets can include secondary loops, and if they’re called after your content loop and you haven’t reset your post data, they’ll be affected by whatever changes you made to the query.
Makes 100% sense. Than you!
Great tut Carrie,
I was in need of creating a dedicated page for testimonials and this worked great.
Although… after following the link to Bill Erickson’s website for the custom meta boxes. I then followed a link from his website to Justin Tadlock’s tutorials where he covered “must use” plugins. In total I spent 6 hours building a new framework for all new Genesis projects going forward. Now the ability to create custom post types with customized admin screens is much easier!
Thanks again for the tutorial and for making reference to other people’s code. It has made my coding more efficient.
-rick
Rick, I’m intrigued! Is it a new base child theme of sorts or more some custom functions to re-use? Would love to read a post with your own findings. I LOVE the custom metabox functionality…slick.
Hey Carrie,
It’s code base that can be used with any Genesis child theme. In a nutshell… WordPress functions/customizations go into the MU plugin, Genesis functions/customizations go into custom_functions.php and theme specific go into the functions.php file. Keeping everything separated makes it easier when building the next website thanks to code re-usability and makes changing themes on an existing site easier when some customizations that aren’t theme dependent but are Genesis dependent need to survive the changeover.
-rd
Very nice. Anything that makes work easier/faster/smarter is a good thing.
I’ve been using this pluign and I absolutely love it. The one change I think could be useful, would have a “custom code” section, where I could easily add code above or beneath. I went around this by adding an action on the page and hooking into Genesis instead.
Do you mean on WP-Types? Couldn’t you create a View Template that would do that?
Hi Carrie, very nice work. The only trouble I have is I upgraded to Genesis 1.9 and now this doesn’t work. Can you help me? Thanks a lot
Hi Thierry,
I’m running it on Genesis 1.9 with no problem, so there might be a conflict somewhere else. Can you tell me more about how/where you’re using the code and what specific problem you’re having?
Cheers,
Carrie
Hi Carrie,
In my child theme I created an file called page_listing.php and copied the codes from above. I also use the AgentPress plugin. The only modification is the following:
echo ‘‘ . genesis_get_custom_field( ‘_listing_price’ ) . ‘‘; //retrieve custom field
echo ” . genesis_get_custom_field( ‘_listing_sqft’ ); //retrieve custom field
But nothing from the page_listing.php is displayed but the default loop. Can you think of anything wrong I’m doing here?
Thanks
Hi Carrie. Problem solved. Thanks you codes really help me.
Hi Thierry,
I saw your post come through here and at http://genesissnippets.com/genesis-custom-loop/ – sorry I didn’t get a chance to respond yet, but glad you got it working! Please feel free to post your solution as it may help someone else! Thanks!
Carrie
Just a little thank you for sharing. I looked all over for instructions on this and finally found yours, which were perfect and easy to follow. Used it to create a Brewers List for a beer distributor website. Thanks Carrie!
–Sara
Hey Sara,
Carrie
So glad to hear it. Thanks for letting me know!
Hi Carrie,
Thanks for this tutorial. One odd thing I ran into was that get_the_content() was not returning the content of the page for me for some reason. I changed
echo ” . get_the_content() ;
to
echo ”;
$page_object = get_page( get_the_id() );
echo $page_object->post_content;
and it outputs the content as expected. I noticed on your testimonials page that you did not include any text, just a title, before the testimonials. Have you tested adding content to your page?
Thanks again for the great tut!
I did at one point and then got rid of it. I think the code here could definitely be improved – just hadn’t had a chance to update it yet. Glad you got it to work!
Hi Carrie, Since a created my page_listing.php (see post from April 2 above) which works great. When I use the Search of AgentPress it returns all posts and the layout is different. Which template the Search is using and why do you thing that the query is not working? Thanks
Solved the issue. Have a great day!
Hoops did not fix everything. The search result is not using my custom loop layout. Which template the Search use to return the result? How can I tell the search to use a different template? Thanks
Hi Thierry!
Sorry I don’t know the answer to that one. Try posting over at studiopress.com/forums – I bet somebody knows.
Cheers,
Carrie
I’m a slight bit confused. Is this what I would need to create post templates? Such as, I have a certain type of posts formatted a certain way, but different from the usual post style?
I want to be able to choose a certain blog post template (that would include sorta like a signature or bit of text that would be at the end of every post of that type) from a drop down menu within the “add new post” editor.
Or am I looking for something else?
Nah, I think you’re looking to create a custom page template and then set a particular post to use that template. Depending on how crazy you’re going with formatting, you may be able to just use a custom post class.
Dear wonderful Carrie
how can i use this for custom post type taxonomies?
i have a CPT of ‘product’
and custom taxonomy of ‘product-category’
and a custom template called ‘taxonomy-product-category.php’ where i’ll drop in the code.
can’t seem to get my head around displaying taxonomies
i need to have the custom loop as you have done, that way i can tweak as needed.
i know it is something simple that needs to be changed in the ‘$args = array’
i’m using genesis 2.0 beta
really hope you can help, it would be greatly appreciated.