Assign Categories to Pages in WordPress

by Amit Verma on February 17, 2010

in Blogging, tools

WordPress has different options for organizing posts. One of them is Categories. The categories can only be assigned to posts, not to pages in WordPress. But sometime you might want to categorize the pages as well. Here are a few cases.

  1. To display related posts on a page.
  2. To display pages and categories in navigation menu in mixed order. WordPress provides the two different functions to display a list of Pages and Categories. But it doesn’t give the option to setup a navigation menu mixed with pages and categories, like the example given below. In such a case you can map pages to categories and use them as category pages. Obviously it will need some changes in the template.
    • Page 1
    • Page 2
    • Category 1
    • Page 3
    • Category 2
  3. To display pages on the category pages with the posts.

How to map Categories to pages

Add following lines of code in the function.php of your theme directory. If you don’t have a function.php in the theme directory then you can add it using any text editor. You can also download the plugin which I have made from http://wordpress.org/extend/plugins/map-categories-to-pages/.

function add_category_box_on_page(){
//add meta box
add_meta_box('categorydiv', __('Categories'), 'post_categories_meta_box', 'page', 'side', 'low');
}

add_action('admin_menu', 'add_category_box_on_page');

function page_categories_meta_box($post) {
?>
<ul id="category-tabs">
	<li class="tabs"><a href="#categories-all" tabindex="3"><?php _e( 'All Categories' ); ?></a></li>
	<li class="hide-if-no-js"><a href="#categories-pop" tabindex="3"><?php _e( 'Most Used' ); ?></a></li>
</ul>

<div id="categories-pop" class="tabs-panel" style="display: none;">
	<ul id="categorychecklist-pop" class="categorychecklist form-no-clear" >
<?php $popular_ids = wp_popular_terms_checklist('category'); ?>
	</ul>
</div>

<div id="categories-all" class="tabs-panel">
	<ul id="categorychecklist" class="list:category categorychecklist form-no-clear">
<?php wp_category_checklist($post->ID, false, false, $popular_ids) ?>
	</ul>
</div>

<?php if ( current_user_can('manage_categories') ) : ?>
<div id="category-adder" class="wp-hidden-children">
	<h4><a id="category-add-toggle" href="#category-add" class="hide-if-no-js" tabindex="3"><?php _e( '+ Add New Category' ); ?></a></h4>
	<p id="category-add" class="wp-hidden-child">
	<label class="screen-reader-text" for="newcat"><?php _e( 'Add New Category' ); ?></label><input type="text" name="newcat" id="newcat" class="form-required form-input-tip" value="<?php esc_attr_e( 'New category name' ); ?>" tabindex="3" aria-required="true"/>
	<label class="screen-reader-text" for="newcat_parent"><?php _e('Parent category'); ?>:</label><?php wp_dropdown_categories( array( 'hide_empty' => 0, 'name' => 'newcat_parent', 'orderby' => 'name', 'hierarchical' => 1, 'show_option_none' => __('Parent category') ) ); ?>
	<input type="button" id="category-add-sumbit" class="add:categorychecklist:category-add button" value="<?php esc_attr_e( 'Add' ); ?>" tabindex="3" />
<?php	wp_nonce_field( 'add-category', '_ajax_nonce', false ); ?>
	<span id="category-ajax-response"></span></p>
</div>
<?php
endif;

}
?>

It will show the category selection box on the right side on “Edit Page” page.

Template changes

You will also have to edit the page template to use categories. You can use standard category code on your page template. Take a look at http://codex.wordpress.org/Function_Reference/get_the_category and http://codex.wordpress.org/Template_Tags/the_category.

Here is a small piece of code to build a page of posts. This example uses the styles from WordPress default theme.

<?php
global $post;
$cats=array();
foreach(get_the_category() as $category) { 
	$cats[]=$category->cat_ID; 
}
$showposts = -1; // -1 shows all posts
$do_not_show_stickies = 1; // 0 to show stickies
$args=array(
   'category__in' => $cats,
   'showposts' => $showposts,
   'caller_get_posts' => $do_not_show_stickies
   );
$my_query = new WP_Query($args);

?>

	<?php if( $my_query->have_posts() ) : ?>

		<?php while ($my_query->have_posts()) : $my_query->the_post(); ?>
			<?php
			//necessary to show the tags
			global $wp_query;
			$wp_query->in_the_loop = true;
			?>
			<div <?php post_class() ?> id="post-<?php the_ID(); ?>">
				<h2><a href="<?php the_permalink() ?>" rel="bookmark" title="Permanent Link to <?php the_title_attribute(); ?>"><?php the_title(); ?></a></h2>
				<small><?php the_time('F jS, Y') ?> <!-- by <?php the_author() ?> --></small>

				<div class="entry">
					<?php the_content('Read the rest of this entry »'); ?>
				</div>

				<p class="postmetadata"><?php the_tags('Tags: ', ', ', '
'); ?> Posted in <?php the_category(', ') ?> | <?php edit_post_link('Edit', '', ' | '); ?>  <?php comments_popup_link('No Comments »', '1 Comment »', '% Comments »'); ?></p>
			</div>

		<?php endwhile; ?>

	<?php else : ?>

		<h2 class="center">Not Found</h2>
		<p class="center">Sorry, but you are looking for something that isn't here.</p>

	<?php endif; ?>

Displaying pages on Category pages

When WordPress fetches the posts from database, the default post type is ‘post’. So even when you have mapped a page to a category, it won’t display the page on that category page. The post type needs to be changed explicitly on the category page. To change the post type, add following code in function.php.

//call a function just before the query runs to fetch posts
add_action('pre_get_posts','change_post_type');

function change_post_type($var) {
	if(is_category()) {
    	    	$var->query_vars['post_type'] = 'any';
            	//it will change the value to 'any' from the default value of ;post';
            	//can be any, attachment,  page, post, or revision.
            	//'any' retrieves any type except revisions.
	}
}
Be Sociable, Share!

{ 36 comments… read them below or add one }

dandy March 1, 2010 at 12:01 pm

Very nice effort indeed. This would be really useful. But this isnt working for Wordpress 2.8.6

i get this error when i activate plugin. This error is shown on edit page below categories box.

Warning: call_user_func(post_categories_meta_box) [function.call-user-func]: First argument is expected to be a valid callback in /home2/artefact/public_html/wp-admin/includes/template.php on line 2936

Can you please check?

Thanks.

Reply

Amit March 1, 2010 at 3:27 pm

@dandy I have tested the current version with WP 2.8.6 and there was no problem in activating the plugin but there was some problem in the Category box on “edit page” page. So I have updated the plugin and you can download it from here. I have tested it on WP 2.8.6. Hope it will help. If still it doesn’t work, feel free to contact me. Let me know how it goes.

I will update it on wordpress plugin directory soon with a option to display Pages on Category pages.

Reply

dandy March 1, 2010 at 3:46 pm

Thanks Amit for your prompt reply and help. I really appreciate. And thanks for fixing up the issue. It works great now and i can assign category to my pages now.

But i think this isnt what i wanted. I wanted to assign pages to categories and then display specific category pages using wp_query.
Like, i wanted to make a category “Header Navigation Pages” and then put all pages in this category that are to appear in header top navigation and then do something like this

<a href="">

But as i assign pages to category and go to “manage category” menu, i see “0″ as a post count in that category.

Still thanks anyway, this is a great plugin indeed.

Reply

dandy March 1, 2010 at 3:47 pm

Thanks Amit for your prompt reply and help. I really appreciate. And thanks for fixing up the issue. It works great now and i can assign category to my pages now.

But i think this isnt what i wanted. I wanted to assign pages to categories and then display specific category pages using wp_query.
Like, i wanted to make a category “Header Navigation Pages” and then put all pages in this category that are to appear in header top navigation and then do something like this

<a href="”>

But as i assign pages to category and go to “manage category” menu, i see “0″ as a post count in that category.

Still thanks anyway, this is a great plugin indeed.

Reply

dandy March 1, 2010 at 3:47 pm

Thanks Amit for your prompt reply and help. I really appreciate. And thanks for fixing up the issue. It works great now and i can assign category to my pages now.

But i think this isnt what i wanted. I wanted to assign pages to categories and then display specific category pages using wp_query.
Like, i wanted to make a category “Header Navigation Pages” and then put all pages in this category that are to appear in header top navigation and then do something like this

<a href="”>

But as i assign pages to category and go to “manage category” menu, i see “0″ as a post count in that category.

Still thanks anyway, this is a great plugin indeed.

Reply

dandy March 1, 2010 at 3:49 pm

Thanks Amit for your prompt reply and help. I really appreciate. And thanks for fixing up the issue. It works great now and i can assign category to my pages now.

But i think this isnt what i wanted. I wanted to assign pages to categories and then display specific category pages using wp_query.
Like, i wanted to make a category “Header Navigation Pages” and then put all pages in this category that are to appear in header top navigation and then do something like this

wp_reset_query();$postlist = get_posts(‘category_name=header_navigation_pages&numberposts=4′);

foreach ($postlist as $post){ setup_postdata($post); ?> <a href="”>

But as i assign pages to category and go to “manage category” menu, i see “0″ as a post count in that category.

Still thanks anyway, this is a great plugin indeed.

Reply

Amit March 6, 2010 at 4:55 pm

@dandy, The default post type in wp_query is ‘post’. So you will have to change it. Try the code below. I haven’t tested the code but it should work.
[sourcecode language="php"]
<?php
$showposts = 4; // to retrive 4 posts only, -1 to shows all posts
$do_not_show_stickies = 1; // 0 to show stickies
$post_type=’any’; //’post_type’ => ‘page’ – returns Pages; defaults to value of post; can be any, attachment, page, post, or revision. any retrieves any type except revisions.

$args=array(
‘category_name’ => ‘header_navigation_pages’,
‘showposts’ => $showposts,
‘caller_get_posts’ => $do_not_show_stickies,
‘post_type’ => $post_type
);
$my_query = new WP_Query($args);
?>

<?php if( $my_query->have_posts() ) : ?>

<?php while ($my_query->have_posts()) : $my_query->the_post(); ?>

<!–Enter your stuff here–>

<?php endwhile; ?>
<?php endif; ?>
[/sourcecode]

Reply

David March 29, 2010 at 12:38 pm

Hi Amit,
Your plugin has been saving my life on a project! Thanks so much. Using your documentation I am able to get my pages to appear in category archives. But I’m still having trouble getting them to activate a category nav I’m working with below. Do I need to insert some code to look for categories in pages first? Currently the category nav is only showing the categories which have posts associated with them… when I really also want pages. My code is below. My site is here: sod2010.info. Thanks for any help.

<a href="”>

category_parent == ’0′ ) { ?>
<a href="cat_ID); ?>”>cat_name; ?>
category_description; ?>
cat_ID) ) { ?>

cat_ID ); ?>

Reply

David March 29, 2010 at 12:42 pm

Oops my code did not past as I had wanted it to. Not totally sure how to do that. Let me try again.

<a href="”>

category_parent == ’0′ ) { ?>
<a href="cat_ID); ?>”>cat_name; ?>
category_description; ?>
cat_ID) ) { ?>

cat_ID ); ?>

Reply

Amit March 29, 2010 at 12:48 pm

Glad to know that it helped. I didn’t get your problem clearly. If you want to list the categories which have only pages not posts you can use following code.

wp_list_categories(‘hide_empty=0′);

Reply

David March 29, 2010 at 9:06 pm

It took me a while but I got it! Thanks.

David

Reply

Amit Verma March 29, 2010 at 9:10 pm

It will be great if you can share the solution here. It will help others.

Reply

David March 30, 2010 at 12:00 am

So here is howI did it. I was working with a nav system that had the following 2 lines of code to get and display categories. Only the cats that had associated posts were showing up but I wanted all cats to show up because I was associating cats to pages.

Original code here:
[sourcecode language="php"]
<?php foreach ( (get_categories(‘exclude=’.get_option(‘woo_cat_ex’) ) ) as $category ) { if ( $category->category_parent == ’0′ ) { ?>
<?php wp_list_categories(‘title_li&child_of=’ . $category->cat_ID ); ?>
[/sourcecode]

New code to show all cats here (just added hide_empty=0 to each line)
[sourcecode language="php"]
<?php foreach ( (get_categories(‘hide_empty=0&exclude=’.get_option(‘woo_cat_ex’) ) ) as $category ) { if ( $category->category_parent == ’0′ ) { ?>
<?php wp_list_categories(‘hide_empty=0&title_li&child_of=’ . $category->cat_ID ); ?>
[/sourcecode]

Thanks again Amit!

Reply

Luc April 2, 2010 at 12:41 am

Hi there,

I’ve been working with this plugin for a while now and I almost have it doing what I need but I’m not quite sure what I’m doing wrong here.

What I have is a top nav bar that are all “Pages”, my website is going to have many categories and to make things easy for the user what I wanted to do is associate certain categories to those pages (which works with the new categories menu added to the “Edit Pages” page) so when I click one of the main nav item (a page), it displays the blog posts that are associated to the same categories that the page is associated with.

Basically, what I want to see is…clicking on a page, blog posts associated with the perticular categories that the page is also associated with will show up.

Right now it seems only the Uncategorised posts show up, if I set a page to have any other category I get a Not Found.

I used your code for the page template you posted above.

I hope I was clear with my question…

Thanks!! :D

Reply

Amit April 5, 2010 at 12:29 pm

@Luc, please make sure that the categories are correctly assigned to the pages.

By default all the pages belong to Uncategorise category so it shows the posts which belong to Uncategorise until you change to category of the post.

If it still doesn’t help, would you share the code?

Reply

timbu December 3, 2010 at 12:03 am

thanks, saved me a couple hours of coding!

Reply

Angela January 9, 2011 at 1:38 pm

Hello :-)

I am a TOTAL newbie at all of this, just to let you know. I wanted to ask if you could tell me step by step what I needed to do – I have installed and activated your plug-in and wanted to know where to go from here.
My site is about womanhood, and I am wanting categories like (FOR EXAMPLE): Frugality, crochet and cooking. I wanted to have pages with the same name that when you click and open them, displays all my posts that are in that category.
So I have installed the plug-in (I have Wordpress version 3.0.3.? It says I can insall version 3.0.4) and have no idea what to do now at all. It seems everyone around here knows what they are doing except me, I have pretty much zero experience with ‘coding’.

Do I create the pages with the titles of the categories I want to be displayed on them?
Is there a code I have to cut and paste somewhere?
Or when I assign the post a category, will it automatically create a page?

These probably seem like really dumb questions, I am really sorry about this. I just understood this plugin the easiest (?) out of others on the list that I could install… If you could lead me step-by-step on what I need to do in language that a newbie like could understand, I would be so very grateful. Sorry for any inconvenience, and hopefully someone someday could benefit from your answer :-D

Warmest regards,
Angela

Reply

Amit Verma January 9, 2011 at 11:40 pm

Your email is bouncing back. Could you tell me your email id at amit@amit.me

Reply

Angela January 10, 2011 at 10:52 am

Sorry had trouble configuring my email thingy. The correct address is with this comment now, lol. If my email went through, then attached to it was a copy of my page.php that retreived thru the editor function, that I copied and pasted into a notebook text file.

If the email didn’t go through to you, then let me know and I’ll email you with my personal email address instead of my website email (while I straighten out all of the kinks lol).

Thanks so much,
Angela

Reply

gorglucks January 17, 2011 at 11:07 pm

Thank you a lot, it’s exactly what I looking for !

Reply

Vladimir February 9, 2011 at 1:33 pm

Hello) You made a really good plugin! But is there a way to display hole posts not through the page template? I ask it, because I am using Platform Pro theme, where you can’t simply edit page template file but need to edit the core of the theme. May be there is another solution? To edit yor plugin? Or to paste some code into the page vie PHP-widget? Thank You in advance!

Reply

Amit February 9, 2011 at 1:46 pm

I had tried inserting whole post through plugin but that wasn’t very efficient. You can insert full post using function.php as well.

Reply

Vladimir February 9, 2011 at 1:52 pm

Sorry, that I am asking simple questions) I am not very comfortable with code yet. What code do I need to put in functions.php to get it work?

Reply

Vladimir February 9, 2011 at 2:03 pm

Sent You a mail. Mark please your changes – for me to learn how to do it myself) Thank you!

Reply

Natalie Lambert February 14, 2011 at 4:38 am

Amit,

I have read all of the comments, your read me file and more and I still can’t get the posts to appear on the pages. I am missing a final step, I am almost there. I installed and associated every page with a category. But they don’t show up.

I am certainly willing to pay you for your time, can you help me determine what final steps I need to do? How can I send you the code or have you see what the issue is? Have you login as me?

Reply

Amit Verma February 14, 2011 at 9:27 am

You can send me the code at amit[at]amit[dot].com

Reply

Vladimir February 14, 2011 at 3:27 pm

I have sent you the code) I know that You are very busy, but could You send me it back please?

Reply

Amit Verma February 14, 2011 at 3:39 pm

I am sorry for that. Your mail was filtered as spam so missed it. I will check it and send you back ASAP.

Reply

Rohit February 14, 2011 at 4:21 pm

Hey Amit i,m using WP3.4
i m really New for these things….
I just Wanted to Auto Sort My post To Their Pages. But I can Assign My post to categories not to Pages…
So i think I m On the Right Place….
i m stucked @ “Template Changes” …… will u plz tell me Which file I’ve to Edit ?
i’ve downloaded That Plugin & Selected all cat.. For Pages But Still My Posts Are Not Getting Auto Sorted.
Plzz Mate I need ur help Badly!

Reply

Amit Verma February 14, 2011 at 8:33 pm

Yes, you are at the right place. I am not sure whether I have understood your requirements completely. Do you want to insert posts on pages or want to do something else?

If you want to insert posts on pages, there is an option on settings page to auto-insert posts headings on the pages. If you want to insert whole post then you will have to edit page.php.

Reply

Rohit February 14, 2011 at 9:21 pm

Ok I Got That Option In Setting….
but there Is Still one problem.
Its Only Showing Name Of the post in specific page….
How can we make it to Display Little bit more info……like how on home screen post shows some of content from post body. and later there is “read more” Option is located.
can we add these properties to other pages?

Reply

Rohit February 15, 2011 at 6:43 pm

I ve Sent u Mail at amit@amit.me which contains page.php file
i m also having an Off topic Problem
i m using WP 3.4 and
will u please tell me how to add thumbnails to post?

Reply

Natalie Lambert February 14, 2011 at 6:04 pm

Hi Amit, I tried to email you at amit {at} amit {dot} com and the email came back undeliverable?

Reply

Amit Verma February 14, 2011 at 8:06 pm

Sorry I made a type. It is amit[at]amit[dot].me

Reply

Kev November 23, 2012 at 8:06 pm

Hi I installed this plugin to select categories as I want to pages to display different categories of posts

I have created 3 pages – Recent posts (this is the main page set for my blog for my recent posts and hidden the page)
I created 2 page templates – Members and Committee.

To try and make things easier I will just concentrate on the members page getting sorted first before mirroring the changes for the committee page

Members is to show category “Members” posts only which it does but is not formatted in the way my theme works as it was just a list of posts. SO I used your code above “Template changes” and pasted in my “members template page.php” which has almost worked but you can compare the difference this these links, its missing comments and has list of posts after every full post.

Members page with category members posts only – http://www.uistcsc.org/members-2/
Hidden page of all posts – http://www.uistcsc.org/recent%20posts/

My question is how can I make these 2 links look the same style and format.

Just noticed that due to the membership settup you will need to login to view files so have created a dummy login to view these pages

username: WPMU
password: WPMU
temporary login is set to member so pages can be viewed so you will not have administrator capabilities. Will expiry once issue is resolved.

Another error i noticed while I was logged out. is the above members link shows all my websites pages on the one page. But when logged in only posts are shown.

Any help would be awesome

Kev

Reply

Amit Verma November 25, 2012 at 11:02 pm

To disable a list of post after each post, please disable auto-insertion from the plugin’s options page.

For the identical formatting, could you please share your theme files on amit [at] amit [dot] .me?

Reply

{ 3 trackbacks }

Leave a Comment

Previous post:

Next post: