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>';
}
}
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:
You can insert your current code before or after loop product link:
Before, using woocommerce_before_shop_loop_item
with a priority below 10 like:
add_action('woocommerce_before_shop_loop_item', 'show_brand_before_title', 5);
After, using woocommerce_after_shop_loop_item
with a priority between 5 and 10, like:
add_action('woocommerce_after_shop_loop_item', 'show_brand_before_title', 7);
After add to cart button, using woocommerce_after_shop_loop_item
with a priority greater than 10, like:
add_action('woocommerce_after_shop_loop_item', 'show_brand_before_title', 20);
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.
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>