We have a WooCommerce clothing store and want to create coupons that have certain categories excluded. Our category structure is as follows (simplified):
– Men
– – Shirts
– – Jeans
– – Sale
– Women
– – Shirts
– – Jeans
– – Sale
However when we want to select [Men » Sale] from the Exclude categories dropdown picker in [WooCommerce » Marketing » Coupons » Usage Restriction] the list is flattened:
– Jeans
– Men
– Sale
– Sale
– Shirts
– Shirts
– Women
Now it is not clear which categories are actually the one we want to exclude. Have in min, this is a very simplified structure, in the live environment this is even worse.
I hoped for an apply_filter but the get_terms() apparently does have none in code, see source code on github here » (line #233)
$categories = get_terms('product_cat', 'orderby=name&hide_empty=0');
Since this is not filtered, I don’t see a way to add a parent category to have this as the desired outcome:
- Men
- Men » Jeans
- Men » Shirts
- Men » Sale
- Women
- Women » Jeans
- Women » Shirts
- Women » Sale
Any idea how to get that list now that there is no filter in the code?
For example, this is what we use for a third party plugin that also uses the WooCommerce category terms, but that actually does have a filter on the get_terms and the native WooCommerce code on coupons does not...
Example:
if (!function_exists('yith_wcbep_add_parent_category_name')) {
function yith_wcbep_add_parent_category_name($terms, $args) {
$term_name = '';
$taxonomy = isset($args['taxonomy']) ? $args['taxonomy'] : '';
foreach ($terms as $term_id => $term_name) {
$term = get_term_by('id', $term_id, $taxonomy);
$term_name = isset($term->name) ? $term->name : '';
if (isset($term->parent) && $term->parent > 0) {
$parent = get_term_by('id', $term->parent, $term->taxonomy);
$term_name = $parent->name . ' > ' . $term_name;
$terms[$term_id] = $term_name;
}
}
return $terms;
}
add_filter('yith_plugin_fw_json_search_found_terms', 'yith_wcbep_add_parent_category_name', 10, 2);
}
To solve this issue, what you can do is to clone WooCommerce coupon product categories restrictions section, customizing the categories output as you like *(here I add the parent term name to the category name), removing with JavaScript the related HTML output from the default WooCommerce ones.
So you will get the following:

Here is the hooked function code:
// Prepend the parent term name to the term name output
function prepend_parent_term_name( $term, $sep = ' > ' ) {
if (isset($term->parent) && $term->parent > 0) {
$parent_name = get_term_by('id', $term->parent, $term->taxonomy)->name;
return esc_html( $parent_name ) . $sep . esc_html( $term->name );
} else {
return esc_html( $term->name );
}
}
// Replace WooCommerce Admin Coupon product categories restictions section with a custom one
add_action( 'woocommerce_coupon_options_usage_restriction', 'action_coupon_options_usage_restriction', 10, 2 );
function action_coupon_options_usage_restriction( $coupon_id, $coupon ) {
echo '<div class="options_group">';
// Categories.
?>
<p class="form-field">
<label for="product_categories2"><?php _e( 'Product categories', 'woocommerce' ); ?></label>
<select id="product_categories2" name="product_categories[]" style="width: 50%;" class="wc-enhanced-select" multiple="multiple" data-placeholder="<?php esc_attr_e( 'Any category', 'woocommerce' ); ?>">
<?php
$category_ids = $coupon->get_product_categories( 'edit' );
$categories = get_terms( 'product_cat', 'orderby=name&hide_empty=0' );
if ( $categories ) {
foreach ( $categories as $cat ) {
echo '<option value="' . esc_attr( $cat->term_id ) . '"' . wc_selected( $cat->term_id, $category_ids ) . '>' . prepend_parent_term_name( $cat ) . '</option>';
}
}
?>
</select> <?php echo wc_help_tip( __( 'Product categories that the coupon will be applied to, or that need to be in the cart in order for the "Fixed cart discount" to be applied.', 'woocommerce' ) ); ?>
</p>
<?php // Exclude Categories. ?>
<p class="form-field">
<label for="exclude_product_categories2"><?php _e( 'Exclude categories', 'woocommerce' ); ?></label>
<select id="exclude_product_categories2" name="exclude_product_categories[]" style="width: 50%;" class="wc-enhanced-select" multiple="multiple" data-placeholder="<?php esc_attr_e( 'No categories', 'woocommerce' ); ?>">
<?php
$category_ids = $coupon->get_excluded_product_categories( 'edit' );
$categories = get_terms( 'product_cat', 'orderby=name&hide_empty=0' );
if ( $categories ) {
foreach ( $categories as $cat ) {
echo '<option value="' . esc_attr( $cat->term_id ) . '"' . wc_selected( $cat->term_id, $category_ids ) . '>' . prepend_parent_term_name( $cat ) . '</option>';
}
}
?>
</select>
<?php echo wc_help_tip( __( 'Product categories that the coupon will not be applied to, or that cannot be in the cart in order for the "Fixed cart discount" to be applied.', 'woocommerce' ) ); ?>
</p>
<?php // Removing default product categories restrictions html ?>
<script>
jQuery(function($){
$('#product_categories').parent().parent().remove();
});
</script>
<?php
echo '</div>';
}
Code goes in functions.php file of your active child theme (or active theme). Tested and works.
This was an interesting feature to solve, seems kind of strange Woocommerce doesn't have hierarchy names in the coupons categories.
So I did some digging and found that the only appropriate filter seems to be get_terms, after some trial and error I came up with this.
if (!function_exists('btAddHierarchyNameToCouponsCat')) {
function btAddHierarchyNameToCouponsCat($terms)
{
if (!is_admin()) {
return $terms;
}
global $pagenow;
if ($pagenow !== 'post-new.php' && $pagenow !== 'post.php') {
return $terms;
}
if (
(
!empty($_GET['post_type'])
&& $_GET['post_type'] === 'shop_coupon'
)
|| (
!empty($_GET['post'])
&& get_post_type($_GET['post']) === 'shop_coupon'
&& !empty($_GET['action'])
&& $_GET['action'] === 'edit'
)
) {
foreach ($terms as &$term) {
$term->name = (function ($term) {
$fullName = array_map(function ($ancestorId) {
$ancestor = get_term_by('term_id', $ancestorId, 'product_cat');
return $ancestor->name;
}, array_reverse(get_ancestors($term->term_id, 'product_cat')));
$fullName[] = $term->name;
return implode(' -> ', $fullName);
})($term);
}
return $terms;
}
return $terms;
}
add_filter('get_terms', 'btAddHierarchyNameToCouponsCat');
}
Here is the before.

And here is the after.

The general idea of this filter is to specifically work only when creating or editing a coupon on the dashboard.
Then it updates the category name to contain the whole hierarchy of the categories names.
This might not be perfect but it's a starting point
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With