Add Custom Meta Fields to Media Attachments in  WordPress

Add Custom Meta Fields to Media Attachments in WordPressWordPress allows you to add a description, caption, title and link onto any media attachment. But what if you want to add custom fields to your images, video or audio files? This can be done by manipulating data with the attachment_fields_to_edit and attachment_fields_to_save filters.

Adding Additional Fields

This function will remove, edit the order and add additional custom fields to the Media attachment edit and add view in WordPress for both Posts and the Media Library.

/**
 * Add custom media metadata fields
 *
 * Be sure to sanitize your data before saving it
 * https://codex.wordpress.org/Data_Validation
 *
 * @param $form_fields An array of fields included in the attachment form
 * @param $post The attachment record in the database
 * @return $form_fields The final array of form fields to use
 */
function add_image_attachment_fields_to_edit( $form_fields, $post ) {
	
	// Remove the "Description" field, we're not using it
	unset( $form_fields['post_content'] ); 
	
	// Add description text (helps) to the "Title" field
	$form_fields['post_title']['helps'] = 'Use a descriptive title for the image. This will make it easy to find the image in the future and will improve SEO.';
		
	// Re-order the "Caption" field by removing it and re-adding it later
	$form_fields['post_excerpt']['helps'] = 'Describe the significants of the image pertaining to the site.';
	$caption_field = $form_fields['post_excerpt'];
	unset($form_fields['post_excerpt']);
	
	// Re-order the "File URL" field
	$image_url_field = $form_fields['image_url'];
	unset($form_fields['image_url']);
	
	// Add Caption before Credit field 
	$form_fields['post_excerpt'] = $caption_field;
	
	// Add a Credit field
	$form_fields["credit_text"] = array(
		"label" => __("Credit"),
		"input" => "text", // this is default if "input" is omitted
		"value" => esc_attr( get_post_meta($post->ID, "_credit_text", true) ),
		"helps" => __("The owner of the image."),
	);
	
	// Add a Credit field
	$form_fields["credit_link"] = array(
		"label" => __("Credit URL"),
		"input" => "text", // this is default if "input" is omitted
		"value" => esc_url( get_post_meta($post->ID, "_credit_link", true) ),
		"helps" => __("Attribution link to the image source or owners website."),
	);
	
	// Add Caption before Credit field 
	$form_fields['image_url'] = $image_url_field;
	
	return $form_fields;
}
add_filter("attachment_fields_to_edit", "add_image_attachment_fields_to_edit", null, 2);

Save The Data as Custom Fields

This function will validate and save the data as custom fields associated with the attachment. Each attachment you upload is considered a post in WordPress and is stored in the postmeta table.

/**
 * Save custom media metadata fields
 *
 * Be sure to validate your data before saving it
 * https://codex.wordpress.org/Data_Validation
 *
 * @param $post The $post data for the attachment
 * @param $attachment The $attachment part of the form $_POST ($_POST[attachments][postID])
 * @return $post
 */
function add_image_attachment_fields_to_save( $post, $attachment ) {
	if ( isset( $attachment['credit_text'] ) )
		update_post_meta( $post['ID'], '_credit_text', esc_attr($attachment['credit_text']) );
		
	if ( isset( $attachment['credit_link'] ) )
		update_post_meta( $post['ID'], '_credit_link', esc_url($attachment['credit_link']) );

	return $post;
}
add_filter("attachment_fields_to_save", "add_image_attachment_fields_to_save", null , 2);

How to Display Attachment Custom Fields

Now that we have 2 new fields created we need to display the data in a plugin or theme. This can be done using the get_children() and get_post_custom() WordPress functions. Let’s take a look at a nice function that uses both to display an image caption somewhere in a theme.

/**
 * Display image credit
 *
 * Display the "Credit" custom fields added to media attachments 
 *
 * Uses get_children() https://codex.wordpress.org/Function_Reference/get_children
 * Uses get_post_custom() https://codex.wordpress.org/Function_Reference/get_post_custom
 * @global $post The current post data
 * @return Prints the caption HTML
 */
function base_image_credit( $post_ID = null ) {
	// Get the post ID of the current post if not set
	if ( !$post_ID ) {
		global $post;
		$post_ID = $post->ID;
	}
	
	// Get all the attachments for the current post (object stdClass)
	$attachments = get_children('post_type=attachment&post_parent=' . $post->ID);
	
	// If attachments are found
	if ( isset($attachments) && !empty($attachments) ) {
		// Get the first attachment
		$first_attachment = current($attachments);
		$attachment_fields = get_post_custom( $first_attachment->ID );
		
		// Get custom attachment fields
		$credit_text = ( isset($attachment_fields['_credit_text'][0]) && !empty($attachment_fields['_credit_text'][0]) ) ? esc_attr($attachment_fields['_credit_text'][0]) : '';
		$credit_link = ( isset($attachment_fields['_credit_link'][0]) && !empty($attachment_fields['_credit_link'][0]) ) ? esc_url($attachment_fields['_credit_link'][0]) : '';
		
		// Output HTML if you want
		$credit = ( $credit_text && $credit_link ) ? "Image provided by $credit_text ({credit_link})" : false;
	}
	
	return $credit;
}

This function takes an optional post ID argument. This may come in handy if you are displaying the caption information outside of the loop somewhere. If you’re using it inside of the loop or on a singular post the post ID isn’t required. The function will check for attachments given a post. If attachments exist it will grab the first attachment and get the _credit_text and _credit_link custom field values if they aren’t empty and returns a small bit of HTML.

Using the Display Image Credit Function

This function can be used anywhere in a plugin or theme. I’ve used the functionality on single.php like this:

 if( function_exists('base_image_credit') ) echo base_image_credit(); 

This example isn’t entirely practical, it merely serves as an example of how to extract the custom fields values from an attachment for a given post. Hopefully you can use this demo to expand upon for your own purposes.

Add Image Credits to Attachment Captions

Let’s look at a more practical example. Image credits are often required on Blogs to meet the needs of the creative commons attribution license. Using the two attachment custom fields we create above for “Credit text” and “Credit Link” we can add an additional paragraph to display the image credit information in the shortcode in WordPress.

For more information on filtering the caption shortcode in WordPress I highly recommend the WP Engineer article Filter Caption Shortcode in WordPress.

/**
 * Add image credits to captions
 *
 * Add the "Credit" custom fields to media attachments with captions
 *
 * Uses get_post_custom() https://codex.wordpress.org/Function_Reference/get_post_custom
 */
function base_image_credit_to_captions($attr, $content = null) {
	// Allow plugins/themes to override the default caption template.
	$output = apply_filters('img_caption_shortcode', '', $attr, $content);
	
	if ( $output != '' )
		return $output;
		
	extract( shortcode_atts(array(
		'id'	=> '',
		'align'	=> 'alignnone',
		'width'	=> '',
		'caption' => ''
	), $attr) );
	
	if ( 1 > (int) $width || empty($caption) )
		return $content;
	
	if ( $id ) {
		$attachment_id = intval( str_replace( 'attachment_', '', $id ) );
		$id = 'id="' . $id . '" ';
	}
		
	$caption_content = '
'; $caption_content .= do_shortcode( $content ); $caption_content .= '

' . $caption . '

'; // Get image credit custom attachment fields $attachment_fields = get_post_custom( $attachment_id ); $credit_text = ( isset($attachment_fields['_credit_text'][0]) && !empty($attachment_fields['_credit_text'][0]) ) ? esc_attr($attachment_fields['_credit_text'][0]) : ''; $credit_link = ( isset($attachment_fields['_credit_link'][0]) && !empty($attachment_fields['_credit_link'][0]) ) ? esc_url($attachment_fields['_credit_link'][0]) : ''; // If image credit fields have data then attach the image credit if ( $credit_text && $credit_link ) $caption_content .= '

Image provided by ' . $credit_link . ', ' . $credit_text . '

'; $caption_content .= '
'; return $caption_content; } add_shortcode('wp_caption', 'base_image_credit_to_captions'); add_shortcode('caption', 'base_image_credit_to_captions');

This will automatically add a new paragraph below wp-caption-text called wp-credit-text. You can style this however you like. I’ve used a nice jQuery mouseover fadein technique to display image credits on the OpenView Blog.

In Conclusion

Hopefully this helps you out on your next WordPress project! Thanks to popper for originally posting this on the WordPress codex.

More Resources

Related Articles

Meet the Author

Kevin Leary, WordPress Consultant

I'm a custom WordPress web developer and analytics consultant in Boston, MA with 17 years of experience building websites and applications. View a portfolio of my work or request an estimate for your next project.