How to Use Image Uploader in WordPress Admin Area
In this tutorial I am going to dive deep in WordPress media uploader functionality. By the way it is possible to implement not for only images but for any supported file types.
This is how it looks in WordPress admin area:

The HTML part
In this very first part of the tutorial we begin with creating media upload buttons with HTML and a little bit of PHP.
The main question is how are you going to store the image field value in database. There are two options – image ID and image URL. I usually prefer to use the first one.
<?php if( $image = wp_get_attachment_image_url( $image_id, 'medium' ) ) : ?>
<a href="#" class="rudr-upload">
<img src="<?php echo esc_url( $image ) ?>" />
</a>
<a href="#" class="rudr-remove">Remove image</a>
<input type="hidden" name="rudr_img" value="<?php echo absint( $image_id ) ?>">
<?php else : ?>
<a href="#" class="button rudr-upload">Upload image</a>
<a href="#" class="rudr-remove" style="display:none">Remove image</a>
<input type="hidden" name="rudr_img" value="">
<?php endif; ?>
Here we have:
- We are going to use
wp_get_attachment_image_url()
to get the image URL. The function also returnsfalse
if there is no image with this specific ID. - How to get
$image_id
? It depends on how are you going to use the image uploader. For example if you’re using it in settings pages, functionget_option()
should be ok for you. - The second parameter of the function
medium
is the image size we are going to display. By default it isthumbnail
. - Never forget to escape the data, I used functions
esc_url()
andabsint()
for that.
The JavaScript part
Or to be exact – jQuery. Actually there is no reason to use vanilla JavaScript because jQuery is included in WordPress admin anyway.
jQuery( function($){
// on upload button click
$( 'body' ).on( 'click', '.rudr-upload', function( event ){
event.preventDefault(); // prevent default link click and page refresh
const button = $(this)
const imageId = button.next().next().val();
const customUploader = wp.media({
title: 'Insert image', // modal window title
library : {
// uploadedTo : wp.media.view.settings.post.id, // attach to the current post?
type : 'image'
},
button: {
text: 'Use this image' // button label text
},
multiple: false
}).on( 'select', function() { // it also has "open" and "close" events
const attachment = customUploader.state().get( 'selection' ).first().toJSON();
button.removeClass( 'button' ).html( '<img src="' + attachment.url + '">'); // add image instead of "Upload Image"
button.next().show(); // show "Remove image" link
button.next().next().val( attachment.id ); // Populate the hidden field with image ID
})
// already selected images
customUploader.on( 'open', function() {
if( imageId ) {
const selection = customUploader.state().get( 'selection' )
attachment = wp.media.attachment( imageId );
attachment.fetch();
selection.add( attachment ? [attachment] : [] );
}
})
customUploader.open()
});
// on remove button click
$( 'body' ).on( 'click', '.rudr-remove', function( event ){
event.preventDefault();
const button = $(this);
button.next().val( '' ); // emptying the hidden field
button.hide().prev().addClass( 'button' ).html( 'Upload image' ); // replace the image with text
});
});
Where to insert the code? I recommend you to create an empty .js file and add it there, we are going to enqueue it in the next step. Or you can also add it to admin_footer
action hook.
And Finally, Enqueueing Scripts
One last step, we have to include two scripts:
- Our custom .js file from the previous step, let’s call it
misha-uploader.js
, - WordPress media uploader scripts, so we can actually use this modal media uploader.
Can be easily done with admin_enqueue_scripts
action hook.
add_action( 'admin_enqueue_scripts', 'rudr_include_js' );
function rudr_include_js() {
// I recommend to add additional conditions here
// because we probably do not need the scripts on every admin page, right?
// WordPress media uploader scripts
if ( ! did_action( 'wp_enqueue_media' ) ) {
wp_enqueue_media();
}
// our custom JS
wp_enqueue_script(
'mishaupload',
get_stylesheet_directory_uri() . '/misha-uploader.js',
array( 'jquery' )
);
}
Creating Settings Page with Image Upload Field
In the beginning of this tutorial I told you that I will describe how create a settings page like this:

It is actually super-simple and can be done with two easy steps:
- Install and activate my Simple Fields plugin on your website.
- Insert the following code to your current theme
functions.php
file:
add_filter( 'simple_register_option_pages', 'misha_option_page' );
function misha_option_page( $option_pages ) {
$option_pages[] = array(
'id' => 'misha_settings',
'title' => 'My Page Settings',
'menu_name' => 'My page',
'fields' => array(
array(
'id' => 'my_field',
'label' => 'Text Field',
'type' => 'text',
),
array(
'id' => 'my_checkbox',
'label' => 'Checkbox',
'type' => 'checkbox',
'short_description' => 'Yes, absolutely'
),
array(
'id' => 'my_image',
'label' => 'Image',
'type' => 'image',
)
),
);
return $option_pages;
}
That’s pretty much it!
Oh and yes, now you can get the image field values with get_option()
function, like this:
$image_id = get_option( 'my_image' );
$image_url = wp_get_attachment_image_url( $image_id, 'medium' );

Misha Rudrastyh
Hey guys and welcome to my website. For more than 10 years I've been doing my best to share with you some superb WordPress guides and tips for free.
Need some developer help? Contact me
Hi, it’s possible upload multiple image and save an array in a metadata field, like the most popular real estate site?
Hi, sure, I recommend you to check this tut for more details.
Hello Misha, thanks for your answer.
We’re using your scripts to manage the image gallery of a site of a real estate agency.
hey, using this method, do the images get attached to a post? via a meta box….
Not just an id in the post meta, but actually get attached to the post.
Hi Eric,
Please let me know if it works for you.
i use it in my plugin . when i click on Upload image button it not works. Js file enqueued corectly. but not works. Help me
Are there any errors in your browser console?
i get warnning : “Loading failed for the <script> with source http://localhost/batteripunkten/wp-content/themes/batteripunkten/customscript.js.” But use your code to enqueue the js
thanks Misha. actually i have a mistake. you used enqueue path of theme folder. so i used plugin folder and it works fine.
Now you please help me a little that for the
second_featured_img
meta key what function i use to get this attachment’surl
or image object to use it in any template.The attachment ID is stored in post meta. So, you can use
get_post_meta()
to get attachment ID.After that any attachment function can help you –
wp_get_attachment_url()
orwp_get_attachment_image_src()
.thanks misha.
It works fine for single image upload. but for multiple image upload it stores only the first attachment id as meta key value, not any array of ids. how i store multiple ids in wp_post_meta table
I didn’t make it work for multiple uploads yet. Sorry. But you can check this tut for more details.
Then why you give the code in js for multiple upload?
When I published this post, it worked, but now – it doesn’t. I suppose it just requires some small refinements.
Thanks Misha a lot.
Actually I made multiple images uploader for image gallery purpose upgrading your code.it works very fine in latest version of wordpress and its credit goes to you.
Ok, great!
I’m glad you’ve figured it out.
hi misha i have error in your script please help
my images cant loading after adding your script
Hi Nazim,
it is not enough information for me to help you.
Hi,
Nice Tutorial post but it’s for just single image upload. In post you have not mention how to display uploaded image on theme pages.
Please write about how to upload multiple images dynamically as you shown in first image of client site.
That would be great.
Waiting for your updated guided post.
Thanks
Hi,
It is done.
Hi Misha,
Thank you for this tutorial.. it is very useful. i have tried this a lot.. thanks it works successfully..
hi,
This is very helpful tutorial. Thanks a lot, I have a request to you can you please upload any video tutorial for multiple images upload.
Hi,
I will.
How show ? in front page ?
I do not recommend to use this uploader outside the admin area. Or do you mean the dashboard?
Hi
Thank you for sharing your knowledge with us all . I am very grateful. I would like to add this to the woo-commerce products quick edit as well . Is this possible?
Thank you
Andwit
Hi,
Yes, sure, here is the tutorial. 🙃
nice tutorial, but after uploading the image how to use this image on frontend?
Thank you!
You can get the image by its ID with
wp_get_attachment_image_src()
function.Many thanks for the reply. Can you please demonstrate an example. Say I want to use the image in header.php file.
Sure,
Thanks ! IT was very useful
When I click on the update button, it creates infinite entries in the database
It shouldn’t. You’re doing something wrong.
Hi dear Misha
How can i use this code for video?
Hi Hossein,
Hmmm.. not sure how to describe it shortly. First of all you have to use
wp_get_attachment_url()
instead ofwp_get_attachment_image_src()
in Step 3.3.Thanks Misha
I use your code for video by some minor changes and it worked correctly.
Thanks!
Thank you very much helped me a lot
Clear and concise
Hi Misha,
I found one typo for the variable customUploader.
Please use one variable either customUploader or custom_uploader.
Due to this, the image media frame is not opening and got an error in the console.
Thanks!
Hi Bhavin,
Thank you very much for noticing it! It is fixed now 👌
Hello Misha, This is a great tutorial. I am currently working on it to allow the images that have already been selected to show in the uploader. I am adapting your work from the single uploader. Trouble is that the array of images just expands with the preselected rather than replacing them. How can I ammend this? Also please could you share the wonderful css that displays the images in a line with the blue cross in the upper right hand corner?
Hello Ed,
You can find the tutorial for multiple images here.
The CSS you can find in my plugin ;)