When working on a WooCommerce website with many products, there’s almost always a large amount of media attached to them.
This isn’t limited to just the main product images or gallery photos; many stores also include downloadable products, multiple product variations, and even add-ons that allow for galleries for each variation.
Managing all these files in WordPress’s default Media Library can quickly become overwhelming. Without a proper organization system, finding the right image or file can take longer than it should, slowing down updates, product launches, and site maintenance.
In this tutorial, we’ll explore how to handle large media libraries efficiently, including using folders, and best practices to keep your media easy to manage—even as your store continues to grow.
Virtual vs Physical Folders Approach
Before we dive into the process of creating folders, I would like to discuss one core principle at the very beginning, before we start coding anything (yes, there will be a little bit of code below, but don’t worry, the plugin approach will also be here).
So, what is actually the difference between having virtual and physical media folders?
- Virtual folders – you can think of virtual folders just like categories for attachments. Basically, when you work with virtual folders, and you create a folder, you simply create a custom taxonomy term (sometimes, a custom database table is used for this, but I think a custom taxonomy is perfectly fine here).
- Physical folders – physical folders may look a little bit more interesting because they actually mirror actual directories in your
wp-content/uploadsfolder. When you put a media file into a folder from your WordPress admin dashboard, it will be moved to this directory on your server as well, and vice versa.
Probably, at this moment, you might think that having physical folders is super-convenient and really a game-changer, but there is a huge pitfall. In order to develop physical media folders, we need to completely rewrite a whole lot of WordPress/WooCommerce functions (with hooks, of course, but still), which will result in a 99% chance of having issues when:
- A new plugin is installed on your WooCommerce store,
- Any of the plugins gets updated,
- Your current WordPress theme gets updated,
- The WordPress core is updated.
So, basically, the only safe way to use physical folders is to set the constant DISALLOW_FILE_MODS to true in your wp-config.php, and every time you need to update your whole store, you need to test everything from scratch.
It also means that below, I am going to talk about the virtual folders approach only. Let’s jump into it.
Working with Media Library Folders in WooCommerce
As promised, below I will dive into two approaches (both for virtual folders) – we will try to create them completely from scratch using a custom taxonomy, and we will also discuss how to do it with the Simple Media Library Folders plugin.
1. Creating Folders
If you decide to use a programmatic approach, rather than a plugin approach, you will also be required to register a custom taxonomy for attachments first. You can do it easily with the code below; you may use it in your functions.php file, for example, inside the init hook.
register_taxonomy(
'bbloomer_media_folders',
array( 'attachment' ), // here we need to provide a custom post type name for media (attachment)
array(
'hierarchical' => true, // depending whether you want to have child folders
'labels' => array(
'name' => __( 'Folders', 'bbloomer_media_folders' ),
'singular_name' => __( 'Folder', 'bbloomer_media_folders' ),
// ... other labels can be here
),
'show_ui' => true,
'show_admin_column' => true,
'query_var' => true,
'public' => true,
'update_count_callback' => '_update_generic_term_count', // this one is important
)
);
Using a custom update_count_callback parameter is crucial here because, by default, WordPress can not properly calculate counts for taxonomy terms related to attachments. Or, to be more precise, it can do it only for media files attached to posts.
All right, now our custom taxonomy is ready, and we can manage media library folders just like any regular custom taxonomy:

If you decide to use Simple Media Library Folders, then you can create folders straight from the Media > Library page:

2. Moving Media to Folders
The process of moving media to folders will also depend on how the folders are implemented on your WooCommerce store.
If you created folders as a custom taxonomy, in that case, the list of folders (taxonomy terms) will be displayed as familiar checkboxes when you edit a specific attachment. Here is an example:

But things get tricky when you try to edit a media file via the modal window (usually from the “Grid” view). Here we are going to have just a text field for our media folders:

So, as you can see, I simply added a folder slug into this field. If you need to add a media file to multiple folders, you need to provide a list of folder slugs, comma-separated.
However, this UI can be improved with the help of two hooks – attachment_fields_to_edit and wp_ajax_save-attachment-compat, but it is probably a good topic for a separate article.
In case you decide to go forward with the plugin approach, then adding a media file to a folder will look like this:
3. Navigating Between Folders
Ok, previously in this article, we mostly discussed folders in general. I think it is time to talk more about WooCommerce.
By default, WooCommerce has four places in the admin UI where you can select an image:
- When setting a product image,
- When selecting gallery images for a product,
- When selecting an image for product categories,
- Last but not least, when selecting an image for a specific product variation.
Of course, there are a lot of different plugins out there that allow you to add some extra configuration. For example, Simple Variation Swatches for WooCommerce will add an extra field for WooCommerce product attributes where you can set a custom image for it.
In any of the scenarios mentioned above, the standard WordPress media modal window will be used. So, our ultimate goal is to display a filter by a folder in that window, kind of like this:

Or, even better, to display a sidebar with folders.
How can we achieve that? Because, by default, we don’t have such a filter over there.
For the sake of simplicity, let’s start with the “List view”, because just using the restrict_manage_posts WordPress’ standard action hook will suffice here. There is another example of using this action hook on the blog.
add_action( 'restrict_manage_posts', 'bbloomer_filter_by_folder' );
function bbloomer_filter_by_folder() {
global $typenow;
// because we only need to displat this filder in the media library (not for Posts/Pages)
if( 'attachment' === $typenow ) {
$args = array(
'show_option_all' => 'All folders',
'taxonomy' => 'bbloomer_media_folders',
'name' => 'bbloomer_media_folders',
'selected' => ( isset( $_GET[ 'bbloomer_media_folders' ] ) ? $_GET[ 'bbloomer_media_folders' ] : false ),
'hierarchical' => true,
'value_field' => 'slug',
);
wp_dropdown_categories( $args );
}
}
That’s pretty much it. However, don’t forget to change bbloomer_media_folders to your custom taxonomy name you registered for media folders.
However, having the filters added to the “List view” doesn’t allow us to filter media by a folder when we, for example, want to set a product image or a variation image. That’s when JavaScript comes into play, and below you will find ready-to-use JS code that allows you to add the filters not only to the “Grid view” of the Library page, but also to every WordPress media modal.
Here you go:
// we create a new taxonomy filter by extending AttachmentFilters
const BBloomerFolderFilter = wp.media.view.AttachmentFilters.extend({
id: 'bbloomer-folder-filter',
createFilters: function() {
// out future select dropdown list basically
const filters = {}
// we can pass BBloomerFolders via wp_localize_script() here
_.each( BBloomerFolders.folders || {}, function( value, index ) {
// let's add each folder to the filter
filters[ value.term_id ] = {
text: value.name,
props: {
// don't forget to change your custom taxonomy slug here
bbloomer_media_folders: value.slug,
}
}
})
// and don't forget about "All Folders" element (reset the filter)
filters.all = {
text: BBloomerFolders.all_folders_text,
props: {
// don't forget to change your custom taxonomy slug here
bbloomer_media_folders: ''
},
priority: 10
}
this.filters = filters
}
})
// add the current AttachmentsBrowser into a constant
const AttachmentsBrowser = wp.media.view.AttachmentsBrowser;
wp.media.view.AttachmentsBrowser = AttachmentsBrowser.extend({
createToolbar: function() {
AttachmentsBrowser.prototype.createToolbar.call( this )
this.toolbar.set(
'BBloomerFolderFilter',
new BBloomerFolderFilter({
controller: this.controller,
model: this.collection.props,
priority: -75
}).render()
)
}
})
If you decide to proceed with the plugin approach, you will have an option to display the whole sidebar with folders like this one:

If something is not clear from this guide or if you have any questions, feel free to ask in the comments section below.





