WordPress Custom Fields and Post Meta

Custom fields (also called post meta) store extra data for a post, like a price, an author name or an event date. Each field is a key and value pair saved in the wp_postmeta table. You can use them on posts, pages and custom post types.

The post meta functions

FunctionWhat it does
add_post_meta( $id, $key, $value, $unique )Add a new field
update_post_meta( $id, $key, $value )Change the field, or add it if it is missing
get_post_meta( $id, $key, $single )Read the field. Use true to get one value, not an array
delete_post_meta( $id, $key )Remove the field

Try them

$post_id = wp_insert_post( array(
	'post_title'  => 'Red running shoes',
	'post_status' => 'publish',
	'post_date'   => '2026-03-01 10:00:00',
) );

update_post_meta( $post_id, 'price', 2499 );
add_post_meta( $post_id, 'size', 8 );
add_post_meta( $post_id, 'size', 9 );   // the same key again, second row

echo 'price: ' . get_post_meta( $post_id, 'price', true ) . "\n";
echo 'size (single): ' . get_post_meta( $post_id, 'size', true ) . "\n";
echo 'size (all): ' . implode( ', ', get_post_meta( $post_id, 'size' ) ) . "\n";

update_post_meta( $post_id, 'price', 1999 );
echo 'new price: ' . get_post_meta( $post_id, 'price', true ) . "\n";

delete_post_meta( $post_id, 'size' );
echo 'sizes left: ' . count( get_post_meta( $post_id, 'size' ) );
Output

price: 2499
size (single): 8
size (all): 8, 9
new price: 1999
sizes left: 0

Without the third parameter true, get_post_meta() gives you an array of all the values of that key.

Show a custom field in a template

<?php
$price = get_post_meta( get_the_ID(), 'price', true );
if ( $price ) {
	echo '<p class="price">Price: Rs. ' . esc_html( number_format( (float) $price ) ) . '</p>';
}
?>

Names that start with an underscore

A meta key which starts with _ (like _thumbnail_id) is hidden: WordPress does not show it in the custom fields box of the editor. Use that for the data which the user should not edit by hand.

Terminal output

$ wp post meta list 1 –fields=meta_key,meta_value
meta_key meta_value
$ wp post meta add 1 _internal_note "check later"
Success: Added custom field.
$ wp post meta list 1 –fields=meta_key,meta_value
meta_key meta_value
_internal_note check later

Register meta for the REST API and the editor

Use register_post_meta() to give the field a type, and to show it in the REST API (which also makes it usable in blocks):

<?php
add_action( 'init', function () {
	register_post_meta( 'post', 'price', array(
		'type'              => 'number',
		'single'            => true,
		'show_in_rest'      => true,
		'sanitize_callback' => function ( $value ) {
			return (float) $value;
		},
	) );
} );
Terminal output

$ wp post create –post_title="Blue jacket" –post_status=publish –porcelain
6
$ wp post meta add 6 price 3999
Success: Added custom field.
$ curl -s "http://example.com/wp-json/wp/v2/posts/6?_fields=id,title,meta" | jq -c .
{"id":6,"title":{"rendered":"Blue jacket"},"meta":{"price":3999,"footnotes":""}}

Query by a custom field

See the meta_query examples in WP_Query. Searching by meta is slower than searching by taxonomy on big sites, because wp_postmeta has no index on the value.

Plugins for custom fields

For big projects, plugins like Advanced Custom Fields (ACF) or Meta Box give you easy screens to build the field boxes. Underneath they use the same post meta functions you learned here.

Note: Always sanitize the data when you save it (sanitize_text_field(), absint()) and escape it when you print it (esc_html()). We talk more about it in Data Validation and Security. Next: Child Theme.

Congratulations! Chapter Finished. Learn more about the similar topics:
Exercises & Assignments
No Content Found.
Interview Questions & Answers
No Content Found.