But wait! I’ve got more about dashboards! Dashboards in WordPress, I mean. Not the admin dashboard, but other kinds of dashboards. We need a WordPress child theme and a custom post type (CPT) to do the job right.

When we left last week’s dashboard scenario, we had a flat page built using Divi.

Dashboard Custom Post Type (CPT)

Maybe it’s just the developer in me, but I like it when genuinely different data types have different post types within WordPress, so I wanted to create a custom post type (CPT) for dashboard pages.

As an aside, an important advantage to this is that, assuming dashboards contain the same elements for each client, the actual guts of the dashboard—the bells, the dials, the pie charts—can be coded into a template specific to the dashboard, meaning that the only thing that needs to get created for a new client is a post that holds the client name and probably their logo. Maybe a gratuitous picture of a zebra.

We’ll get to the template thing, but for the moment let’s set that part aside for later.

As far as I’m aware, there’s no way to create a CPT from the admin console. Instead, you need to do it in custom code, typically within a plugin. Here’s an ultra-simple plugin that does precisely that.



 * @package AlphaZebra

 * @version 0.0.1



Plugin Name: PZPublish

Plugin URI:

Description: It sets up custom post types! Yay!

Author: The Alpha Zebra

Version: 0.0.1

Author URI:


/ call our custom function with the init hook

add_action( ‘init’, ‘pz_register_cpts’ );

 // custom function to register a “publication” post type

function pz_register_cpts() {

    // and dashboard

     register_post_type( ‘dash’,


         ‘labels’ => array(

             ‘name’ => __( ‘Dashboards’ ),

             ‘singular_name’ => __( ‘Dashboard’ ),

             ‘add_new_item’ => __(‘Add New Dashboard’),


     ‘public’ => true,

     ‘has_archive’ => true,

     ‘show_in_rest’ => true,




I’ve used “dash” for the CPT internal name, because I suspect WordPress may use “dashboard” for the admin console. But the display names say “Dashboards” and “Dashboard”. Admittedly, this could be confusing, but it’s just us in the back end, so it’s probably ok.

If you install a plugin like this, you’ll need to jump into “Tools/Permalinks” and save the settings again to get the new dash type listing and displaying properly (it’s a quirk, just trust me on this one).

In any case, with the dashboards living in the “dash” CPT world, you can now create posts that won’t be shown in contexts other than client interactions.

WordPress Child Theme Templates

If you create a couple of more or less empty “dash” posts at this point, a user can list them in what WordPress calls an “Archive” page, from which you can click on the one you want and view the single (mostly empty) dash page.

This isn’t actually the behavior we want (we want the user to go straight to the specific dashboard post they are allowed to access), but we’ll get to that. For the moment, note that the layout for the page is governed by whatever is serving as the default archive template for the theme we’re using.

When we click and display a single dash page, the look of the page is governed by whatever the default single page template for the current theme is.

If you haven’t worked with customizing or developing WordPress themes before, the following discussion is probably going to seem a little murky, but the end goal is to create a specific appearance for views of single dash posts. So we’re going to create a custom template for single dash posts.

Because we are good people and, more’s the point, competent developers, we are not going to create this template file alongside the template files in our original theme. Rather, we are going to take advantage of WordPress’s extremely handy support for what it calls child themes.

A child theme is just a collection of things you’d like to change from the original theme. Any file you mess with is placed in your child theme folder and it will take precedence over the original version in the original theme folder. So you get your original theme, plus any tweaks. When the original theme is updated by whomever created it, your tweaked files don’t get overwritten and your changes remain in force.

(OK, it is not, strictly speaking, 100% true that new files and settings take precedence. There are just a couple of exceptions and they don’t matter for this discussion, so I’m ignoring them.)

The file structure of themes has changed over time, plus not all aspects of theme building are controlled by strict rules, so not all themes work quite the same way with respect to template files. That’s annoying, but it’s not a huge deal and it’s basically just another small twist that I’m going to ignore in this article.

For the theme I’m tweaking, which is the Extra theme from Elegant Themes, creating a new archive template means making a couple of files. One is single-dash.php, which is the wrapper template for views of a single dash post. The other, called from within single-dash.php, lives in the template-parts subdirectory and is called content.dash.php.

Both of these files just start out as copies of the normal post templates stored in the Extra theme directory. Note that if I don’t use these files, the dash posts will be treated like regular posts and displayed that way. For the moment, this isn’t actually a problem. So I’m going to save these two templates for a future post. For the moment, then, I’m going to make a child copy of the theme’s header.php, which gets called for any post type that doesn’t have its own custom header file.

We do want to control access to the page so that only admins and the specific client can get into each dash page.

So here’s a bit of PHP that I’ve added to the child copy of header.php in the template, just after the body section opens as you can see:

<body <?php body_class(); ?>>


      global $post;

      // get post type name

            $CPTName = get_post_type();

            if( $CPTName == ‘dash’) {

                  // get post slugname

                  // get user name

                  $currentUser = wp_get_current_user();

                  $role = ‘admin’;

                  if( !strcmp($role, ‘admin’ ) === 0 ) {

                  if( stristr( $post->post_name, $currentUser->user_login ) === false ) {

                        //redirect to home page

                        wp_redirect( ‘https://peakzebra.com/’);





All I’m doing here is making sure that the user name of the current user (which I create and control in this application) is part of the requested dash post slug name. If that’s not the case (and if it’s not an admin viewing the page), the user is redirected to the home page.

So you have to have successfully logged in to an account I’ve created for you and be trying to access the dashboard that matches to your account.

Right now, the dashboard pages are copied from one to the next and tweaked for each client’s different data sources, but this is, I’d be the first to admit, a dumb way to do it. So next time around we’ll change the template so that it’s the template pulling in the pieces, using the client name as a parameter to fetch the right components on the page. So, yes, more to come on this topic.