Search code examples
phpwordpresswoocommerceproductshortcode

Add a div at top of WooCommerce shortcode output


I have a WooCommerce product list generated by the [products category='tshirts'] shortcode.

I would like to add a div to the top of the list, so it looks like this:

<div class='woocommerce'>
   <ul class='products'>
       <div class='test'>Hello</div> //This is the div I would like to add
       <li class='product'></li>
       <li class='product'></li>
       <li class='product'></li>
       ...

I have tried the following but it is still not working:

function action_woocommerce_shop_loop( $array, $int ) { 
    echo "<div class='test'>Hello</div>";
}; 
add_action( 'woocommerce_shop_loop', 'action_woocommerce_shop_loop', 10, 2 ); 

Any help would be appreciated!


Solution

  • Several options are possible:

    1. Re-write the woocommerce_product_loop_start function which is pluggable

    function woocommerce_product_loop_start( $echo = true ) {
        ob_start();
    
        wc_set_loop_prop( 'loop', 0 );
    
        wc_get_template( 'loop/loop-start.php' );
        
        // Loop prop name = products
        if ( wc_get_loop_prop('name') == 'products' ) {
            echo '<div class="test">Hello</div>';
        }
    
        $loop_start = apply_filters( 'woocommerce_product_loop_start', ob_get_clean() );
    
        if ( $echo ) {      
            // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
            echo $loop_start;
        } else {
            return $loop_start;
        }
    }
    


    2. Overwrite the loop/loop-start.php template file. This template can be overridden by copying it to yourtheme/woocommerce/loop/loop-start.php

    Replace

    if ( ! defined( 'ABSPATH' ) ) {
        exit;
    }
    ?>
    <ul class="products columns-<?php echo esc_attr( wc_get_loop_prop( 'columns' ) ); ?>">
    

    With

    if ( ! defined( 'ABSPATH' ) ) {
        exit;
    }
    ?>
    <ul class="products columns-<?php echo esc_attr( wc_get_loop_prop( 'columns' ) ); ?>">
    <?php
    // Loop prop name = products
    if ( wc_get_loop_prop('name') == 'products' ) {
        echo '<div class="test">Hello</div>';
    }
    ?>
    


    3. Via do_action( "woocommerce_shortcode_before_{$this->type}_loop", $this->attributes );

    function action_woocommerce_shortcode_before_products_loop( $atts ) {   
        echo "<div class='test'>Hello</div>";
    }
    add_action( 'woocommerce_shortcode_before_products_loop', 'action_woocommerce_shortcode_before_products_loop', 10, 1 );
    

    Result: (However, this is not quite what you are looking for)

    <div class='woocommerce'>
       <div class='test'>Hello</div> //This is the div I would like to add
       <ul class='products'>
           <li class='product'></li>
           <li class='product'></li>