How to Automatically Add Image Credit or Source URL to Photo Captions in WordPress

Add image author or source URL to photos in WordPress

Photo credit added automatically to every photo with a caption (via putukrejums.lv)

Crediting and linking the source of any republished photo or illustration on the web is one of the most important best practices of web publishing. Unfortunately, there isn’t a standard way of doing it in WordPress and authors are left with their own decision on how and where to credit the original author or website.

I decided to add a simple “Source URL” input field to every image that is uploaded. Adding credit with a link to the source of that image now becomes as easy as adding a title or caption for an image:

Attached image Source URL input field

Implementation

You need to add the following snippet of PHP to your theme’s functions.php:

Add the source URL input field to image upload screen

add_filter("attachment_fields_to_edit", "add_image_source_url", 10, 2);
function add_image_source_url($form_fields, $post) {
	$form_fields["source_url"] = array(
		"label" => __("Source URL"),
		"input" => "text",
		"value" => get_post_meta($post->ID, "source_url", true),
                "helps" => __("Add the URL where the original image was posted"),
	);
 	return $form_fields;
}

add_filter("attachment_fields_to_save", "save_image_source_url", 10 , 2);
function save_image_source_url($post, $attachment) {
	if (isset($attachment['source_url']))
		update_post_meta($post['ID'], 'source_url', esc_url($attachment['source_url']));
	return $post;
}

Automatically append the source URL to image captions

add_filter('img_caption_shortcode', 'caption_shortcode_with_credits', 10, 3);
function caption_shortcode_with_credits($empty, $attr, $content) {
	extract(shortcode_atts(array(
		'id'	=> '',
		'align'	=> 'alignnone',
		'width'	=> '',
		'caption' => ''
	), $attr));

	// Extract attachment $post->ID
	preg_match('/\d+/', $id, $att_id);
	if (is_numeric($att_id[0]) && $source_url = get_post_meta($att_id[0], 'source_url', true)) {
		$parts = parse_url($source_url);
		$caption .= ' ('. __('via') .' <a href="'. $source_url .'">'. $parts['host'] .'</a>)';
	}

	if (1 > (int) $width || empty($caption))
		return $content;

	if ($id)
		$id = 'id="' . esc_attr($id) . '" ';

	return '<div ' . $id . 'class="wp-caption ' . esc_attr($align) . '" style="width: ' . (10 + (int) $width) . 'px">'
		. do_shortcode($content) . '<p class="wp-caption-text">' . $caption . '</p></div>';
}

Please note that the source URL will be visible only if you specify image caption upon inserting the image.

8 Comments

Chris Bracco Feb 28, 2012, 23:25

Thanks a ton for this code! One question – how can I append this to the caption for a post thumbnail?

Kaspars Feb 29, 2012, 22:07

Chris, this should work also with thumbnail captions. Or do you mean featured images? In that case you need to write some custom code (depending on the theme you’re using) to echo caption along with the featured image.

Chris Bracco Mar 1, 2012, 2:14

Nevermind, I’ve figured out how to do it. Thanks!

Kaspars Mar 1, 2012, 10:20

Would you mind sharing your solution, Chris? There might be others interested in doing something similar.

Chris Bracco Mar 1, 2012, 18:04

All you have to do is include the following inside your main WP loop, underneath your featured thumbnail…

<?php 
$thumb_id = get_post_thumbnail_id($post->ID);
$thumb_title = get_the_title($thumb_id); 
?>

<?php if(!empty(get_post($thumb_id)->post_excerpt)) : ?>
<figcaption class="wp-caption-text">
<?php echo get_post($thumb_id)->post_excerpt; ?>

<?php 
$source_url = get_post_meta($thumb_id, 'source_url', true);
$parts = parse_url($source_url);
if(!empty($source_url))
echo ' (via: <a href="' . $source_url . '" target="_blank">' . $parts['host'] . '</a>)';
?>
</figcaption>
<?php endif; ?>

If you aren’t using HTML5, then make sure to use something different than the <figcaption> tag, like a <div> or <span>.

Zeruela Mar 7, 2013, 23:32

Where’s the main WP loop that you are reference?

Kaspars Mar 10, 2013, 12:36

I am sure that Chris was referring the main have_posts() while loop inside your index.php, archive.php and single.php template files.