Customize The Admin Post List in WordPress Website

What do you see when you click on Admin post list in your WordPress website? A list of all the posts created by you is displayed with their titles and dates. But, that’s about it which is displayed! You won’t be able to see any other details related to your post. So, if you want to display some elements other than the title and date, you will need to customize the list.

The admin post list is created using WP_List_Table class. Let’s try and understand how a particular post list is customized.

Creating Custom Post
Go to functions.php file, and paste the following definitions to this file

add_action( ‘init’, ‘bs_post_types’ );
function bs_post_types() {

$labels = array(
‘name’                => __( ‘Events’, THEMENAME ),
‘singular_name’       => __( ‘Event’, THEMENAME ),
‘add_new’             => __( ‘Add New’, THEMENAME ),
‘add_new_item’        => __( ‘Add New Event’, THEMENAME ),
‘edit_item’           => __( ‘Edit Event’, THEMENAME ),
‘new_item’            => __( ‘New Event’, THEMENAME ),
‘all_items’           => __( ‘All Event’, THEMENAME ),
‘view_item’           => __( ‘View Event’, THEMENAME ),
‘search_items’        => __( ‘Search Events’, THEMENAME ),
‘not_found’           => __( ‘No events found’, THEMENAME ),
‘not_found_in_trash’  => __( ‘No events found in Trash’, THEMENAME ),
‘menu_name’           => __( ‘Events’, THEMENAME ),

$supports = array( ‘title’, ‘editor’ );

$slug = get_theme_mod( ‘event_permalink’ );
$slug = ( empty( $slug ) ) ? ‘event’ : $slug;

$args = array(
‘labels’              => $labels,
‘public’              => true,
‘publicly_queryable’  => true,
‘show_ui’             => true,
‘show_in_menu’        => true,
‘query_var’           => true,
‘rewrite’             => array( ‘slug’ => $slug ),
‘capability_type’     => ‘post’,
‘has_archive’         => true,
‘hierarchical’        => false,
‘menu_position’       => null,
‘supports’            => $supports,
register_post_type( ‘event’, $args );

You will simply need these definitions to get started with creating a custom post type. You will need to pull out the permalink from your theme settings to make sure the users can set their own permalinks. This holds true specifically for the multilingual websites. With these definitions, you are able to get the admin list, the standard one, with the title and date. There is no other information related to the post provided in this case. You will need to customize as per your need.

Customizing Table Headers
While customizing, you won’t be looking at the WP_Lists_Table class at any point. You can easily add the custom header. It’s as easy as adding a value to an array. Here’s an example. The three add-on columns include- event date, ticket status and venue.

add_filter(‘manage_event_posts_columns’, ‘bs_event_table_head’);
function bs_event_table_head( $defaults ) {
$defaults[‘event_date’]  = ‘Event Date’;
$defaults[‘ticket_status’]    = ‘Ticket Status’;
$defaults[‘venue’]   = ‘Venue’;
$defaults[‘author’] = ‘Added By’;
return $defaults;

The filter used in this code corresponds to the name of the post type created for this example. With this filter, you can easily customize the header for any post in your admin list. you will need to use manage_posts_posts_column to modify the columns within the post and add the columns you wish to view

Fill up the Columns
Once you have created the columns for the table, you will need to fill them up too! The whole process is as simple or as complex as creating the table headers.

add_action( ‘manage_event_posts_custom_column’, ‘bs_event_table_content’, 10, 2 );

function bs_event_table_content( $column_name, $post_id ) {
if ($column_name == ‘event_date’) {
$event_date = get_post_meta( $post_id, ‘_bs_meta_event_date’, true );
echo  date( _x( ‘F d, Y’, ‘Event date format’, ‘textdomain’ ), strtotime( $event_date ) );
if ($column_name == ‘ticket_status’) {
$status = get_post_meta( $post_id, ‘_bs_meta_event_ticket_status’, true );
echo $status;

if ($column_name == ‘venue’) {
echo get_post_meta( $post_id, ‘_bs_meta_event_venue’, true );

In the above example code, it is clear that each column is called separately. You will need to see which column is being displayed and release the corresponding output. The data required to be released at output is stored at the postmeta table.

Event date stored in _bs_meta_event_date

Ticket status uses _bs_meta_event_ticket_status

Venue stored in _bs_meta_event_venue

All you need is the get_post_meta() function to retrieve the post meta values mentioned above. You can easily echo the values with this function. You can easily decide the snippets that you want to show in the output. With this function, your table would look more organized.

Sorting the Columns
Sorting or rather placing the columns in order is a two-step process. You will need to add the columns that you wish to sort to the array- that would be your first step. Second, you will need to create a filter for individual columns which will automatically modify the query and sort the column as per the user’s requests.

add_filter( ‘manage_edit-event_sortable_columns’, ‘bs_event_table_sorting’ );
function bs_event_table_sorting( $columns ) {
$columns[‘event_date’] = ‘event_date’;
$columns[‘ticket_status’] = ‘ticket_status’;
$columns[‘venue’] = ‘venue’;
return $columns;

add_filter( ‘request’, ‘bs_event_date_column_orderby’ );
function bs_event_date_column_orderby( $vars ) {
if ( isset( $vars[‘orderby’] ) && ‘event_date’ == $vars[‘orderby’] ) {
$vars = array_merge( $vars, array(
‘meta_key’ => ‘_bs_meta_event_date’,
‘orderby’ => ‘meta_value’
) );

return $vars;

add_filter( ‘request’, ‘bs_ticket_status_column_orderby’ );
function bs_ticket_status_column_orderby( $vars ) {
if ( isset( $vars[‘orderby’] ) && ‘ticket_status’ == $vars[‘orderby’] ) {
$vars = array_merge( $vars, array(
‘meta_key’ => ‘_bs_meta_event_ticket_status’,
‘orderby’ => ‘meta_value’
) );

return $vars;

add_filter( ‘request’, ‘bs_venue_column_orderby’ );
function bs_venue_column_orderby( $vars ) {
if ( isset( $vars[‘orderby’] ) && ‘venue’ == $vars[‘orderby’] ) {
$vars = array_merge( $vars, array(
‘meta_key’ => ‘_bs_meta_event_venue’,
‘orderby’ => ‘meta_value’
) );

return $vars;

Let’s understand what’s happening here. When the posts are requested to be listed, an array of arguments is released which decides what elements/column headers will be displayed in the list. You will also need to mention the order in which the posts are to be pulled so that the admin list is ready with the order. You will need to tell WordPress which meta_key to filter and how to use these values. You will need to use the arguments responsible for taxonomy filtering in WP_Query.

Filtering the Data
You will need to begin with mentioning the controls that WordPress can use for data filtering. Once, you have mentioned the controls you will need to ensure that the controls are responsible for the changes.

add_action( ‘restrict_manage_posts’, ‘bs_event_table_filtering’ );
function bs_event_table_filtering() {
global $wpdb;
if ( $screen->post_type == ‘event’ ) {

$dates = $wpdb->get_results( “SELECT EXTRACT(YEAR FROM meta_value) as year,  EXTRACT( MONTH FROM meta_value ) as month FROM $wpdb->postmeta WHERE meta_key = ‘_bs_meta_event_date’ AND post_id IN ( SELECT ID FROM $wpdb->posts WHERE post_type = ‘event’ AND post_status != ‘trash’ ) GROUP BY year, month ” ) ;

echo ”;
echo ” . __( ‘Show all event dates’, ‘textdomain’ ) . ”;
foreach( $dates as $date ) {
$month = ( strlen( $date->month ) == 1 ) ? 0 . $date->month : $date->month;
$value = $date->year . ‘-‘ . $month . ‘-‘ . ’01 00:00:00’;
$name = date( ‘F Y’, strtotime( $value ) );

$selected = ( !empty( $_GET[‘event_date’] ) AND $_GET[‘event_date’] == $value ) ? ‘selected=”select”‘ : ”;
echo ” . $name . ”;
echo ”;

$ticket_statuses = get_ticket_statuses();
echo ”;
echo ” . __( ‘Show all ticket statuses’, ‘textdomain’ ) . ”;
foreach( $ticket_statuses as $value => $name ) {
$selected = ( !empty( $_GET[‘ticket_status’] ) AND $_GET[‘ticket_status’] == $value ) ? ‘selected=”selected”‘ : ”;
echo ” . $name . ”;
echo ”;


You will need to make sure that the filters are added to the right page. If you are on the ticket status page, you will need to add the specific filters to that page-namely selector for event dates and selector for ticket will be able to retrieve the ticket status using the function get_ticket_statuses(). Remember all this is user defined. Once you have mentioned the filter, you will see that the table has taken the form it will display at the output. Now, you need to ensure that the filters you have set actually work. Simply add arguments to the query and you will be able to fix the issue

add_filter( ‘parse_query’,’bs_event_table_filter’ );
function bs_event_table_filter( $query ) {
if( is_admin() AND $query->query[‘post_type’] == ‘event’ ) {
$qv = &$query->query_vars;
$qv[‘meta_query’] = array();

if( !empty( $_GET[‘event_date’] ) ) {
$start_time = strtotime( $_GET[‘event_date’] );
$end_time = mktime( 0, 0, 0, date( ‘n’, $start_time ) + 1, date( ‘j’, $start_time ), date( ‘Y’, $start_time ) );
$end_date = date( ‘Y-m-d H:i:s’, $end_time );
$qv[‘meta_query’][] = array(
‘field’ => ‘_bs_meta_event_date’,
‘value’ => array( $_GET[‘event_date’], $end_date ),
‘compare’ => ‘BETWEEN’,
‘type’ => ‘DATETIME’


if( !empty( $_GET[‘ticket_status’] ) ) {
$qv[‘meta_query’][] = array(
‘field’ => ‘_bs_meta_event_ticket_status’,
‘value’ => $_GET[‘ticket_status’],
‘compare’ => ‘=’,
‘type’ => ‘CHAR’

if( !empty( $_GET[‘orderby’] ) AND $_GET[‘orderby’] == ‘event_date’ ) {
$qv[‘orderby’] = ‘meta_value’;
$qv[‘meta_key’] = ‘_bs_meta_event_date’;
$qv[‘order’] = strtoupper( $_GET[‘order’] );

You will need to add the relevant rules to the query defined for each filter. Add meta_query when filtering the events. With this sorted, you have a custom admin list in your hand.


Note: It’s always a good habit to take a backup before getting on with customizations.


Deepa is a passionate blogger associated with Semaphore Software., a leading Offshore WordPress development company. She loves sharing information regarding WordPress tips & tricks. If you are looking for Hire WordPress Programmers then just get in touch with her.

About deeparanganathan