How do I add two custom fields to images to allow me to put in text for source name example: Shutterstock and then link that text to the second custom field URL field example: shutterstock.com

Some solutions out there don't work or are outdated.

add_filter( 'attachment_fields_to_edit', 'ac_add_image_source', 10, 2 );

function ac_add_image_source( $form_fields, $post ) {

$form_fields['source_name'] = array(
    'label' => __('Source Name'),
    'input' => 'text',
    'value' => get_post_meta( $post->ID, '_wp_attachment_source_name', true ),
    'helps' => __('Add the name of the image source'),

$form_fields['source_url'] = array(
    'label' => __('Source URL'),
    'input' => 'text',
    'value' => get_post_meta( $post->ID, '_wp_attachment_source_url', true ),
    'helps' => __('Add the URL where the original image was posted'),

return $form_fields;


/** * Save credit fields * */ add_filter( 'attachment_fields_to_save', 'ac_save_image_source', 10 , 2 );

function ac_save_image_source( $post, $attachment ) {

if ( isset( $attachment['source_name'] ) ) {
    $source_name = get_post_meta( $post['ID'], '_wp_attachment_source_name', true );
    if ( $source_name != esc_attr( $attachment['source_name'] ) ) {
        if ( empty( $attachment['source_name'] ) )
            delete_post_meta( $post['ID'], '_wp_attachment_source_name' );
            update_post_meta( $post['ID'], '_wp_attachment_source_name', esc_attr( $attachment['source_name'] ) );

if ( isset( $attachment['source_url'] ) ) {
    $source_name = get_post_meta( $post['ID'], '_wp_attachment_source_url', true );
    if ( $source_name != esc_attr( $attachment['source_url'] ) ) {
        if ( empty( $attachment['source_url'] ) )
            delete_post_meta( $post['ID'], '_wp_attachment_source_url' );
            update_post_meta( $post['ID'], '_wp_attachment_source_url', esc_attr( $attachment['source_url'] ) );

return $post;


1 Answer 1


There are a few different ways you could achieve this.

The most obvious one would be to use two existing image fields- are you already using Title, caption, alt text and description? If not, these are available, and you could simply add some code to your template to use (say) the caption as the link and the description as the source.

If this seems messy or if you are already using the image fields, you could also use a plugin to make categories available to media items. I recently used this one with some success: https://wordpress.org/plugins/wp-media-library-categories/

With the addition of a couple of lines of code, this lets you store image categories separately from ordinary post categories:

* separate media categories from post categories
* use a custom category called 'category_media' for the categories in the media library
add_filter( 'wpmediacategory_taxonomy', function(){ return 'category_media'; } );

This way you could store the sources as media categories, putting the URL in the category description field. The advantage of this approach would be that you'd be able to globally change source URLs without changing individual image data.

Hope this helps.


The functions.php hook you found is working just fine. To output the values it's storing, you just need to pass the ID of the image to the get_post_meta function along with the keys for the values stored. In the snippet below I'm assuming the image is the thumbnail of the current post.

$source_url = get_post_meta(get_post_thumbnail_id(get_the_ID()),'_wp_attachment_source_url', true);
$source_name = get_post_meta(get_post_thumbnail_id(get_the_ID()),'_wp_attachment_source_name', true); ?>
<a href="<?php echo $source_url; ?>"><?php echo $source_name; ?></a>

Let me know if you have any trouble.


In response to the original poster's request, here is a filter to incorporate the newly stored source information into images inserted via the WordPress editor. This function and filter need to be put in the functions.php file as well. This checks that both a link and source name exist. If they do, it outputs a line break and a link to the source, opening in a new window.

function image_add_caption_with_source( $html, $id, $caption, $title, $align, $url, $size, $alt = '' ) {

   * Filters the caption text and adds source info.
   * Note: If the caption text is empty, the caption shortcode will not be appended
   * to the image HTML when inserted into the editor.
   * Passing an empty value also prevents the {@see 'image_add_caption_shortcode'}
   * Filters from being evaluated at the end of image_add_caption().
   * @since 4.1.0
   * @param string $caption The original caption text.
   * @param int    $id      The attachment ID.
  $caption = apply_filters( 'image_add_caption_text', $caption, $id );
  $source_url = get_post_meta($id,'_wp_attachment_source_url', true);
  $source_name = get_post_meta($id,'_wp_attachment_source_name', true);
   * Filters whether to disable captions.
   * Prevents image captions from being appended to image HTML when inserted into the editor.
   * @since 2.6.0
   * @param bool $bool Whether to disable appending captions. Returning true to the filter
   *                   will disable captions. Default empty string.
  if ( empty($caption) || apply_filters( 'disable_captions', '' ) )
    return $html;

  $id = ( 0 < (int) $id ) ? 'attachment_' . $id : '';

  if ( ! preg_match( '/width=["\']([0-9]+)/', $html, $matches ) )
    return $html;

  $width = $matches[1];

  $caption = str_replace( array("\r\n", "\r"), "\n", $caption);
  $caption = preg_replace_callback( '/<[a-zA-Z0-9]+(?: [^<>]+>)*/', '_cleanup_image_add_caption', $caption );

  // Convert any remaining line breaks to <br>.
  $caption = preg_replace( '/[ \n\t]*\n[ \t]*/', '<br />', $caption );

  $html = preg_replace( '/(class=["\'][^\'"]*)align(none|left|right|center)\s?/', '$1', $html );
  if($source_url && $source_name):
   $source ='<br /><a target="_blank" href="'.$source_url.'">'.$source_name.'</a>';
   $source = "";
  if ( empty($align) )
    $align = 'none';

  $shcode = '[caption id="' . $id . '" align="align' . $align . '" width="' . $width . '"]' . $html . ' ' . $caption . $source . '[/caption]';

   * Filters the image HTML markup including the caption shortcode.
   * @since 2.6.0
   * @param string $shcode The image HTML markup with caption shortcode.
   * @param string $html   The image HTML markup.

  return apply_filters( 'image_add_caption_shortcode', $shcode, $html );

// remove the existing filter
remove_filter( 'image_send_to_editor', 'image_add_caption', 20, 8 );
// add the new filter
add_filter( 'image_send_to_editor', 'image_add_caption_with_source', 20, 8 ); 
  • Hi Jonny, I use all the tabs for my images so would need two extra fields added. The above link i mentioned does do this but when i actually put text and url into the fields it shows nothing on frontend. Also don't need to put my images into categories as each image has a different source.
    – camputer
    Commented Sep 27, 2016 at 10:39
  • I just noticed someone edited the link out from my main post so I added the code there instead. It put it into two separate boxes but it is all just one code
    – camputer
    Commented Sep 27, 2016 at 14:38
  • Do you know if that code above is successfully saving what you type in into the database?
    – Jonny Perl
    Commented Sep 27, 2016 at 14:42
  • I am not sure do you have a site you could quickly try it on? Just paste into functions.php
    – camputer
    Commented Sep 27, 2016 at 16:50
  • Sure. It seems to work (ie display the admin form and store the data) - it's just that the snippet you found didn't specify how to output the stored values. I am adding info about that to my answer above.
    – Jonny Perl
    Commented Sep 27, 2016 at 19:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.