
What are custom fields in WordPress and how to use them?
Custom fields in WordPress are extra pieces of information, stored as key and value pairs, that you attach to a post, page, or custom post type. For example, a book review might have custom fields for "author", "rating", and "ISBN". You can add them through the built-in Custom Fields panel in the editor, with a plugin like Advanced Custom Fields (ACF), or in code with functions like register_post_meta() and update_post_meta(), and then display them in your theme with get_post_meta() or block bindings.
Custom fields are what turn WordPress from a blogging tool into a flexible content management system. They let you store structured data, like prices, dates, locations, and ratings, alongside your regular content. This guide explains what custom fields are, how they're stored, how to add and display them with and without plugins, how to use them in block themes, and best practices for keeping them secure and fast.
What Are Custom Fields?
Every post in WordPress has standard data: a title, content, an author, a date, and so on. Custom fields let you add anything else you need. Each custom field has:
- A key (name): The label that identifies the field, such as
book_author. - A value: The data itself, such as
Jane Austen.
WordPress calls this data post meta (or metadata). It's stored in the wp_postmeta database table, where each row links a meta_key and meta_value to a post_id.
Examples of Custom Fields
- Real estate: Price, number of bedrooms, square footage, address
- Events: Start date, end date, venue, ticket link
- Recipes: Prep time, cook time, servings, calories
- Portfolio: Client name, project URL, completion date
- Reviews: Rating, pros, cons, product link
- Blog posts: A custom subtitle, a "mood" field, or a sponsor name
Plugins also rely heavily on custom fields. SEO plugins store your SEO titles and meta descriptions as post meta, and WooCommerce stores product prices and stock levels the same way.
Custom Fields vs. Taxonomies
It's easy to confuse custom fields with categories and tags. A simple rule:
- Use taxonomies when you want to group content and create archive pages, like "all recipes that are vegetarian".
- Use custom fields for specific data about one item, like "this recipe takes 25 minutes".
Method 1: Using the Built-In Custom Fields Panel
WordPress includes a basic custom fields interface that requires no plugins. It's hidden by default in the block editor.
Enabling the Custom Fields Panel
- Open any post in the block editor.
- Click the three-dot Options menu in the top-right corner.
- Choose Preferences.
- In the General tab, scroll to Advanced and enable Custom fields.
- Click Show & Reload Page.
A Custom Fields panel now appears below the post content.
Adding a Custom Field
- Scroll down to the Custom Fields panel.
- Under Add New Custom Field, type a name in the Name field, or choose an existing one from the dropdown.
- Enter the value in the Value field.
- Click Add Custom Field.
- Update or publish the post.
The next time you add a custom field to another post, the name will appear in the dropdown, which keeps names consistent.
Keys that start with an underscore (like _edit_lock) are "protected" and hidden from this panel. Plugins use them for internal data.
The built-in panel is fine for simple, occasional use, but it's not very user-friendly for clients or for fields that need validation, like dates or images. That's where plugins come in.
Method 2: Using a Custom Fields Plugin
Custom field plugins give you a proper interface, with field types like text, number, date picker, image, select dropdown, relationship, and repeater.
Popular Custom Fields Plugins
- Advanced Custom Fields (ACF): The most widely used option. The free version covers many field types; ACF PRO adds repeaters, flexible content, options pages, and ACF Blocks.
- Meta Box: A developer-friendly framework with a free core and paid extensions.
- Pods: A free framework for custom fields, post types, and taxonomies.
- Carbon Fields: A code-first library for developers who want to define fields in PHP.
Creating Fields With ACF
Here's how to add a "Book Details" set of fields to posts using ACF:
- Install ACF: Go to Plugins > Add New Plugin, search for "Advanced Custom Fields", install, and activate it.
- Create a field group: Go to ACF > Field Groups and click Add New.
- Name the group: Enter "Book Details".
- Add fields: Click Add Field for each one. For example:
- Field Label: Book Author, Field Name:
book_author, Field Type: Text - Field Label: Rating, Field Name:
book_rating, Field Type: Number (min 1, max 5) - Field Label: Publication Date, Field Name:
book_publication_date, Field Type: Date Picker - Field Label: Buy Link, Field Name:
book_buy_link, Field Type: URL
- Field Label: Book Author, Field Name:
- Set location rules: Under Settings > Location Rules, choose where the fields appear, such as Post Type is equal to Post, or Post Category is equal to Book Reviews.
- Save the field group.
Now, when you edit a matching post, the "Book Details" fields appear in the editor, either below the content or in the sidebar depending on your settings.
Displaying ACF Fields
In the block editor, you can display ACF fields using block bindings (covered below) or ACF's own blocks if you use ACF PRO. In a classic PHP template, use ACF's functions:
<?php
$sajjad_book_author = get_field( 'book_author' );
$sajjad_book_rating = get_field( 'book_rating' );
$sajjad_buy_link = get_field( 'book_buy_link' );
if ( $sajjad_book_author ) : ?>
<div class="book-details">
<p><strong><?php esc_html_e( 'Author:', 'mytheme' ); ?></strong> <?php echo esc_html( $sajjad_book_author ); ?></p>
<?php if ( $sajjad_book_rating ) : ?>
<p><strong><?php esc_html_e( 'Rating:', 'mytheme' ); ?></strong> <?php echo esc_html( $sajjad_book_rating ); ?>/5</p>
<?php endif; ?>
<?php if ( $sajjad_buy_link ) : ?>
<p><a href="<?php echo esc_url( $sajjad_buy_link ); ?>" rel="nofollow sponsored"><?php esc_html_e( 'Buy this book', 'mytheme' ); ?></a></p>
<?php endif; ?>
</div>
<?php endif; ?>
get_field() returns the value, which you should escape when outputting, while the_field() echoes it directly. Using get_field() with explicit escaping is the safer habit.
Method 3: Working With Custom Fields in Code
For developers, WordPress provides a complete API for post meta. Add PHP snippets to a custom plugin or your child theme's functions.php.
The Core Post Meta Functions
get_post_meta( $post_id, $key, $single ): Retrieves a value. Passtrueas the third argument to get a single value instead of an array.add_post_meta( $post_id, $key, $value, $unique ): Adds a new value.update_post_meta( $post_id, $key, $value ): Updates a value, or adds it if it doesn't exist.delete_post_meta( $post_id, $key ): Removes a value.
A single post can have multiple values for the same key, which is why get_post_meta() returns an array unless $single is true.
Displaying a Custom Field in a Template
To show a book_author field saved through the built-in panel:
<?php
$sajjad_book_author = get_post_meta( get_the_ID(), 'book_author', true );
if ( ! empty( $sajjad_book_author ) ) {
echo '<p class="book-author">' . esc_html__( 'Written by', 'mytheme' ) . ' ' . esc_html( $sajjad_book_author ) . '</p>';
}
?>
Place this inside the loop in a template such as single.php in your child theme.
Registering Meta for the Block Editor and REST API
In modern WordPress, it's best to register your meta keys. This tells WordPress the data type, how to sanitize it, who can edit it, and whether it's available in the REST API (which the block editor uses).
function sajjad_register_book_meta() {
register_post_meta(
'post',
'book_author',
array(
'type' => 'string',
'description' => __( 'The author of the reviewed book.', 'sajjad' ),
'single' => true,
'default' => '',
'show_in_rest' => true,
'sanitize_callback' => 'sanitize_text_field',
'auth_callback' => function () {
return current_user_can( 'edit_posts' );
},
)
);
register_post_meta(
'post',
'book_rating',
array(
'type' => 'integer',
'single' => true,
'default' => 0,
'show_in_rest' => true,
'sanitize_callback' => 'absint',
'auth_callback' => function () {
return current_user_can( 'edit_posts' );
},
)
);
}
add_action( 'init', 'sajjad_register_book_meta' );
For a custom post type, the post type must include custom-fields in its supports argument for REST-exposed meta to be editable in the block editor.
Adding a Custom Meta Box
If you want a simple, dedicated input without a plugin, you can create a meta box. It includes a nonce, capability checks, and sanitization to keep it secure:
function sajjad_add_book_meta_box() {
add_meta_box(
'sajjad_book_details',
__( 'Book Details', 'sajjad' ),
'sajjad_render_book_meta_box',
'post',
'side'
);
}
add_action( 'add_meta_boxes', 'sajjad_add_book_meta_box' );
function sajjad_render_book_meta_box( $post ) {
wp_nonce_field( 'sajjad_save_book_details', 'sajjad_book_nonce' );
$author = get_post_meta( $post->ID, 'book_author', true );
?>
<p>
<label for="sajjad_book_author"><?php esc_html_e( 'Book author', 'sajjad' ); ?></label>
<input type="text" id="sajjad_book_author" name="sajjad_book_author" value="<?php echo esc_attr( $author ); ?>" class="widefat" />
</p>
<?php
}
function sajjad_save_book_meta_box( $post_id ) {
if ( ! isset( $_POST['sajjad_book_nonce'] ) ||
! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['sajjad_book_nonce'] ) ), 'sajjad_save_book_details' ) ) {
return;
}
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
return;
}
if ( ! current_user_can( 'edit_post', $post_id ) ) {
return;
}
if ( isset( $_POST['sajjad_book_author'] ) ) {
update_post_meta(
$post_id,
'book_author',
sanitize_text_field( wp_unslash( $_POST['sajjad_book_author'] ) )
);
}
}
add_action( 'save_post', 'sajjad_save_book_meta_box' );
Classic meta boxes still work in the block editor, appearing below the content or in the sidebar, though they are considered a legacy approach compared to registered meta with block editor controls.
Using Custom Fields in Block Themes With Block Bindings
WordPress 6.5 introduced the Block Bindings API, which lets core blocks display custom field values without writing a custom block. For example, a Paragraph block can show the value of a book_author field.
First, register the meta with show_in_rest set to true, as shown above. Then, in the Site Editor's code editor or in a template file, bind a block's content to the field:
<!-- wp:paragraph {"metadata":{"bindings":{"content":{"source":"core/post-meta","args":{"key":"book_author"}}}}} -->
<p></p>
<!-- /wp:paragraph -->
Supported blocks and attributes include:
- Paragraph:
content - Heading:
content - Image:
url,alt,title - Button:
url,text,linkTarget,rel
Recent versions (6.7 and later) also include a user interface in the block sidebar for connecting supported blocks to registered custom fields, so you may not need to edit markup by hand. Meta keys starting with an underscore are treated as protected and aren't available for bindings.
Querying Posts by Custom Field
Custom fields are also useful for filtering. For example, to show the highest-rated book reviews:
<?php
$sajjad_top_books = new WP_Query(
array(
'post_type' => 'post',
'posts_per_page' => 5,
'meta_key' => 'book_rating',
'orderby' => 'meta_value_num',
'order' => 'DESC',
'meta_query' => array(
array(
'key' => 'book_rating',
'value' => 4,
'compare' => '>=',
'type' => 'NUMERIC',
),
),
)
);
if ( $sajjad_top_books->have_posts() ) {
echo '<ol class="top-books">';
while ( $sajjad_top_books->have_posts() ) {
$sajjad_top_books->the_post();
printf(
'<li><a href="%1$s">%2$s</a></li>',
esc_url( get_permalink() ),
esc_html( get_the_title() )
);
}
echo '</ol>';
wp_reset_postdata();
}
?>
Meta queries are powerful, but they can be slow on large sites because meta_value isn't indexed. If you frequently filter by a field, consider whether a taxonomy would be a better fit.
Custom Fields for Users, Terms, and Comments
Post meta is the most common type, but WordPress has the same system for other objects:
- User meta:
get_user_meta(),update_user_meta(), stored inwp_usermeta - Term meta:
get_term_meta(),update_term_meta(), stored inwp_termmeta - Comment meta:
get_comment_meta(),update_comment_meta(), stored inwp_commentmeta
ACF and similar plugins can add fields to all of these through their location rules.
Best Practices for Custom Fields
- Use clear, prefixed keys:
sajjad_book_authoris less likely to clash with a plugin thanauthor. - Register your meta:
register_post_meta()documents the data, sets types, and handles sanitization. - Always sanitize input and escape output: Use functions like
sanitize_text_field(),absint(),esc_html(),esc_attr(), andesc_url(). - Check capabilities and nonces: Any custom save routine must verify the user can edit the post.
- Don't overuse meta queries: Use taxonomies for data you filter or group by often.
- Plan for portability: If you rely on a plugin like ACF, your templates depend on it. Using
get_post_meta()for simple fields reduces that dependency. - Clean up unused fields: Old plugins can leave behind thousands of meta rows. Tools like WP-Optimize or a careful SQL cleanup (after a backup) can help.
FAQ: WordPress Custom Fields
Custom fields are extra key and value pairs of data attached to posts, pages, or custom post types, such as a price, rating, or event date. WordPress stores them as post meta.
They're hidden by default. Open the Options menu, go to Preferences, and enable Custom fields under the Advanced section, then reload the editor.
No. WordPress has built-in custom fields and a full meta API. ACF makes them easier to manage, with better field types and a friendlier interface.
In PHP templates, use get_post_meta() with the post ID, the field key, and true, then escape the output. In block themes, use block bindings to connect a block to the field.
A custom post type is a new kind of content, like Events. Custom fields are extra data points attached to individual items, like an event's date and venue. They're often used together.
Keys that begin with an underscore are protected and hidden from the panel. Plugins use them to store internal data.
Not for normal use. Reading meta for a single post is fast and cached. Performance issues usually come from complex meta queries across many posts on large sites.
Conclusion
Custom fields let you store structured information, such as ratings, prices, dates, and links, alongside your WordPress content. You can start with the built-in Custom Fields panel, move to a plugin like Advanced Custom Fields for a polished editing experience, or work directly with register_post_meta(), get_post_meta(), and related functions for complete control.
In modern block themes, the Block Bindings API makes it possible to show custom field values in core blocks without building custom blocks, which is a big step forward. Whichever approach you choose, prefix your keys, sanitize and escape your data, and use taxonomies when you need grouping. With those habits in place, custom fields will make your site far more capable and your content far better organized.


