The WordPress admin panel changed from version to version, and 3.2 introduces an even newer look for the whole admin section. What hasn’t changed is the semantics, the data model and structure of what powers the admin area, and this is what backwards compatibility and “solid platform” is all about.
Today we’ll talk about the admin columns. Ones that live in the edit post and edit page screens inside those massive tables. The tables are generated on the fly, featuring hooks and actions for developers to take advantage of. There are several reasons to do so, since WordPress now powers books websites, real estate portals and many other setups that require more than just a post title, description and a list of tags.

Take books for example, you might want to show the ISBN number of the book, feature it’s cover, number of pages or it’s price, so that the website editors can easily spot the one they’re looking for in the list. Or real estate: property IDs, thumbnails, pricing, etc. I’m sure you’ll find your own reason to take advantage of your different content models, but in today’s post we’ll keep it simple. I’ll show you how to add the post thumbnail and the word count in two separate columns for the edit posts screen.
Understanding How Columns Work
Columns in WordPress’ edit tables are very powerful if used correctly, and you can power your own admin screens with WP_List_Table too! With WordPress list tables, you’ll get nice-looking, AJAX-powered, customizable tables, with pagination and screen options free of charge. But that’s an advanced topic which we’ll perhaps talk about in a different post. Today we’ll be working with the Edit Posts screen but before we start take a good look at it.

Take good look at the columns, use your browser DOM inspector to see how elements are structured, how columns are structured. Look at the different views of the table and finally note that there’s a Screen Options panel, where you can customize how many posts per page should be shown, which columns should be shown, and which ones remain hidden. The two columns that we’re going to add today will appear in that panel very soon.

Writing the Code
We’ll be working with your functions.php file in your theme folder this time, but keep in mind that the snippets will run well in plugins as well. I do think that any visual aspects, including the custom post types and custom columns should belong to a theme, rather than a plugin, since their usage in the theme is quite crucial, although depends on the situation.
We’ll start off with a hook to the after_setup_theme action and since we’re going to display a thumbnail image, we might as well display a nicely sized one, so let’s add a new image size called “edit-screen-thumbnail” which is cropped to 100 by 100 pixels, we’ll use that later.
add_action( 'after_setup_theme', 'my_theme_setup' );
function my_theme_setup() {
add_image_size( 'edit-screen-thumbnail', 100, 100, true );
}
The List Table Actions and Filters
This is important. In order to get the most out of list tables, you should understand how it’s actions and filters work. I suppose you’re familiar with actions and filters overall and the ones that we’re going to use today are manage_edit-post_columns which is a filter, and manage_posts_custom_column which is an action.
The manage_edit-post_columns filter is run on the existing columns in the edit posts list table, meaning it will get the checkbox, title, description and so on in an associative array, where the key is sort of a column ID used by WordPress to identify the column contents afterwards, and the value is the column title which is displayed.
The manage_posts_custom_column is an action which runs when an unknown (or custom) column content is about to be printed. This action doesn’t run for the standard columns, but whenever WordPress encounters one that it is not aware of, it will attempt to use this action to output the contents. It’s passed in the column ID which I mentioned earlier as an argument.
So now that you’re familiar with the filter and action used, let’s start by adding a couple of new columns to the table, and then create the actual content for the entries to display in those columns.
Creating the New Columns
It’s best if you hooked to admin_init for the rest of the actions since these things get only displayed in the admin side of your website. This will help take some load off your website, but I’ll skip this part for brevity and jump directly to creating (or how I like to call it — declaring) the new columns.
add_filter( 'manage_edit-post_columns', 'my_columns_filter', 10, 1 );
function my_columns_filter( $columns ) {
$column_thumbnail = array( 'thumbnail' => 'Thumbnail' );
$column_wordcount = array( 'wordcount' => 'Word count' );
$columns = array_slice( $columns, 0, 1, true ) + $column_thumbnail + array_slice( $columns, 1, NULL, true );
$columns = array_slice( $columns, 0, 3, true ) + $column_wordcount + array_slice( $columns, 3, NULL, true );
return $columns;
}
As you can see, I’m altering the incoming $columns associative array and I’m using the array_slice PHP function to “inject” two of my columns. The thumbnail column will go right after the checkbox column, while the word count column will go right after the title column. I then return the new $columns array and here’s the result.

As you can see the contents for the columns are empty, but you can already toggle their visibility through the Screen Options panel. If you get confused with ordering the columns, use print_r to inspect the $columns array and see how array_slice alters it for you.
What’s left now is to print out the contents for each entry, and that’s what we’ll do next.
Displaying the Custom Columns Content
I mentioned earlier that the display is done through an action. The passed in argument is the column ID which we’ve set to “thumbnail” and “wordcount” in the previous step. So we’ll check for those IDs and print out the contents using simple functions and the content from the global $post variable.
add_action( 'manage_posts_custom_column', 'my_column_action', 10, 1 );
function my_column_action( $column ) {
global $post;
switch ( $column ) {
case 'thumbnail':
echo get_the_post_thumbnail( $post->ID, 'edit-screen-thumbnail' );
break;
case 'wordcount':
echo str_word_count( $post->post_content );
break;
}
}
After you’ve done that your new edit posts screen should look similar to the following:

Note that if your posts had thumbnails before this code, they won’t be resized to 100×100 pixels, instead, WordPress will use the original images (which might be quite big) and size them proportionally. Use a plugin called Regenerate Thumbnails to resize and crop the existing image attachments.
Wrapping Up
Of course displaying a post thumbnail and the word count is not the best thing you can do with custom columns, but as stated in the beginning of this post, you can use this technique to really take your setup to the next level. Themes and plugins can benefit from custom columns. Think podcasts, videos, items for sale and audio length, video size, item price or number of purchases. All these can easily be squeezed into the edit screen with only a few lines of code.
Custom columns work especially great with custom post types where your authors and editors will have all the required info at their fingertips. And the best part of it is that they can customize the columns themselves — ones they want to see and ones they don’t, with a few clicks in the Screen Options panel.
That’s about it, folks! Hope you’ve learned something new today and hope you take advantage of these techniques in your next WordPress project. Feel free to share your thoughts or any questions you may have via the comments section below, and don’t forget to subscribe to our RSS feed and keep up with the latest around WordPress.



Great post, Konstantin! Thanks for this, it’s exactly what I needed at this moment.
The only problem I’m having is that the new columns are showing up only in the regular post table, not in my custom-post-type table. Is there something I’ve missed?
Cheers,
Darrell
Actually, a teensy bit of research and I figured this out. I just needed to change
manage_edit-post_columnstomanage_edit-${custom-post-type}_columnsand it worked beautifully.Thanks again for the great post!
Darrell
Hi Darrell, you got it all right. You just use a different filter but use the same callback function, that’s totally legit. Plus you can use several filters on one callback, which is why it’s a good idea to have a separate callback for each column filter that declares a new column. Might sound redundant but here’s an example, you need the thumbnail and the word count on posts but you need the word count on pages without the thumbnail. Hope that makes sense :)
Cheers and thank you for your comment!
Hi Konstantin!
Thanks for this tutorial.
Just 1 question. How can i ordner my table with custom posts by “Word Count” for example?
You have any idea? I miss the link like Title or Date.
Thx Tino
Hey Tino, you’re welcome! Your question is fair enough, I’d ask myself the same after reading/writing our follow-up post about Tweets & Retweets Count in WordPress. Ordering in WordPress is done through WP_Query and query variables. There are ways to sort by meta values so you’ll have to cache your wordcount into a meta key for each post.
In fact it would make a great tutorial, perhaps a part II. Why don’t you submit your discussion to our Suggestions Board over at Facebook? We look there from time to time and might as well publish a follow-up tutorial or a whole series!
Thanks for your comment and have a great day!
Hi Tino,
Sorting columns uses the WP_Query object. So natively you can only change the ‘Orderby Parameters’ that WP_Query uses for sorting the post(types). There is a work around which let you order the post(types) by any value you want.
You have to use different filters. I have used this technique in my plugin if you are curious on how I did this you can check the code. Plugin is called ‘Codepress Admin Columns‘ which I released for free. If you are just looking for a solution you can also just install this plugin and it will give you the option to place a wordcount column in any type you want, and it also support sorting.
If you have any question or want some example code, feel free to send me an email at info[at]codepress[dot]nl
Thanks for answer.
One part II is definitely a good idea. I’ve subscribed to your feed ;)
You also have a nice day!
Thanks for this bit of code, but I have an issue and assume it is due to WP3.3. Here is my code:
add_filter( 'manage_edit-books_columns', 'books_edit_columns' );
function books_edit_columns($columns) {
$column_thumbnail = array( 'thumb' => 'Thumbnail' );
$column_wordcount = array( 'wordcount' => 'Word Count' );
$columns = array_slice( $columns, 0, 1, true ) + $column_thumbnail + array_slice( $columns, 1, NULL, true );
$columns = array_slice( $columns, 0, 3, true ) + $column_wordcount + array_slice( $columns, 3, NULL, true );
return $columns;
}
add_action( 'manage_posts_custom_column', 'my_column_action', 10, 1 );
function my_column_action( $column ) {
global $post;
switch ( $column ) {
case 'thumb':
echo get_the_post_thumbnail( $post->ID, 'thumbnail' );
break;
case 'wordcount':
echo str_word_count( $post->post_content );
break;
}
}
And here is a screen shot showing the issue of ‘none’ showing up in each column along with the appropriate data.
If I add any more columns of meta data to posts edit page, I can get the appropriate data show up…but so does ‘none’ with them all. I am not sure how else to explain.
Thoughts on a fix?
Pingback: Hacking Term List Table « kucrut
Thanks for this great article. There is no useful documentation available, so i found this perfect illustrated tutorial.
One interesting thing to add, would be how to customize the columns width.
Greetings Maik
Probably a bit dated, but I was looking for the same answer.
In short, you can easily add your own styling:
add_action( 'admin_head-edit.php', 'my_column_thumbnail_width' );function my_column_thumbnail_width() {
?>
.widefat .column-thumbnail { width: 10em; }
<?php
}
Edit:
To have the same layout as used at
media.php, I would suggest to use this instead:.widefat .column-thumbnail { width: 120px; // thumbnail size + 20px text-align: center; }Thanks for this tutorial.
How could you add the sorting function to the new added columns ??
You might wish to take a look here: http://scribu.net/wordpress/custom-sortable-columns.html, which handles sortable columns
Hope it’s OK to add this, but after some struggling with this over at WPSE, here’s how to add a featured image, having this one default to the first image attached to a post if none available, and having that one default to a locally hosted image.
add_action( 'after_setup_theme', 'cor_after_setup_theme' );function cor_after_setup_theme() {
add_image_size( 'edit-screen-thumbnail', 48, 48, true );
}
add_filter( 'manage_edit-product_columns', 'cor_add_product_column', 10, 1 );
function cor_add_product_column( $column ) {
$column_thumbnail = array(
'thumbnail' => ''
);
$column = array_slice( $column, 0, 1, true ) + $column_thumbnail + array_slice( $column, 1, NULL, true );
return $column;
}
add_action( 'manage_posts_custom_column', 'cor_manage_product_column', 10, 1 );
function cor_manage_product_column( $column ) {
global $post;
$args = array(
'numberposts' => 1,
'post_mime_type' => 'image',
'post_parent' => $post->ID,
'post_type' => 'attachment',
);
$attachments = get_children( $args );
if ( has_post_thumbnail() ) {
echo get_the_post_thumbnail( $post->ID, 'edit-screen-thumbnail' );
} elseif ( $attachments ) {
foreach ( $attachments as $attachment ) {
$image_attributes = wp_get_attachment_image_src( $attachment->ID, 'edit-screen-thumbnail' );
echo '';
}
} else {
echo '';
}
}
That didn’t go well… Here’s the right one: https://gist.github.com/1989734