WordPress · Admin how-to

Add custom columns to any WordPress post list

Surface the data that actually matters right in your admin posts list. No plugin bloat, just two WordPress hooks and a few lines of code that work for any post type.

CKTechCheck on YouTube

Prefer to watch a walkthrough?

This one is a code tutorial, so there is no video to embed here. I cover WordPress tweaks, tools, and gear on the channel, though. Subscribe to catch new tutorials and reviews the moment they go live.

Visit the channel

Editor's note (July 2026): The two hooks this guide relies on, manage_{post_type}_posts_columns and manage_{post_type}_posts_custom_column, are still current in WordPress 6.x, so the code below works exactly as written. One naming change is worth knowing: in October 2024 WordPress.org forked Advanced Custom Fields into a plugin called Secure Custom Fields (SCF). The free plugin in the WordPress.org directory now carries the SCF name, while ACF itself is still developed by WP Engine at advancedcustomfields.com. Either one works here, because the code reads each saved value with get_post_meta() instead of going through the plugin's own API.

The short version

WordPress builds every admin list table from two hooks. A filter, manage_{post_type}_posts_columns, registers your column header, and an action, manage_{post_type}_posts_custom_column, fills each row. Hook both, read your field with get_post_meta(), and the value shows up in the list. It works for any post type and needs no plugin beyond the one storing your fields.

Two hooks. Any post type.
Why bother

The power of custom columns in WordPress

Custom columns in the WordPress admin are more than a convenience. They are a genuine content-management upgrade. Out of the box, WordPress shows a fixed set of columns with only basic information about each post. That is rarely enough for a quick overview, especially for custom post types that hold specialized data. Adding your own columns lets you see the details that matter most to you and your team, right in the posts list of your dashboard.

The data layer

Leveraging ACF for richer admin columns

Advanced Custom Fields (ACF) lets you attach custom fields to your WordPress edit screens with almost no effort. Those fields can hold all sorts of data, and that data is often exactly what you want surfaced in an admin column. Say you run a car dealership site with a product post type. Fields like MPG and Engine Size would be handy at a glance. ACF stores those values on each product, and with a little code you can make them visible every time you open your list of products.

The free plugin in the WordPress.org directory now carries the name Secure Custom Fields, as noted above, but the steps are identical whichever build you run.

The code

Coding custom columns for any post type

The best part is that this approach applies universally to any post type. You hook into two core WordPress hooks. The first, manage_{post_type}_posts_columns, filters the columns shown in the admin list table. The second, manage_{post_type}_posts_custom_column, outputs the content for each new column you added. Here is a snippet that adds MPG and Engine Size columns to a product post type:

functions.php
// Add the MPG and Engine Size columns to the product post type
function add_acf_columns( $columns ) {
    return array_merge( $columns, array(
        'mpg'          => __( 'MPG' ),
        'engine_size'  => __( 'Engine Size' ),
    ) );
}
add_filter( 'manage_product_posts_columns', 'add_acf_columns' );

// Populate the custom columns with the ACF field data
function custom_column( $column, $post_id ) {
    switch ( $column ) {
        case 'mpg':
            echo get_post_meta( $post_id, 'mpg', true );
            break;

        case 'engine_size':
            echo get_post_meta( $post_id, 'engine_size', true );
            break;
    }
}
add_action( 'manage_product_posts_custom_column', 'custom_column', 10, 2 );

Remember to swap 'mpg' and 'engine_size' for the actual field names defined in your ACF settings.

WordPress admin product list table with custom MPG and Engine Size columns added, showing a Honda Fit, Mustang GT, and Corolla SE with their mileage and engine size values
The payoff: MPG and Engine Size now sit right in the product list, next to the built-in columns.

Escape on output. The snippet echoes each value directly. If a field could ever hold HTML, wrap the output in esc_html(), for example echo esc_html( get_post_meta( $post_id, 'mpg', true ) );. For plain numbers like these it is optional, but escaping on output is the safer habit.

Reading the value

Displaying ACF field data in a column

Once your fields are set up, showing their data is refreshingly simple. The get_post_meta() function pulls the stored value for a given post, and you echo it into the column cell. That is all the second hook is doing above: for each row, it fetches the right field for that post ID and prints it, so you never have to open a post just to check a single spec.

If you prefer ACF's own helper, get_field() works too and applies ACF's formatting. The plain get_post_meta() call returns the raw stored value, which is usually what you want in a compact admin column.

Take it further

Make the columns sortable

Displaying a value is step one. More often than not you will also want to click the column header to sort by it, say to line up your products from best to worst MPG. WordPress supports this with one more filter, manage_edit-{post_type}_sortable_columns, plus a small tweak to the main query so it knows to order by the stored value:

functions.php
// Make the MPG and Engine Size columns sortable
function acf_sortable_columns( $columns ) {
    $columns['mpg']          = 'mpg';
    $columns['engine_size']  = 'engine_size';
    return $columns;
}
add_filter( 'manage_edit-product_sortable_columns', 'acf_sortable_columns' );

// Tell the main admin query how to order by the ACF value
function acf_columns_orderby( $query ) {
    if ( ! is_admin() || ! $query->is_main_query() ) {
        return;
    }
    $orderby = $query->get( 'orderby' );
    if ( 'mpg' === $orderby || 'engine_size' === $orderby ) {
        $query->set( 'meta_key', $orderby );
        $query->set( 'orderby', 'meta_value_num' ); // use 'meta_value' for text
    }
}
add_action( 'pre_get_posts', 'acf_columns_orderby' );

Use meta_value_num when the field holds numbers, like MPG, and meta_value for plain text. After this, the MPG and Engine Size headers become clickable and reorder the whole list.

Code vs plugins

Why custom code beats a plugin here

Plugins can add a lot of capability with almost no effort, but they carry a cost. An outdated or poorly maintained plugin is a common source of security holes. Writing a few lines yourself for something this small keeps you off that treadmill: fewer third-party dependencies, a smaller attack surface, and behavior that is exactly what you asked for and nothing more. For a feature that fits in twenty lines, that trade is usually worth it.

Common questions

Frequently Asked Questions

Do I need a plugin to add custom admin columns in WordPress?

No. Two built-in WordPress hooks handle it: a filter to register the column and an action to fill it. A plugin like ACF or Secure Custom Fields is only there to store the field data you want to display, not to build the column.

What are the WordPress hooks for custom columns?

Use manage_{post_type}_posts_columns to filter which columns appear, and manage_{post_type}_posts_custom_column to output the value for each row. Swap {post_type} for your post type, for example manage_product_posts_columns.

Is ACF still safe to use after the Secure Custom Fields fork?

Yes. In October 2024 WordPress.org forked ACF into Secure Custom Fields (SCF). ACF is still actively developed by WP Engine, and SCF is the free version in the WordPress.org directory. The code in this guide works with either, since it reads values with get_post_meta() rather than a plugin-specific function.

How do I make a custom admin column sortable?

Register the column as sortable with the manage_edit-{post_type}_sortable_columns filter, then hook pre_get_posts to order the query by the field's meta value. The sortable snippet above shows the full pattern.

Where should I put this code?

In your child theme's functions.php file or a small site-specific plugin. Avoid editing a parent theme directly, since a theme update would wipe your changes.

The bottom line

Small code, big quality-of-life win

Custom columns are one of the highest-leverage tweaks you can make to the WordPress admin. They put the information you care about one glance away, for any post type, without cluttering your workflow. By pulling ACF field values into columns of your own, you turn a generic posts list into a dashboard tuned to how you actually work.

Add sortable headers on top and you have a lightweight, plugin-free tool that scales with your content. Drop the snippets into a child theme or a small plugin, swap in your own field names, and you are set.

Disclosure: This post contains affiliate links. As an Amazon Associate I earn from qualifying purchases, at no extra cost to you.