Custom Avatars in WordPress

WordPress has built-in support for Gravatars, globally recognized avatars. This means if you go to Gravatar.com and associate a picture with your email, any WordPress website you post on can use it.

But some people might not want to use Gravatar. I’m working on a magazine site where some of the authors have created gravatars, but many just want to email their photo to the editor and have her take care of it.

I’ve created a Custom Avatar feature that extends the built-in avatar functions of WordPress. It adds a “Custom Avatar URL” field to the user’s Profile page. If an avatar is provided, it is displayed by the function get_avatar() rather than the gravatar.

The Genesis theme has a great feature called the Author Box. Instead of me having to rebuild it to show my custom avatar, it just works with this solution since I’m extending the built-in avatar functions, not creating new ones.

Adding Custom Avatar Field

We’re going to create two functions: one that displays the field on the profile, and one that updates the field when you click “Update”.

<?php
/**
 * Add Custom Avatar Field
 * @author Bill Erickson
 * @link http://www.billerickson.net/wordpress-custom-avatar/
 *
 * @param object $user
 */
function be_custom_avatar_field( $user ) { ?>
	<h3>Custom Avatar</h3>
	 
	<table>
	<tr>
	<th><label for="be_custom_avatar">Custom Avatar URL:</label></th>
	<td>
	<input type="text" name="be_custom_avatar" id="be_custom_avatar" value="<?php echo esc_url_raw( get_the_author_meta( 'be_custom_avatar', $user->ID ) ); ?>" /><br />
	<span>Type in the URL of the image you'd like to use as your avatar. This will override your default Gravatar, or show up if you don't have a Gravatar. <br /><strong>Image should be 70x70 pixels.</strong></span>
	</td>
	</tr>
	</table>
	<?php 
}
add_action( 'show_user_profile', 'be_custom_avatar_field' );
add_action( 'edit_user_profile', 'be_custom_avatar_field' );

/**
 * Save Custom Avatar Field
 * @author Bill Erickson
 * @link http://www.billerickson.net/wordpress-custom-avatar/
 *
 * @param int $user_id
 */
function be_save_custom_avatar_field( $user_id ) {
	if ( current_user_can( 'edit_user', $user_id ) ) {
		update_usermeta( $user_id, 'be_custom_avatar', esc_url_raw( $_POST['be_custom_avatar'] ) );
	}
}
add_action( 'personal_options_update', 'be_save_custom_avatar_field' );
add_action( 'edit_user_profile_update', 'be_save_custom_avatar_field' );

I’ve added a description on the first function to help the users add the correct size photo. Make sure your users upload a square photo (or else it will be squished) and that is at least as large as the largest use in the site. On this project, the Author Box displays the avatar as a 70px square, and on the homepage it’s a 30px square, so I recommend they upload at least 70×70 photo.

Making it Work

We’ll be able to access the custom avatar using get_the_author_meta( 'be_custom_avatar' ). Now let’s set up a filter on get_avatar() that uses the custom avatar, if provided.

<?php
/**
 * Use Custom Avatar if Provided
 * @author Bill Erickson
 * @link http://www.billerickson.net/wordpress-custom-avatar/
 *
 */
function be_gravatar_filter($avatar, $id_or_email, $size, $default, $alt) {
	
	// If provided an email and it doesn't exist as WP user, return avatar since there can't be a custom avatar
	$email = is_object( $id_or_email ) ? $id_or_email->comment_author_email : $id_or_email;
	if( is_email( $email ) && ! email_exists( $email ) )
		return $avatar;
	
	$custom_avatar = get_the_author_meta('be_custom_avatar');
	if ($custom_avatar) 
		$return = '<img src="'.$custom_avatar.'" width="'.$size.'" height="'.$size.'" alt="'.$alt.'" />';
	elseif ($avatar) 
		$return = $avatar;
	else 
		$return = '<img src="'.$default.'" width="'.$size.'" height="'.$size.'" alt="'.$alt.'" />';

	return $return;
}
add_filter('get_avatar', 'be_gravatar_filter', 10, 5);

This modifies get_avatar() function to perform in the following way:

  • If there’s a custom avatar, use that.
  • If there isn’t a custom avatar, check to see if there’s a gravatar. If there’s a gravatar, use that.
  • If there’s neither, display the default.

Bill Erickson

Bill Erickson is the co-founder and lead developer at CultivateWP, a WordPress agency focusing on high performance sites for web publishers.

About Me
Ready to upgrade your website?

I build custom WordPress websites that look great and are easy to manage.

Let's Talk

Reader Interactions

Comments are closed. Continue the conversation with me on Twitter: @billerickson

Comments

  1. Elpie says

    Creating a custom avatar for registered users cuts down some of the HTTP requests but would only really be useful if WordPress was set up so everyone had to register in order to comment, or if there were a lot of regular, registered contributors. If there’s only a few then its arguable that the benefit of using a custom avatar is outweighed by the disadvantage in page loading speeds.

    Using gravatars generates a LOT of HTTP requests for every comment on a post. If I understand your code correctly then on pageload for every post with comments the server loads the page, then sends another request to check for the custom avatar for every comment on that page. If one isn’t found then another HTTP request gets sent to gravatar.com and then if those two conditions are not satisfied there is yet another HTTP request to get the default avatar. If the default avatar hasn’t been set to use the blank avatar within WordPress another HTTP request will be sent out to gravatar.com to grab the mystery man, identicon or whatever has been set as the default. That is a whole heap of HTTP requests and could have significant implications for slowing down pages that contain a lot of comments.

    • Bill Erickson says

      Correct, this technique is designed for websites which have many contributors. It is not designed for commenting systems.

      I built this for a magazine site with 20 or so contributors. We’re only displaying gravatars for article authors (comments are done with Disqus).

  2. Adam Cap says

    Dude this is gnarly… I didn’t think this type of thing was possible but it looks like a huge help for me. I run a site driven by user submissions, and it was annoying to tell people they have to register for gravatar if they want their picture to show up along with their article.

    Thanks for sharing!!

    -Adam

      • Adam Cap says

        Ah very cool, I didn’t know about that. I really like how that lets you upload an image, though I’m totally with you on avoiding plugins when possible.

        I’ve noticed one “bug” with the code (or at least an issue with how I’m trying to use it). I show an author box at the very top of my sidebar, then a few widgets down I have an “Authors of the Month” jawn which also includes get_avatar() functions.

        I use get_avatar() functions a total of 4 times within the sidebar… the first avatar is filtered by be_gravatar_filter() and shows the right avatar, but then the other 3 avatars shown are the same as avatar #1.

        So what I’ve done as a temp fix is use a remove_filter() to prevent those last 3 get_avatar() from being filtered, but I’m trying to figure out if there’s a way to reset the filter so it goes through each get_avatar() individually and doesn’t store the first image it finds.

        Do you have any idea what to do about that? If it was a query, I know you could reset_query, but this seems more complicated.

        • Bill Erickson says

          The problem is the code I posted looks for the author of the current post/page you’re on – it’s designed with that assumption. You might check to see if $id_or_email is defined (the second variable in the filter) and if so, get THAT author’s avatar. If it isn’t defined, get the avatar for the author of the current page.

          • Adam Cap says

            Ahh that makes sense. Here’s what I ended up doing, just incase anyone else has the same problem:

            I was having issues getting things to work by adding extra “ifs” to your original function, so I just duplicated it and added $id_or_email to the get_the_author_meta() like so:

            function be_gravatar_filter_two($avatar, $id_or_email, $size, $default, $alt) {
            $custom_avatar = get_the_author_meta(‘be_custom_avatar’,$id_or_email);
            if ($custom_avatar) $return = ”;
            elseif ($avatar) $return = $avatar;
            else $return = ”;
            return $return;
            }

            Then I just removed the original filter and applied the second one where I needed it in my template:

            Thanks for the help man!

  3. rick says

    I guess I am stupid and don’t know a great lot about this. Just where do you put the codes? I believe it might be function.php. I have fresh-ink-magazine. Thanks

  4. Wendy says

    Hi, this is exactly what I’m looking for!!! a custom url avatar for subscribers…..
    Does it only work under Genesis theme????
    cuz it doesn’t work on mine 🙁

    or should it be placed in the general functions.php file???
    I tried both the theme functions.php and the general one in wp-includes folder…..
    but either of them worked > in the end but it showed “Fatal error: Call to undefined function add_action() in /home/vul3yji3/public_html/wp-includes/functions.php on line 4486” ……

    Could you please indicate the right place to insert the code for me??? I really need this!!!

    Thank you very much!!

  5. Wendy says

    !!!! I succeeded!!! I found the right place~
    It works well now~~~
    Thank you so much!!!!

    I’ll give you a “like” 😀 ~ thumbs up!!!

  6. Wendy says

    Hi Bill,
    It works well in one of my wordpress but it doesn’t work in my other 2 sites…. (in ipage & hostmonster…….)

    I successfully added the custom field in profile.php and I can also save the url but the gravatar just stayed as wordpress’s default image …..

    Do you have any idea ????
    Thanks!!

    • Bill Erickson says

      I’m sorry, but troubleshooting the specific conflicts in your theme is beyond the scope of this tutorial.

  7. Cor van Noorloos says

    Hello Bill,

    Would it be possible to disable the gravatar lookup completely and just use your plugin if else the mystery man avatar?

  8. jonnyjaniero says

    thanks Bill, most useful. exactly what i needed for my current client project.

    a note for others… you may want add a $position to the action. i had WPML installed that also hooked into user page and Bills code was positioned in between fields of WPML. handy to know if user existing plugins that hook into the user profile admin screen.

    i specified 15, but its whatever works in your particular situation
    add_action( ‘show_user_profile’, ‘be_custom_avatar_field’, 15 );

  9. jonnyjaniero says

    oh, also added some existing wordpress classes to form markup should help it sit better.
    add the ‘form-table’ class to table

    and
    ‘regular-text’ to the input field
    <input type="text" class="regular-text" name="be_custom_avatar" id="be_custom_avatar" value="ID ) ); ?>” />

    again, thanks for this Bill

  10. Sjoerd says

    The be_gravatar_filter function code doesn’t return its return value. And it works for all the commenters above me? Or did the example code change?

    Anyway, the function be_gravatar_filter should end with: return $return;

    • Bill Erickson says

      Thanks for catching this. I recently moved all the code from in the blog post to Github and must have not copied it all over. I just updated the code.