You may already be familiar with Advanced Custom Fields, a popular plugin we develop that makes adding custom fields to your WordPress site as easy as clicking a few buttons.
But did you know that WordPress has its own version of custom fields? In this article, I will take a closer look at the WordPress implementation of custom fields, then compare them to the custom fields possible with ACF.
WordPress custom fields are additional inputs you can add to posts or pages that save the values to the metadata for that post or page.
WordPress stores custom fields as key -> value
pairs in the wp_postmeta table. That data can then be used in your theme or plugins to render custom content in your theme or perform additional logic based on the field values.
Fortunately, WordPress custom fields are quite simple to use, even with minimal knowledge of PHP and the WordPress database. In this section, I’ll go over how to add custom fields and update existing fields, as well as how to pull them into WordPress themes or plugins.
If you haven’t seen the custom field interface before, it’s likely because it’s hidden away from the edit screens by default! If you’re using the classic editor, you can enable the custom fields metabox by editing a post and clicking Screen Options:
If you’re using the block editor, you’ll have to click the three dots at the top of a post or page to open the editor settings and click Preferences. Next, head to the “Panels” section and enable the Custom Fields toggle:
Once enabled, the editor should reload and you’ll now see a custom fields section at the bottom:
If you’ve tried enabling custom fields but aren’t seeing the option for it in the classic editor’s “Screen Options” or the block editor preferences, there are a couple of reasons why that might be happening. The first is if you’re using a custom post type that hasn’t declared support for custom fields. To add custom fields to a WordPress custom post type, you’ll need to either add custom-fields
to the supports array in register_post_type(), or pass custom-fields
to the add_post_type_support(). Naturally, a custom post type registered in ACF already includes support for ACF custom fields.
Another reason the custom fields UI might not show up is if you’re using ACF. ACF hides these settings to speed up load times and prevent confusion between the WordPress core custom fields functionality and the ACF custom fields functionality. If you’d like to display the WordPress core custom fields in addition to ACF fields, you can add the following snippet into your theme’s functions.php
or in a custom plugin:
add_filter('acf/settings/remove_wp_meta_box', '__return_false');
The WordPress custom fields UI is very simple. There’s just a “Name” field (which is also used as the field “key”) and a “Value” field. To get started, enter a name for the custom field. Don’t worry about having to do this every time—your previous field names are saved and will be available via a dropdown the next time you add a custom field.
In this quick tutorial, we’re going to use custom fields to create a basic “Related Posts” section for a post. To do that, you’ll need to add a new custom field with “Related Posts” as the name, and enter a post ID for another post as the value.
Once you save the page and reload, you can then select from any existing custom fields you have saved. You can even use the same field multiple times, which is helpful if there are multiple related posts you want to attach to a post.
Once you’ve added a few related posts, it’s time to pull that functionality into a theme!
WordPress core has several helpful functions that can be used to retrieve and render custom field values in a theme or plugin. In the example below, we use get_post_meta() to retrieve an array of the related posts and display them at the bottom of a post template.
function hellfish_related_posts() {
$related_post_ids = get_post_meta( get_the_ID(), 'Related Posts' );
// Bail out early if there are no related posts.
if ( ! is_array( $related_post_ids ) || empty( $related_post_ids ) ) {
return;
}
// Loop over the posts and render the HTML for the related posts section.
$related_posts = array();
foreach ( $related_post_ids as $post_id ) {
$post_id = (int) $post_id;
$permalink = get_the_permalink( $post_id );
$post_title = get_the_title( $post_id );
$thumbnail = get_the_post_thumbnail( $post_id );
if ( ! $permalink || !$post_title ) {
continue;
}
$related_posts[] = sprintf(
'<div class="hfm-related-post">
<a href="%s">%s%s</a>
</div>',
$permalink,
$thumbnail,
$post_title
);
}
if ( empty( $related_posts ) ) {
return;
}
printf(
'<div class="hfm-related-posts>
<h4>Related Posts</h4>
%s
</div>',
implode( '', $related_posts )
);
}
The get_post_meta()
function will always return an array of metadata if found, or false on failure. So the above function checks if the “Related Posts” custom field has an array of data, and then loops through them to generate the necessary HTML for our related posts functionality. Here’s what that looks like on the frontend after a little CSS magic:
If you need to query a post or page by a field value, you can do so with the WordPress get_posts() function or by using WP_Query
directly. With our previous example of related posts in mind, we could use get_posts()
like this to get a list of the posts that have one or more of a specific related post:
$args = array(
'meta_key' => 'Related Posts',
'meta_value' => array( 17, 19 ),
'meta_type' => 'NUMERIC'
);
$posts = get_posts( $args );
By passing in an array of post IDs as the meta_value
, we can search for posts that have one or more of those IDs set as a value for our “Related Posts” custom fields. Setting the meta_type
to NUMERIC
casts any meta values found as numbers so that we know we’re making a proper comparison.
If you’re curious about other ways to use get_posts()
for custom fields, I’d recommend checking out the official documentation, as well as the documentation for the WP_Query class which is used internally by get_posts()
.
WP_Query
is a powerful class in WordPress that allows developers to retrieve and manipulate post data from the database. As we’ve just seen with get_posts()
, WP_Query
can be used to query posts by custom field values, but it offers even more flexibility and customization options. By creating a new instance of WP_Query
and passing in an array of arguments, developers can specify the post type, category, tag, author, and other criteria to retrieve the desired data. For example, to achieve the same result as the previous get_posts()
example, you could use WP_Query
like this:
$query = new WP_Query( array( 'meta_key' => 'Related Posts', 'meta_value' => array( 17, 19 ), 'meta_type' => 'NUMERIC' ) );
This would retrieve a list of posts that have one or more of the specified related post IDs set as a value for the “Related Posts” custom field.
The biggest pro and the biggest con for the WordPress implementation of custom fields is actually the same thing – simplicity.
I consider it a pro in this case because it’s incredibly easy to add custom fields to a post or page, and the functions for retrieving those fields are relatively basic. Someone with even a minimal knowledge of PHP can get up and running with WordPress custom fields with only a few trips to the documentation.
On the other hand, just having a simple textarea
to use for a field value is quite limiting and potentially error prone. For example, if you need to use the custom fields to store and retrieve things that are true or false, or selected from a predefined list of options, a textarea
may not be the best option. Or you just may need something more advanced, with robust APIs and multiple different types of custom fields.
The Advanced Custom Fields plugin takes the spirit of the custom fields functionality in WordPress core and extends it with over 30 different field types and options for those fields.
It also allows you to organize multiple fields into a field group, a collection of fields displayed on a location of your choosing.
Within the fields you assign to each field type, there are several settings to further customize each field so you can make sure it works exactly as you need it to. For example, you can use an Image field that restricts the available image types and has a min/max file size requirement:
You can also set each field to show up conditionally based on the values of other fields – handy for more complex forms of content:
To make something like the “Related Posts” functionality with less effort, you could use ACF’s Relationship field. This lets you select from existing posts, pages, or custom post types. No more having to manually find and remember the post IDs! You can set up bidirectional relationships, or tell the Relationship field to only select from certain post types or from posts that have a certain taxonomy (i.e., category or tag).
Once you’ve assigned a field group to a post or page, ACF will take care of adding the metaboxes, saving the data, and formatting the values based on the field type selected. Here’s what the new “Related Posts” panel in the post editor looks like after switching to ACF:
Rendering the related posts in PHP is quite similar to how you would do it with WordPress custom fields, so I won’t bore you with the details. Generally, instead of using get_post_meta()
to get the field values, you’d use ACF’s function get_field().
The options page feature in ACF PRO allows you to add extra admin pages to edit ACF fields. Unlike WordPress custom fields, this allows you to create global fields that are not attached to a particular post or page. Instead, the data can be displayed on any page throughout your WordPress site. This makes it ideal for a number of use cases, including header and footer data.
Open your functions.php
file and add the line of code below to create an options page:
if( function_exists('acf_add_options_page') ) {
acf_add_options_page();
}
This will add a default options page to the sidebar in your admin area. You can add parameters to customize your new options page. For example, adding the code below to your functions.php
will create a customized options page with multiple child pages:
if( function_exists('acf_add_options_page') ) {
acf_add_options_page(array(
'page_title' => 'Theme General Settings',
'menu_title' => 'Theme Settings',
'menu_slug' => 'theme-general-settings',
'capability' => 'edit_posts',
'redirect' => false
));
acf_add_options_sub_page(array(
'page_title' => 'Theme Header Settings',
'menu_title' => 'Header',
'parent_slug' => 'theme-general-settings',
));
acf_add_options_sub_page(array(
'page_title' => 'Theme Footer Settings',
'menu_title' => 'Footer',
'parent_slug' => 'theme-general-settings',
));
}
Aside from the Relationship field, ACF has a variety of field types that range from a basic Checkbox field all the way to more advanced field types like the Repeater field and the Google Map field. These fields can also be inserted into custom blocks or displayed in the WordPress REST API, so the possibilities with ACF are almost endless.
We’ll look at the Repeater field as an example. This is an extremely useful field, as it provides a low-effort solution for repeating content types such as slides, team member bios, or any other data that you want to render in your theme multiple times.
This is because the Repeater field acts as a parent to a set of sub fields which can be replicated as many times as necessary. Any type of field can be used within a Repeater field:
When editing a post, you’ll then be able to add multiple rows containing those fields. This is similar to how you can add multiple rows of the same WordPress custom field, except you can do it with multiple fields at once!
WordPress custom fields are a useful tool for adding some custom (if relatively basic) functionality to your website. Even being an avid ACF user, I’d still at least consider using the core custom fields if I only needed a basic text field in a few pages. But with anything more than that, I’d have no trouble letting ACF handle the job.
Have you ever used the WordPress custom fields on your websites? If so, would you use them again? Let us know in the comments.
Speed up your workflow and unlock features to better develop websites using ACF Blocks and Options Pages, with the Flexible Content, Repeater, Clone, Gallery Fields & More.
For plugin support, please contact our support team directly, as comments aren't actively monitored.