I have a custom taxonomy associated with the WooCommerce product post type, which I have added to the woocommerce_sortable_taxonomies array so they can be ordered in the WordPress admin.

The plugin stores the term order in its own database table wp_woocommerce_termmeta with each row containing a term_id, meta_key (value of order) and meta_value

I use wp_get_object_terms() on the front end of the site to only pull through terms which have products assigned to them. How can I order the terms based on the values stored in the above mentioned table?

WooCommerce hooks into the terms_clauses filter to enable terms to be sorted by this with a call to get_terms() but there doesn't appear to be anyway to filter the wp_get_object_terms() database query.

  • Downvoter, care to explain why?
    – Andy
    Jul 22, 2015 at 9:20

2 Answers 2


I solved this by passing the array of terms into a sorting function. The array is passed by reference so nothing needs to be returned:

function sort_object_terms(&$terms) {
    global $wpdb;

    // First get an array of just the term IDs
    $term_ids = array_map(function($term) {
        return (int)$term->term_id;
    }, $terms);

    // Now get the order value for all the term IDs
    $results = $wpdb->get_results(
        SELECT woocommerce_term_id AS term_id, meta_value AS sort_order
        FROM {$wpdb->woocommerce_termmeta}
        WHERE meta_key = 'order' AND woocommerce_term_id IN ('" . implode("','", $term_ids) . "')

    $term_orders = array();
    foreach($results as $result) {
        $term_orders[ $result->term_id ] = $result->sort_order;

    // Finally, sort the terms by their term order value
    uasort($terms, function($a, $b) use ($term_orders) {
        if($term_orders[ $a->term_id ] === $term_orders[ $b->term_id ]) {
            return 0;

        return ( $term_orders[ $a->term_id ] > $term_orders[ $b->term_id ] ) ? 1 : -1;

You can get the terms and then create an array of term ids which you pass as include parameter to get terms with menu order parameter and woocommerce will handle the rest like this:

$terms = get_the_terms($post->ID, 'product_highlights');
if (!empty($terms) && is_array($terms)) {
    $post_terms = array();
    foreach ($terms as $term) {
        $post_terms[] = $term->term_id;

    $categories = get_terms('product_highlights', array(
        'orderby' => 'name',//required for woocommerce
        'menu_order' => 'asc',//required for woocommerce
        'include' => $post_terms,

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.