J.me

Customize Custom Post Type Landing Page with Clean URL

WordPress has been long capable on using custom post type. Since WordPress 3.0, we are now easier to create a custom post type. I have blogged some tips about it.

However, many didn’t know that the custom post type already had it’s own landing page, though, you will need to pass the post type variable to the URL. This post will guide you to the step by step on customizing the post type landing page, as well as adding a new rewrite rule for a cleaner URL.

Register the Post Type

First of all, let’s create our custom post type. In this example, we will register a book post type.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
function theme_init()
{
	$labels = array(
		'name' => __('Books'),
		'singular_name' => __('Book'),
		'add_new' => __('Add Book'),
		'add_new_item' => __('Add New Book Item'),
		'edit_item' => __('Edit Book Item'),
		'new_item' => __('New Book Item'),
		'view_item' => __('View Book Item'),
		'search_items' => __('Search Books'),
		'not_found' =>  __('Nothing found'),
		'not_found_in_trash' => __('Nothing found in Trash'), 
		'parent_item_colon' => ''
	);
	$args = array(
    	'labels' => $labels,
    	'public' => true,
    	'publicly_queryable' => true,
    	'show_ui' => true, 
    	'query_var' => true,
    	'rewrite' => true,
    	'capability_type' => 'post',
    	'hierarchical' => false,
    	'menu_position' => null,
    	'supports' => array('title','editor','author','thumbnail','excerpt','comments')
  	); 
  	register_post_type('book', $args);
}
add_action('init', 'theme_init');

Add this code to the theme functions.php. We hook the function to the init action. In case you didn’t know the WordPress hook, you can take a good read on codex.

The post type is now ready to use, it appeared on the back-end, you can add, edit and remove the book. The single post is accessible now. The landing page is accessible by appending ?post_type=book to your website URL.

Clean the URL

Now, we want to make the URL cleaner. Instead of accessing the landing page with yourwebsite.com/?post_type=book, we want to make it yourwebsite.com/book instead. We can do this by adding a new rewrite rule.

1
2
3
4
5
6
7
function theme_rewrite()
{
	add_rewrite_rule('book/?$', 'index.php?post_type=book', 'top');
	add_rewrite_rule('book/page/(\d+)/?$', 'index.php?post_type=book&paged=$matches[1]', 'top');
	//flush_rewrite_rules(); // run one time only
}
add_action('init', 'theme_rewrite');

Again, add this to the theme functions.php file. We add a new rewrite rule and redirect it to index.php?post_type=book, don’t forget to use ‘top’ in the third parameter, this is to make sure this rule must be run before any other WordPress rule. We also add another rule to work with pagination.

Notice the commented line above? After we add a new rewrite rule, we must flush the rewrite rules. This must be done one time when it is changed. So when you have it run once, comment or remove that line as it is not needed anymore. The rules will also flushed when you go to Settings -> Permalinks in back-end.

However, the add rewrite rule line must be keep though, as if you remove it, the next time it flushed, you will lost the rule.

Customizing the Landing Page

The current landing page used the same template as the home page, which in most case is either front-page.php, home.php or index.php. This isn’t good as they are shared with any other post type. So, we must create a new filter, to look for home-book.php before falling to another template.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function theme_home_template( $template )
{
	if ( get_query_var('post_type') )
	{
		$new_template = 'home-'.get_query_var('post_type').'.php';
		$templates = array(
			$new_template,
			$template
		);
		return locate_template($templates);
	}
	return $template;
}
add_filter('home_template', 'theme_home_template');

Add this code again to theme’s functions.php. Then, create the home-book.php and customize it to the way you need. 🙂

Conclusion

That’s it. So to conclude it, we first register the post type as usual, then adding a rewrite rule for the sake of cleaner URL. Finally, we create a new home-{post_type}.php file to serve as the template of the landing page. Now that we have the template, we can customize it to every way we wanted.

A different approach can be done though, such as creating a page and a custom template that query to the post type. I have used this on some of my clients. The downside is we will create a blank page, not that it’s bad, but it’s always good to not leave any junk in the administration back-end – so user can’t remove it accidentally and break the site.

This approach, although a little tricky, is a good way to make everything work seamlessly without any configuration needed. 😉

No comment yet

Leave a comment