Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
Creates 'fake' sub-pages for custom post types in WordPress. In this example we are creating 3 sub-pages called "About", "People" and "Information" for the CPT "department"
* Creates fake sub pages for a custom post type.
// Create 'Fake sub-pages' permalinks and titles.
$sub_pages = array(
'about' => 'About',
'people' => 'People',
'information' => 'Information',
add_filter('rewrite_rules_array', 'ace_insertrules');
add_filter('query_vars', 'ace_insertqv');
// Adding fake sub-pages' rewrite rules
function ace_insertrules($rules)
global $sub_pages;
$newrules = array();
foreach ($sub_pages as $slug => $title)
$newrules['department/([^/]+)/' . $slug . '/?$'] = 'index.php?department=$matches[1]&fpage=' . $slug; // department is the name of our custom post type
return $newrules + $rules;
// Tell WordPress to accept our custom query variable
function ace_insertqv($vars)
array_push($vars, 'fpage');
return $vars;
// Remove WordPress's default canonical handling function
remove_filter('wp_head', 'rel_canonical');
add_filter('wp_head', 'ace_rel_canonical');
function ace_rel_canonical() {
global $current_sp, $wp_the_query;
if (!is_singular())
if (!$id = $wp_the_query->get_queried_object_id())
$link = trailingslashit(get_permalink($id));
// Make sure sub-pages' permalinks are canonical
if (!empty($current_sp))
$link .= user_trailingslashit($current_sp);
echo '<link rel="canonical" href="'. $link .'" />';
// If using Yoast - remove the canonical link from your custom post type as we set proper canonical tags above.
function ace_seo_canonical_exclude( $canonical ) {
global $post;
if (is_singular('department')) {
$canonical = false;
return $canonical;
add_filter( 'wpseo_canonical', 'ace_seo_canonical_exclude' );
* Department single page template
* We have created sub (fake) pages in create-sub-pages-for-custom-post-type.php to display content from our custom posts types that have a relationship with the current Department
* This is so we can have the correct permalink
// get the current sub-page slug
$current_sp = get_query_var('fpage');
// If we have a sub-page slug and are therefore on a sub-page then remove the standard loop so we don't show the content of the parent post on sub-pages
if ($current_sp) {
remove_action( 'genesis_loop', 'genesis_do_loop' );
add_action ('genesis_loop', 'ace_get_subpage_template');
// Get the current sub-page slug and load the correct template part
function ace_get_subpage_template() {
$current_sp = get_query_var('fpage');
if ( $current_sp == 'about' ) {
else if ( $current_sp == 'information' ) {
else if ( $current_sp == 'people' ) {
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.