phphtmlwordpresswoocommerceproduct

Display brand linked terms above product title in WooCommerce shop pages


I am trying to display the brand name above the product title on the shop page. The codes works but it removes the link from the product title so it doesn't link anymore to the single page. I have no idea how this can be edited to work properly. Thanks in advance!

add_action('woocommerce_before_shop_loop_item_title', 'show_brand_before_title', 10);
    function show_brand_before_title() {
        global $product;
        $terms = get_the_terms($product->get_id(), 'product_brand'); // Replace 'product_brand' with the slug of your brand taxonomy
        if ($terms && !is_wp_error($terms)) {
            $brand_list = array();
            foreach ($terms as $term) {
                $brand_list[] = '<a href="' . esc_url(get_term_link($term->term_id, 'product_brand')) . '">' . esc_html($term->name) . '</a>'; // Replace 'product_brand' with the slug of your brand taxonomy
            }
            echo '<div class="product-brand product-brand-shop-page">' . implode(', ', $brand_list) . '</div>';
        }
}

Solution

  • You simply can't add a link (or multiple links) inside a link in HTML, as it creates a conflict that leads to unexpected things like in your case.

    You have multiple choices:

    1) Change displayed location (before or after the product link):

    You can insert your current code before or after loop product link:

    2) Keep the same hook (same location):

    If you want to keep you current location, you need to close the default loop product link before displaing your brand links, and reopen the default loop product link after it.

    Try the following:

    add_action('woocommerce_before_shop_loop_item_title', 'show_brand_before_title', 10);
    function show_brand_before_title() {
        global $product;
    
        $taxonomy = 'product_cat'; // Targeted taxonomy (here woocommerce product brands)
        $terms    = get_the_terms($product->get_id(),$taxonomy); // Get the related product terms
    
        if ( $terms && !is_wp_error($terms) ) {
            $brand_list = array(); // Initialize
    
            foreach ($terms as $term) {
                $brand_list[] = sprintf('<a href="%s">%s</a>', esc_url( get_term_link($term) ), esc_html($term->name) );
            }
    
            if ( $brand_list ) {
                echo '</a>'; // Close product link
    
                printf( '<div class="product-brand product-brand-shop-page">%s</div>', implode(', ', $brand_list) ); // Display linked brands
    
                // Add back (reopen) default product link
                woocommerce_template_loop_product_link_open();
            }
        }
    }
    

    It should work now.


    How to better understand:

    For your information, the content-product.php template source code shows the related default hooks involved and their priorities (location).

    See below an extract:

    ?>
    <li <?php wc_product_class( '', $product ); ?>>
        <?php
        /**
         * Hook: woocommerce_before_shop_loop_item.
         *
         * @hooked woocommerce_template_loop_product_link_open - 10
         */
        do_action( 'woocommerce_before_shop_loop_item' );
    
        /**
         * Hook: woocommerce_before_shop_loop_item_title.
         *
         * @hooked woocommerce_show_product_loop_sale_flash - 10
         * @hooked woocommerce_template_loop_product_thumbnail - 10
         */
        do_action( 'woocommerce_before_shop_loop_item_title' );
    
        /**
         * Hook: woocommerce_shop_loop_item_title.
         *
         * @hooked woocommerce_template_loop_product_title - 10
         */
        do_action( 'woocommerce_shop_loop_item_title' );
    
        /**
         * Hook: woocommerce_after_shop_loop_item_title.
         *
         * @hooked woocommerce_template_loop_rating - 5
         * @hooked woocommerce_template_loop_price - 10
         */
        do_action( 'woocommerce_after_shop_loop_item_title' );
    
        /**
         * Hook: woocommerce_after_shop_loop_item.
         *
         * @hooked woocommerce_template_loop_product_link_close - 5
         * @hooked woocommerce_template_loop_add_to_cart - 10
         */
        do_action( 'woocommerce_after_shop_loop_item' );
        ?>
    </li>
    

    Related: WooCommerce hooks and overriding templates