The Issue
When you upload a new image into the WordPress media library, it automatically generates a Title for your new image based on the underlying file name.
Unfortunately, WordPress isn’t too sophisticated when it generates the image Title: it removes extraneous spaces in the file name and that’s about it. It won’t remove dashes or underscores, nor will it ensure that words are properly capitalized. So by default your image ends up with a Title that’s literally whatever you used for the file name, minus extra spaces. Which can be pretty crappy, depending on how you name your files.
But the bigger issue is this: WordPress will not automatically set the image Alt-Text.
If you’re serious about SEO you’ll know that’s a problem. For SEO purposes, your images should have an Alt-Text properly specified, it costs nothing and definitely makes a difference. I’ll say it again: always make sure you specify an Alt-Text for your images.
So how might you do that? You could enter the Alt-Text manually in the Edit Media page after you upload an image, but that’s a hassle.
Fortunately there’s a better approach: you can automatically generate the Alt-Text based on a clean, sanitized file name.
And while you’re at it, you might optionally set the image Caption and Description to that same sanitized file name (or something else, if you prefer).
Solution Overview
When you upload a new media file to WordPress it creates a new Attachment. An Attachment is in effect a type of post, and as such an Attachment has a Title, an Excerpt and Content just like regular posts do. In the case of an Attachment, the Excerpt is used to store the image Caption, and the Content is used to store the image Description.
In addition, just like all regular posts, the Attachment can have metadata associated with it. In fact the Alt-Text is exactly that: metadata stored alongside the Attachment (post).
So our approach will be as follows:
- First, upload the new image which creates an Attachment.
- Second, update the Attachment to set the image Title, Excerpt (Caption) and Content (Description).
- Finally, update the Attachment’s metadata to set the image Alt-Text.
We’ll rely on one WordPress action hook and two WordPress functions:
- Hook: we’ll attach our code to the WordPress
add_attachment
hook, which fires immediately after an attachment is created. - Function 1: in WordPress, posts are stored in the wp_posts table. So we can use the
wp_update_post()
function to update the wp_posts table with our new image Title, Excerpt and Description. - Function 2: also, in WordPress post meta is stored in the wp_post_meta table. So we can use the
update_post_meta()
function to set the Alt-Text.
The only question now is: what should we set all of these to? Well, to anything we like, but the easiest is to set them all to a clean, sanitized file name.
So our approach will make sure that each image file uploaded into the media library gets a thorough swish and rinse on the file name: it will automatically get rid of dashes, underscores, extra spaces, and properly capitalize each word.
We’ll use this cleaned-up name for the Title and Alt-Text, and even (optionally) for the Caption and Description if desired.
There’s just one remaining thing that you must do: give each image file a meaningful file name before you upload it. Don’t use the default out-of-camera file name such as IMG_0001.jpg or DSC99876.jpg. Simply rename it to a decent short phrase and you’re good to go.
Detailed Instructions
Follow these steps:
- Rename your image files to a short, meaningful phrase. Don’t worry about dashes, underscores or extra spaces, the code will clean those up.
- Copy the PHP code below and place it in your theme’s functions.php file
- Upload your image files into the WordPress media library. The Edit Media screen will be automatically pre-populated as desired.
/* Automatically set the image Title, Alt-Text, Caption & Description upon upload
--------------------------------------------------------------------------------------*/
add_action( 'add_attachment', 'my_set_image_meta_upon_image_upload' );
function my_set_image_meta_upon_image_upload( $post_ID ) {
// Check if uploaded file is an image, else do nothing
if ( wp_attachment_is_image( $post_ID ) ) {
$my_image_title = get_post( $post_ID )->post_title;
// Sanitize the title: remove hyphens, underscores & extra spaces:
$my_image_title = preg_replace( '%\s*[-_\s]+\s*%', ' ', $my_image_title );
// Sanitize the title: capitalize first letter of every word (other letters lower case):
$my_image_title = ucwords( strtolower( $my_image_title ) );
// Create an array with the image meta (Title, Caption, Description) to be updated
// Note: comment out the Excerpt/Caption or Content/Description lines if not needed
$my_image_meta = array(
'ID' => $post_ID, // Specify the image (ID) to be updated
'post_title' => $my_image_title, // Set image Title to sanitized title
'post_excerpt' => $my_image_title, // Set image Caption (Excerpt) to sanitized title
'post_content' => $my_image_title, // Set image Description (Content) to sanitized title
);
// Set the image Alt-Text
update_post_meta( $post_ID, '_wp_attachment_image_alt', $my_image_title );
// Set the image meta (e.g. Title, Excerpt, Content)
wp_update_post( $my_image_meta );
}
}
Nicely done. Thanks for sharing.
Thanks for this code Francisco!
This will now be in every one my WordPress websites by default!
Cheers,
Gints
Thank you for the nice Code and sharing it!
but how does it works with svg image, with jpg ect it works but the svg image not showing a alt text- perhaps you have a idea?
I believe the issue regarding SVG uploads is with WordPress itself, in that WP does not allow SVG uploads into the media library (try a Google search for “WordPress upload svg”). It seems enabling SVG uploads may be a little more complex than it appears, for example as noted in the following link, I hope this helps:
https://www.bjornjohansen.no/svg-in-wordpress
That’s such a great tip!
i try and work great no need to install new plugin
Thank you.
Great!
Thank you!
Thanks man great thank’s
is there any way to make alt tag different then title, i mean with this function alt tag is same as title tag, please suggest any way by which alt tag should be different then title tag
The Alt-Text is set on lines 27-28 of the code above. You could instead define your own variable, say $my_image_alt_text, and set it to a formula/value of your choice, and then use that variable in line 28, changing it to something like “update_post_meta( $post_ID, ‘_wp_attachment_image_alt’, $my_image_alt_text );”. Of course, the idea is to set the Alt-Text to something specific to the particular image rather than always setting it to a constant value. So you would want to define a formula/value for $my_image_alt_text accordingly.
nice, but I was expecting a tutorial on changing titles/alts of already uploaded images as well
Hello – changing titles/alt-text for previously uploaded images is a COMPLETELY different problem than what the code in this post aims to solve, because of the way WordPress handles images that are inserted into posts/pages.
The key point regarding previously uploaded images is that when you insert those images into a post/page, the image title and alt-text are COPIED into the html of the post/page by WordPress. So if you subsequently change the title/alt-text of the image in the media library, it will NOT affect any post/pages where that image is displayed, since the title/alt-text of the image was copied over into the post/page (and therefore will NOT be refreshed with the new image/alt-text from the media library).
Any updated image title/alt-text in the media library will only appear on posts/pages when the image is inserted into the post/page AFTER the title/alt-text was updated in the media library.
Thank you, for this wonderful piece of code! You saved my endless search for a solution!
Very elegant solution. The cost/benefit of this is off the chart.
Thanks for this! Helped me to upload bulk of images to wordpress/SEO.
Thank you for this!! I was trying to find a way to do this without adding another bloated plugin. You saved the day.
As an SEO consultant, I’ve been struggling with this for years. I can’t tell you how many images I’ve uploaded and had to manually update, it’s in the 10’s of thousands for sure. If I had this solution 5 years ago I would have saved myself hundreds of hours. You are a life saver for sure and my work just got a lot easier so I can spend more time on research.
I was looking for this for ages. You saved me tons of time! Thanks!
Hi,
Thank you for this great code.
Could you please confirm that, if I simply need to Set the image Alt-Text (without having to Sanitize the title etc), I would have to comment the following lines and keep all the rest of the code the same:
// Sanitize the title: remove hyphens, underscores & extra spaces:
// $my_image_title = preg_replace( ‘%\s*[-_\s]+\s*%’, ‘ ‘, $my_image_title );
// Sanitize the title: capitalize first letter of every word (other letters lower case):
// $my_image_title = ucwords( strtolower( $my_image_title ) );
Thanks!
Hello – yes, you are correct, simply comment out the lines you indicate and that will prevent the file Title from being sanitized, so the original file Title (of your uploaded files) will be used without any changes for the image Title, Caption, Description and Alt-Text. If in addition you do not want to set the image image Title, Caption or Description, then you should also comment out lines 22, 23, 24 respectively. The result will be that only the Alt-Text (and nothing else) will be set to the original file name.
Hello,
Can you please give me the complete PHP code in case only the Alt-Text (and not TitleTag, Caption, Description) has to get the original file name. I tried leaving out the lines 22,23,24 but the Title field of the image keeps getting the filename.
Thnx, in advance
Regards,
Luke
Hello – remember that the code above is an override, meaning that if you leave out lines 22, 23, 24 then the overrides will not occur and WordPress will do what it normally does (e.g. it will set the image title to be the original file name). So, if you’d like the file name to be blank, then you could set it explicitly to an empty string (e.g. “”), for example on line 22 above you could set: ‘post_title’ => “”, and on lines 23 and 24 you could also set those to ‘post_excerpt’ => “”, and ‘post_content’ => “”, to make the caption and description be blank. I hope that helps.
HI,
Great post and very informative.
I have a quick question.
What line of PHP code would I add if I wanted to remove any numbers from the file name?
Many Thanks
Hello – you could insert the following lines of code at line #14 (i.e. right after the “preg_replace” line that removes hyphens, underscores & extra spaces):
// Sanitize the title: remove all number characters 0 – 9:
$my_image_title = preg_replace( ‘%[0-9]+%’, ”, $my_image_title );
I hope that helps.
Thank you so much Francisco. I was getting really annoyed at the time I spent stripping out hyphens and copy/pasting from title to alt… and there you were only a Google search away. I owe you!
Great Article, How Can rename the main Media file to the post slug?
This looks incredibly helpful–thank you!
Can I override the PHP code when I want a different title, alt, etc, on a specific image? I assume by going in and manually entering the words/phrases I want for just that image?
Hello – yes, if you want a specific title, alt-text or description on a particular image you can always go in to the WP Media Library and edit the specific image you’d like to change. However, remember that you will need to edit/save the image BEFORE you insert it into a post or page. This is because WP copies the image title, alt-text, caption into the post. So if you have already added the image to a post/page, and then you edit the image in the Media Library, the changes won’t appear in that post/page, it will only appear in any subsequent post/page you add the image to later on.
I tried this code and it worked fine with 1 exception, the Alt, Title, Caption and Description all contained the file extension. For example, if the file name was file_name.jpg I end up with “File Name.jpg”
Is there a way to strip all file extensions (.png, .jpg, .gif, etc..)
Hello – the code above should do exactly as you request, we have it running on several sites and it does not append the file extension on any of them. For example, if you do an “inspect element” on any image on this site, you’ll see the alt-text appears without any file extension. Could there be something happening in your particular theme that is overriding the code above?
Thank you for the quick response. I’ve tracked it down to it being an issue with a data import. If I manually add the image through the Media Manager it works fine. The issue is caused when using Woocommerce’s product import.
I’m not sure if there is anything you can do about that or if you have some insight as to why this would be different but thought I’d at least let you know.
Thanks for finding the root of the issue with WooCommerce. I’ve used Woo on several sites, but not enough to run into the problem you’re experiencing. It seems however that Woo might be overriding the file name somehow, which makes me wonder, perhaps Woo is hooking into the same hook at the code above but with a higher priority? The “add_action” line above doesn’t specify a priority so it will end up as the default, but perhaps by adding a high priority to it may force it to take precedence over Woo?
This is ace. Thanks for putting this together and sharing ;-)
Oh! Any idea how you would do this for already uploaded images, i.e. a batch process? You could then use in conjunction with say, the SEO Friendly Images plugin to alter the code of each post to match the new alt tag info? Just wondering… ;-)
I think this is what I was looking for but haven’t tried it yet: https://wordpress.org/plugins/auto-image-attributes-from-filename-with-bulk-updater/
That is an interesting plugin, it may help to achieve what you’re looking for, so I would certainly give it a try.
Hi – yes, regarding previously uploaded images, you are running into a problem that is pretty well established with WordPress, in that the Alt-Text is actually copied into the post, rather than referenced back to the image (please see an earlier reply I posted above about a similar question another person had). So since the image’s alt-text is copied into the post, any changes you make to the image alt-text afterwards won’t make it into the post… unfortunately, I don’t know of any “global update” plugins that would update all posts that contain the image and update them with the latest alt-text from the image.
Yo this code is great ! I ended up commenting the description and caption, leaving just the title and alt tags… Thanks again for this.
Is it only me, or is this code only working when you upload directly to the media library? I have found that it doesn’t insert the alt tag when uploading an image when selecting an image element and uploading through that in Avada Fusion Builder/Beaver Builder/Visual Composer and also plugins like slider revolution.
Francisco, could you be so kind to confirm?
Hello – The code will only work if you upload images directly into the WordPress Media Library (i.e. hitting the Upload button in the media library). It will work whether you upload one image or several images at a time.
Also, please note that the code assumes you are uploading images into the media library FIRST, and THEN inserting the images into a post (or page, or gallery, etc.) If you upload images directly into a post/page, it will not work, because in that case you will insert the image into the post before it was added to the media library, and thus before this code is executed (because the code is hooked to the “add_attachment” hook).
Remember that when you insert any image into a post, WordPress is effectively COPYING the alt-text from the image’s media library record into the post. So if you later update the alt-text of the image in the media library, the post(s) that include that image will NOT have their alt-text updated.
I hope this helps.
Such a Time Saver !!!! Thank you so much!
This is working great!
How would you append the site title to the end of the alt tag then? Something like:
“image-file-name.jpg” converts to:
Image File Name | SiteTitle.com
Hello, I’m glad this code is helpful to you. Regarding appending the site title to the alt-tag, perhaps the following would work:
ON LINE #28 ABOVE:
update_post_meta( $post_ID, ‘_wp_attachment_image_alt’, $my_image_title && ‘ | ‘ && get_bloginfo( ‘name’ ) );
I am not sure if your code previously worked, but it does not any longer. Instead, I managed to get this working:
update_post_meta( $post_ID, ‘_wp_attachment_image_alt’, $my_image_title . ‘ | ‘ . get_bloginfo( ‘name’ ) );
Hello – the code definitely still works, in fact it is running on this site and several other sites I manage, which are all running the very latest versions of WordPress, Genesis and plugins. By the way, the code you suggest is identical to that indicated on line #28 above except your code simply appends additional information to the title, specifically: . ‘ | ‘ . get_bloginfo( ‘name’ ). Incidentally, you may consider putting that additional information on the WordPress post title (i.e. which you can specify in the Genesis / SEO Settings admin page) rather than on the image title itself. Hope that helps.
Muchas Gracias!!!!!
De nada – espero que sea útil!
Thank you Francisco, this is exactly what I was looking for.
It only took me a few minutes to modify this code to add a text string prior to or after the ALT Tag ($my_image_title).
I did this by modifying the code on line 28
ORIGINAL CODE (LINE 27/28)
// Set the image Alt-Text
update_post_meta( $post_ID, ‘_wp_attachment_image_alt’, $my_image_title );
ADD A TEXT STRING PRIOR TO $my_image_title
update_post_meta( $post_ID, ‘_wp_attachment_image_alt’, ‘Your Text String – ‘.$my_image_title );
RESULT
File Name = your_image.jpg
ALT Text = Your Text String – Your Image
ADD A TEXT STRING AFTER $my_image_title
update_post_meta( $post_ID, ‘_wp_attachment_image_alt’, $my_image_title.’ – Your Text String’. );
RESULT
File Name = your_image.jpg
ALT Text = Your Image – Your Text String
A big thank you to Andrei (Comment Reply on 25th October 2018) for giving me the starting point to modify this code.
David – I’m glad the code helps you, cheers!
I’m new to wordpress having just set up a site for a camera club we have recently started. I really want to implement this code so that images in our gallery can display the photographers name underneath.
The problem is that I have no idea how or where to place this piece of code!
Is there a guide somewhere as to how to use this code in a wordpress installation? Do I have to insert it into an existing file somewhere, or perhaps save it as an addin, and then install it?
thanks
Guy
Hello Guy – to implement the code, you will simply need to include it in your theme’s functions.php file. There are many ways to achieve that, google for “WordPress edit functions.php” and you should see a variety of tutorials, hopefully one will work for you. If you’re still having trouble, please feel free to contact me and I’d be glad to help. Cheers.
This is great. Thank you!
John – very glad to hear the code helps you, best regards.
Hello Francisco, this code is very useful, thanks a lot !
I would however recommend a small improvement, and maybe you can help me with that.
Some pictures may have some characters in the informations that, when added, may break sitemap.xml entries when that sitemap includes pictures.
Could it please be possible to delete some characters at the upload process?
For instance try with this picture :
https://www.syfy.com/sites/syfy/files/styles/1140×640/public/2017/08/stephen_king.jpg?timestamp=1502737529
it includes the following informations :
Stephen King signs the copies of his book ‘Rivival’ at Barnes & Noble Union Square in New York City on November 11, 2014.
and the ‘ will be breaking it.
I would also add :
‘ ” « »
There was also this picture which contains “line breaks” in the code, and it was breaking it : https://i0.wp.com/www.cinefilos.it/wp-content/uploads/2018/04/Pet-Sematary.jpg?fit=1000%2C563&ssl=1
How would you update your code to clean those infos?
Thanks !
I think the issue is happening because you are uploading images that have a Title metadata field embedded in them. When a Title metadata field exists, WordPress takes that Title metadata and uses it for the media title, thereby overriding the file name. The code above assumes that the file name will be used, not the Title metadata within the file.
The issue you are experiencing will arise because the metadata field can contain characters that file names typically don’t allow, e.g. newline characters, quotes, etc. So the solution is to expand the filtering to also filter out such characters.
For a solution, try the following suggestion. The comments in the updated code below explain what is happening. Newline characters will be filtered out because they are white space.
REPLACE THESE ORIGINAL LINES OF CODE (lines #12-13 above):
// Sanitize the title: remove hyphens, underscores & extra spaces:
$my_image_title = preg_replace( ‘%\s*[-_\s]+\s*%’, ‘ ‘, $my_image_title );
WITH THE FOLLOWING UPDATED CODE:
// Sanitize the title: remove hyphens, underscores, white spaces, non-alphanumerics
// First, replace all non-alphanumeric characters with a single blank
// Then, replace all white-space characters with a single blank
$my_image_title = preg_replace( ‘%[^0-9a-z]+%i’, ‘ ‘, $my_image_title );
$my_image_title = preg_replace( ‘%[\s]+%’, ‘ ‘, $my_image_title );
I hope this helps, best regards.
Totally awesome bit of code. As a non-tech person I was wondering if it were at all possible to only capitilise the first word?
I worked it out. replace ucwords with ucfirst.
Thank you so much for that code snippet, I am uploading images remotely using WordPressPCL on my site and that was a SEO issue, because couldn’t fill those fields.
Thank you!
Thanks u very much!
Glad the script works for you, cheers!
Thank you for sharing great tutorial !!! That’s what I needed. Lana :)
hi
great code
just i want replace h1 tag in alt image
The code works well. Thanks for sharing.
Glad to hear the code works for you, cheers.
Works like a charm! Is possible to set the “current post title” instead?
worked well on my site thanks
Thank you ! :-)
Thanks :-)
This will be a standard part of my childtheme from now on!
(I had to modify the script a little bit because I want the “image title” to be empty)
You should make this to a plugin with the option to choose/manage if you want each meta to be generated automatically or left empty.
Thanks again
Lars, Copenhagen
Fantastic code, thank you so much! What a time saver!
Hello, great addition that I should implement for my next WP website.
Thank you for sharing
I bookmarked this page since about 3 to 4 years now. Still very useful more than using a plugin. Thanks for sharing.
Thank you for the tip.
It took me some time to realize that it’s using the file name instead of the real post title.
In my case I’m using it in a Woocommerce and the goal was to add to the image “Alt” the available product title. With this very little modification it’s using the product (works also for blogs) and the fallback variant is the image title as in your original script:
$parentPost = get_post( $post_ID )->post_parent;
if ($parentPost)
$my_image_title = get_post( $parentPost )->post_title;
else
$my_image_title = get_post( $post_ID )->post_title;
This saves so much time, is awesome, thanks.