How to Create Shared WooCommerce Attribute Stock
In this lesson, I would like to discuss how you can set up the WooCommerce attribute stock on your store. For example, you have multiple products with the color “blue” on your WooCommerce store. How to make all those products have the same stock?
Of course, there are multiple ways of achieving that.
For example, you can use the same SKU for these products with my Duplicate SKU Stock Sync plugin (don’t worry that by default, WooCommerce doesn’t allow duplicate SKUs, because my plugin allows you to use that). But in this particular tutorial, we will talk about using another way, specifically, the attribute stock.
Add the Attribute Stock Custom Fields
First of all, we need to decide where we’re going to store the attribute stock quantity. I think the most obvious and easiest way to do that – in the attribute terms of custom fields.
In order to add a custom field to the attribute terms pages, we need to use the following WooCommerce hooks:
pa_color_edit_form_fields– to add the field to the edit attribute term pages,edited_pa_color– to save the field value into the database.
Below is the complete code:
<?php
add_action( 'pa_color_edit_form_fields', 'rudr_attribute_stock_field', 25, 2 );
function rudr_attribute_stock_field( $term ) {
// Stock quantity for "Color" attribute terms in a custom field
$stock_qty = get_term_meta( $term->term_id, '_stock_qty', true );
?>
<tr class="form-field">
<th scope="row" valign="top"><label for="stock_qty">Stock</label></th>
<td>
<input type="number" name="stock_qty" id="stock_qty" value="<?php echo $stock_qty ?>">
</td>
</tr>
<?php
}
add_action( 'edited_pa_color', 'rudr_save_attribute_stock' );
function rudr_save_attribute_stock( $term_id ) {
$stock_qty = isset( $_POST[ 'stock_qty' ] ) ? absint( $_POST[ 'stock_qty' ] ) : '';
update_term_meta( $term_id, '_stock_qty', $stock_qty );
}Pay attention to pa_color, which is a part of both hooks: {$taxonomy}_edit_form_fields and edited_{$taxonomy}. It is a taxonomy name for your attribute; it could be different in your case. The _stock_qty value is just a custom field meta key; you can use anything.
Here is the result:

Now, you can set the WooCommerce attribute stock quantity for any term of the “Color” attribute individually.
Add an Admin Column for the Attribute Stock Quantity
I think it is also a good idea to display the attribute stock quantity in a column.
Kind of like this way:

Can be achieved easily with two hooks: manage_edit-{$taxonomy}_columns and manage_{$taxonomy}_custom_column.
Here is how:
add_filter( 'manage_edit-pa_color_columns', 'rudr_add_stock_column' );
function rudr_add_stock_column( $columns ) {
$columns[ 'stock_qty' ] = 'Stock';
return $columns;
}
add_action( 'manage_pa_color_custom_column', 'rudr_display_column', 10, 3 );
function rudr_display_column( $html, $column_name, $term_id ) {
if( 'stock_qty' === $column_name ) {
$stock_qty = get_term_meta( $term_id, '_stock_qty', true );
if( $stock_qty ) {
$html = "<mark class=\"instock\">In stock</mark> ({$stock_qty})";
} else {
$html = '<mark class="outofstock">Out of stock</mark>';
}
}
return $html;
}
Now our WooCommerce attribute stock for colors is set and ready. But how can we apply it to the products anyway?
Modifying the Stock Quantity on Shop Pages
Now, our goal is “to trick” WooCommerce; we have to make it think that the real stock quantity is stored in the attribute term stock _stock_qty field, but not in the default one in the products’ metadata.
How can we do that?
I assume the correct way is to use the woocommerce_product_get_stock_quantity filter hook.
To be honest, guys, the logic in this part can be quite complicated, for example:
- We need to keep in mind that a product might have multiple attribute terms with the stock management,
- We need to consider having the “Manage stock” checkbox checked or unchecked. In theory, it would be great to ignore the attribute stock when this checkbox is checked and the stock is managed on the individual product level; however, in that case, the hook I mentioned before,
woocommerce_product_get_stock_quantity, will not be triggered. - What about product variations? The logic can be quite different there as well.
In this tutorial, we will work only with simple products, and I consider that our simple products might have only one “Color” attribute.
add_filter( 'woocommerce_product_get_stock_quantity', 'rudr_use_attribute_stock', 25, 2 );
function rudr_use_attribute_stock( $stock_quantity, $product ) {
// no colors are set for this product
if( ! $attribute_name = $product->get_attribute( 'pa_color' ) ) {
return $stock_quantity;
}
// we decided to do it for simple products only (for now)
if( ! $product->is_type( 'simple' ) ) {
return;
}
$attribute_term = get_term_by( 'name', $attribute_name, 'pa_color' );
$attribute_stock = get_term_meta( $attribute_term->term_id, '_stock_qty', true );
if( isset( $attribute_stock ) ) {
$stock_quantity = $attribute_stock;
}
return $stock_quantity;
}After using this code snippet, the modified product stock quantity will be applied pretty much everywhere in your store:
- Product pages,
- Shop and archive pages,
- Cart and Checkout,
- Admin pages (probably you don’t want it here, in that case, add
! is_admin()condition).
If you have any questions or suggestions for this code, please use the comments below.
Update the Attribute Stock After a Product Purchase
You should not forget that when a product is purchased, if it uses the attribute stock, then the stock of that specific attribute should be decreased accordingly.
Probably, the best hooks for this purpose are woocommerce_reduce_order_item_stock and woocommerce_restore_order_item_stock.
add_action( 'woocommerce_reduce_order_item_stock', 'rudr_reduce_stock', 25, 3 );
function rudr_reduce_stock( $item, $change, $order ){
$product = $item->get_product();
if( ! $product->is_type( 'simple' ) ) {
return;
}
$attribute_name = $product->get_attribute( 'pa_color' );
if( ! $attribute = get_term_by( 'name', $attribute_name, 'pa_color' ) ) {
return;
}
$current_stock = get_term_meta( $attribute->term_id, '_stock_qty', true );
if( $current_stock > 0 ) {
$new_stock = max( 0, $current_stock - $change );
update_term_meta( $attribute->term_id, '_stock_qty', $new_stock );
}
}I hardcoded the product attribute taxonomy here as well, which is pa_color.
Misha Rudrastyh
Hey guys and welcome to my website. For more than 15 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