Using Wordpress Insert Pages plugin with your Custom Post Types and Custom Templates

Wes Modes
9 min readMar 14, 2020

--

Custom Post Types (CPTs) allow you to define complex data as a special kind of post type that WordPress handles exceptionally well. But combined with custom post templates and a few select plugins is where WordPress really helps moderately experienced developers create rich custom websites.

Creating a Custom Post Type

I used the CPT UI plugin to create a Custom Post Type. It does the heavy lifting of creating a CPT adding the appropriate menu items and editing functions.

CPT UI does the heavy lifting of creating a Custom Post Type

You can specify what aspects of the editor you want to include for your CPT (editor, featured image, comments, etc).

CPT UI: Specify what features you want your CPT to support

You can use a plugin like CPT UI or you can add code to your theme’s function.php to create the CPT. For example, to add my “thing” type to the “understraps” theme, I could use the code:

function cptui_register_my_cpts_thing() {
/**
* Post Type: Things.
*/
$labels = [
"name" => __( "Things", "understrap" ),
"singular_name" => __( "Thing", "understrap" ),
"menu_name" => __( "Things", "understrap" ),
"all_items" => __( "All Things", "understrap" ),
"add_new" => __( "Add new", "understrap" ),
"add_new_item" => __( "Add new Thing", "understrap" ),
"edit_item" => __( "Edit Thing", "understrap" ),
"new_item" => __( "New Thing", "understrap" ),
"view_item" => __( "View Thing", "understrap" ),
"view_items" => __( "View Things", "understrap" ),
"search_items" => __( "Search Things", "understrap" ),
"not_found" => __( "No Things found", "understrap" ),
"not_found_in_trash" => __( "No Things found in trash", "understrap" ),
"parent" => __( "Parent Thing:", "understrap" ),
"featured_image" => __( "Featured image for this Thing", "understrap" ),
"set_featured_image" => __( "Set featured image for this Thing", "understrap" ),
"remove_featured_image" => __( "Remove featured image for this Thing", "understrap" ),
"use_featured_image" => __( "Use as featured image for this Thing", "understrap" ),
"archives" => __( "Thing archives", "understrap" ),
"insert_into_item" => __( "Insert into Thing", "understrap" ),
"uploaded_to_this_item" => __( "Upload to this Thing", "understrap" ),
"filter_items_list" => __( "Filter Things list", "understrap" ),
"items_list_navigation" => __( "Things list navigation", "understrap" ),
"items_list" => __( "Things list", "understrap" ),
"attributes" => __( "Things attributes", "understrap" ),
"name_admin_bar" => __( "Thing", "understrap" ),
"item_published" => __( "Thing published", "understrap" ),
"item_published_privately" => __( "Thing published privately.", "understrap" ),
"item_reverted_to_draft" => __( "Thing reverted to draft.", "understrap" ),
"item_scheduled" => __( "Thing scheduled", "understrap" ),
"item_updated" => __( "Thing updated.", "understrap" ),
"parent_item_colon" => __( "Parent Thing:", "understrap" ),
];
$args = [
"label" => __( "Things", "understrap" ),
"labels" => $labels,
"description" => "Used for all single elements (ads) that appear in the publication",
"public" => true,
"publicly_queryable" => true,
"show_ui" => true,
"show_in_rest" => true,
"rest_base" => "",
"rest_controller_class" => "WP_REST_Posts_Controller",
"has_archive" => false,
"show_in_menu" => true,
"show_in_nav_menus" => true,
"delete_with_user" => false,
"exclude_from_search" => false,
"capability_type" => "post",
"map_meta_cap" => true,
"hierarchical" => false,
"rewrite" => [ "slug" => "thing", "with_front" => true ],
"query_var" => true,
"menu_position" => 5,
"supports" => [ "title", "thumbnail", "excerpt" ],
"taxonomies" => [ "post_tag" ],
];
register_post_type( "thing", $args );
}
// register the new CPT
add_action( 'init', 'cptui_register_my_cpts_thing' );

Creating Custom Fields For Your Custom Post Type

CPT UI is pretty basic, and doesn’t define custom fields which are useful in a CPT. For this, I used the Advanced Custom Fields plugin (often called ACF). With AFT, you can define various types of custom fields (text fields, textarea, images, numbers, edit fields, etc) for your CFT.

Advanced Custom Fields allows you to define custom fields for your CFT.

These can be highly customized defining type of field, min and max values, filetypes, etc.

Advanced Custom Fields: Configuring custom fields

Creating a Custom Page (or Post) Template For Your CPT

Once you define your Custom Post Type and Custom Fields, you will likely need to define a custom WordPress template to display them. A good way to start is to copy the default Wordpress post template single.php or the default page template page.php from your theme to a new template. You must name your new template single-mycpt.php where mycpt is the slug for your Custom Post Type. It includes the headers, nav, sidebars, comments, and footers for your page or post. I’ll refer to this as a page or post template. Here is my post template single-thing.php for my Custom Post Type “thing.”

<?php
/**
* Template Name: Thing Page
* Template Post Type: thing

*
* Page for displaying a single ad.
*
* @package understrap
*/
// Exit if accessed directly.
defined( 'ABSPATH' ) || exit;
get_header('thing');
$container = get_theme_mod( 'understrap_container_type' );
?>
<div class="wrapper" id="single-wrapper"> <div class="<?php echo esc_attr( $container ); ?>" id="content" tabindex="-1"> <div class="row"> <main class="site-main" id="main"> <?php while ( have_posts() ) : the_post(); ?> <?php get_template_part( 'loop-templates/content-thing', 'single' ); ?> <?php understrap_post_nav(); ?> <?php endwhile; // end of the loop. ?> </main><!-- #main.site-main --> </div><!-- .row --> </div><!-- #content --></div><!-- #single-wrapper --><?php get_footer();

Note three things about this post template: First the header block allows WordPress and plugins to recognize your template. Second, the line <?php while ( have_posts() ) : the_post(); ?> begins “The Loop”, how WordPress displays the content of your post or page. The third thing is the code inside the loop that calls the function get_template_part(). We’ll talk about this next.

Creating a Custom Content Template for your CPT

Many themes divide the business of presenting a post or page to a content template (e.g., loop-templates/content-mycpt.php), which is a good practice. These templates are handling the presentation stuff inside the loop. By default, they present the title, content or excerpt (depending on the context). Here’s my content template loop-templates/content-thing.php for my “thing” CPT.

<?php
/**
* Template Name: Thing Template
* Template Post Type: thing,page,post
*
* Template for displaying an ad.
*
* @package understrap
*/
// Exit if accessed directly.
defined( 'ABSPATH' ) || exit;
?>
<article <?php post_class(); ?> id="post-<?php the_ID(); ?>"> <div class="entry-content thing-content"> <div class="image">
<?php $ad_image = get_field('ad_image'); ?>
<?php if ( ! empty ( $ad_image ) ): ?>
<img
src="<?php echo $ad_image['url']; ?>"
alt="<?php echo $ad_image['alt']; ?>" />
<?php else: ?>
<?php $ad_content = get_field('ad_content'); ?>
<?php echo $ad_content; ?>
<?php endif; ?>
</div> <!-- .image -->
</div><!-- .entry-content.thing-content --></article><!-- #post-## -->

Note that it has a template comment header at the top and that it uses the get_field() function which is part of the Advanced Custom Fields plugin to display fields.

Remember to go back to your page template and change the get_template_part() line to point to your new content template.

Inserting a CPT in Another Post or Page

To insert a Custom Post Type into another post or page, I use the Insert Pages plugin. Insert Pages allows you to use your custom templates to present your CPTs.

If you are using the Gutenberg block editor, search for an Insert Pages block.

Insert Pages adds a new Gutenberg block type

You will have to specify the CPT you want to use and the content template you want to use. Insert Pages will allow you to search for your CPT (handy!), but you have to specify the path to the custom content template.

Specify the CPT to insert and the custom content template you want to use

If you are using Elementor or Beaver Builder, you also get a new Insert Pages block. You will have to specify the slug of the CPT you want (no search this time), but if your template has a proper header and is in the templates directory, it will be offered as one of the custom template options.

Here are a few specific nuances I’ve learned that may help you use Insert Pages to insert your CPTs using your custom templates.

1. Use the content template not the page template

You created a custom page template for your CPT (e.g., single-mycpt.php). This allows you to see your CPT on its own page or post. But you probably don’t want to use your page or post template with Insert Pages, unless you want to insert your nav, header, and footer twice within every inserted page.

The content template you created for your CPT (e.g., loop-templates/content-mycpt.php), is the template you probably want to use for Insert Pages. If you added the proper headers to your template and it is inside your template directory, Insert Pages should find it and offer it as a custom template choice.

2. Make sure you have a proper template comment block

For your content template to show up in the Insert Pages config block in Elementor or Beaver Builder, you need to include a standard template comment block at the top. Here’s the Post Type Template used since WP 4.7.

Here’s my comment block in my content template for the “thing” CPT:

<?php
/**
* Template Name: Thing Template
* Template Post Type: thing,page,post
*
* Template for displaying an ad.
*
* @package understrap
*/
// Exit if accessed directly.
defined( 'ABSPATH' ) || exit;
?>

3. Insert Pages may not find your templates in a child theme

If you use a child-theme, there is a possibility that your template directory defaults to the parent theme folder. In that case, if you put your templates in the child-theme folder Insert Pages won’t find them. That may change in the future, but I don’t have a workaround for that.

I shifted from a child theme to my own theme which used UnderStrap as a jumping off point.

4. CPT content templates may need “The Loop”

If you use the content template to present your post or CPT, many WP functions only work within The Loop. The loop tells many WP and plugin functions which post we are referring to. In many cases, there are alternatives functions that work outside of The Loop. But if you don’t have an alternative, you can move your Loop out of the single template into your content template.

For example, in the custom templates above, I’ve commented out the loop in my post template and added it to my content template. Here’s a portion of my post template:

<?php // while ( have_posts() ) : the_post(); ?>  <?php get_template_part( 'loop-templates/content-thing', 'single' ); ?>  <?php understrap_post_nav(); ?><?php //endwhile; // end of the loop. ?>

And here’s the lines I’ve added to my content template. Near the top:

// Exit if accessed directly.
defined( 'ABSPATH' ) || exit;
?>
<?php while ( have_posts() ) : the_post(); ?> <article <?php post_class(); ?> id="post-<?php the_ID(); ?>">

And the bottom:

  </article><!-- #post-## --><?php endwhile; // end of the loop. ?>

This allows me to specify my content template and have it displayed on another post or page with Insert Pages.

Conclusions

None of this is for the faint of heart. It involves a good bit of experimentation and methodical trial-and-error. While most of this could be done, by using WP’s Theme Editor, it helps to have knowledge of GIT or SFTP to upload files.

However, Custom Post Types with Custom Fields is a very powerful feature of modern WordPress. Combined with custom templates and a few select plugins, you can create a very rich complex website with a minimum of effort.

I’ve done my best to break this down as clearly as possible. If it still seems confounding (“WTF is The Loop?”), it may help to read WordPress’ very excellent developer documentation, which details both high-level concepts and every WP function.

Good luck and happy experimenting.

--

--

Wes Modes

Wes Modes is a California educator and artist focused on social practice, sculpture, performance and new media work.