How to customize Woocommerce Single Product Page | 14 Useful Hacks

In this video I’m going to show you 14 useful Woocommerce single product page hacks you can use in every store. If you would like to use those snippets here below then just add the ones you need inside your child theme’s functions.php file or better yet, use Code Snippets plugin. This way you’re not going to lose these modifications in case you’re switching your theme.

Also, take a look at the video tutorial here below and then it will probably be a bit easier to understand what is what.

Video: How to use Woocommerce Single Product Page Hacks

How to create and display custom product field?

First, let’s create a new Woocommerce single product custom field and let’s output it in the desired place. The end result will look like the one here below on the screenshot.

Woocommerce Single Product Page Hacks

So, just grab this code and use it accordingly.

// Add custom field to Woocommerce backend under General tab
add_action( 'woocommerce_product_options_general_product_data', 'wpsh_add_text_field' );
function wpsh_add_text_field() {
    woocommerce_wp_text_input( array(
        'id'            => '_shipping_time',
        'label'         => __( 'Shipping info', 'woocommerce' ),
        'description'   => __( 'This is a custom field, you can write here anything you want.', 'woocommerce' ),
        'desc_tip'      => 'true',
        'type'          => 'text'
    ) );
}


// Save custom field values
add_action( 'woocommerce_admin_process_product_object', 'wpsh_save_field', 10, 1 );
function wpsh_save_field( $product ) {
    if ( isset( $_POST['_shipping_time'] ) ) {        
        $product->update_meta_data( '_shipping_time', sanitize_text_field( $_POST['_shipping_time'] ) );
    }
}

// Display this custom field on Woocommerce single product pages
add_action( 'woocommerce_product_meta_end', 'wpsh_display_on_single_product_page', 10 );
function wpsh_display_on_single_product_page() {
    global $product;
    
    // Is a WC product
    if ( is_a( $product, 'WC_Product' ) ) {
        // Get meta
        $text = $product->get_meta( '_shipping_time' );
        // NOT empty
        if ( ! empty ( $text ) ) {
            echo '<div class="woocommerce-message">Estimated shipping time: ' . $text . '</div>';
        }
    }
}
// Display this custom field on Woocommerce archive pages
add_action( 'woocommerce_after_shop_loop_item', 'wpsh_display_on_archive_page', 10 );
function wpsh_display_on_archive_page() {
    global $product;
    // Is a WC product
    if ( is_a( $product, 'WC_Product' ) ) {
        // Get meta
        $text = $product->get_meta( '_shipping_time' );
        // NOT empty
        if ( ! empty ( $text ) ) {
            echo '<div class="custom-text">Estimated shipping time: ' . $text . '</div>';
        }
    }
}

How to create custom tab?

This snippet here below creates new custom Woocommerce single product tab and it contains text and contact form. Just replace the content as you like and you’re good to go.

add_filter( 'woocommerce_product_tabs', 'custom_tab' );
function custom_tab( $tabs ) {	
	// Adds the new tab
	$tabs['form'] = array(
		'title' 	=> __( 'Send us an enquiry', 'woocommerce' ),
		'priority' 	=> 30,
		'callback' 	=> 'custom_tab_content'
	);
	return $tabs;
}
function custom_tab_content() {

	// The new tab content

	echo '<h4>Send us an enquiry</h4>';
	echo '<p>Lorem ipsum dolor sit amet consectetur adipiscing elit ultricies convallis volutpat, placerat proin scelerisque eget velit tellus at nibh risus. </p>';
	echo do_shortcode( '' );
}

It’s easy. If you want to move Woocommerce related products in a tab then use this snippet.

/* Related products IN CUSTOM TAB */

// Remove related products from original location
remove_action( 'woocommerce_after_single_product_summary', 'woocommerce_output_related_products', 20);
 
// Create a new custom tab
add_filter( 'woocommerce_product_tabs', 'related_product_tab' );
 
function related_product_tab( $tabs ) {   
$tabs['related-products'] = array(
   'title'    => __( 'Related products', 'woocommerce' ),
   'priority'    => 50,
   'callback'    => 'related_product_tab_content'
);
   return $tabs;
}
 
// Add related products inside new tab
function related_product_tab_content() {
woocommerce_output_related_products();
}

If you want to move Woocommerce upsell products in a tab then use this snippet.

 /* UPSELLS IN CUSTOM TAB */

// Remove uplsells products from original location
remove_action( 'woocommerce_after_single_product_summary', 'woocommerce_upsell_display', 15 );
 
// Create a new custom tab
 
add_filter( 'woocommerce_product_tabs', 'upsells_product_tab' );
 
function upsells_product_tab( $tabs ) {   
$tabs['upsells-products'] = array(
   'title'    => __( 'Compatible products', 'woocommerce' ),
   'priority'    => 50,
   'callback'    => 'upsells_tab_content'
);
   return $tabs;
}
// Add upsells inside new tab
function upsells_tab_content() {
woocommerce_upsell_display();
}

How to scroll directly to Woocommerce product tab and open it automatically?

This code snippet here below adds links above add to cart button. If you click on the link it will scroll to the product tab and automatically opens it. If you’re using custom tabs then add a new link with the custom tab name.

add_action( 'woocommerce_single_product_summary', 'scroll_to_product_tab', 21 );
  
function scroll_to_product_tab() {
     
    global $post, $product; 
     
    // LINK TO SCROLL TO DESC TAB
    if ( $post->post_content ) {
        echo '<p><a class="jump-to-tab" href="#tab-description">' . __( 'Read more', 'woocommerce' ) . ' →</a></p>';
    }
     
    // LINK TO SCROLL TO ADDITIONAL INFO TAB
    if ( $product && ( $product->has_attributes() || apply_filters( 'wc_product_enable_dimensions_display', $product->has_weight() || $product->has_dimensions() ) ) ) {
        echo '<p><a class="jump-to-tab" href="#tab-additional_information">' . __( 'Additional information', 'woocommerce' ) . ' →</a></p>';
    }
        // LINK TO SCROLL TO REVIEWS TAB
    if ( comments_open() ) {
        echo '<p><a class="jump-to-tab" href="#tab-reviews">' . __( 'Reviews', 'woocommerce' ) . ' →</a></p>';
    }
    ?>
        <script>
        jQuery(document).ready(function($){
            $('a.jump-to-tab').click(function(e){
                e.preventDefault();
                var tabhash = $(this).attr("href");
                var tabli = 'li.' + tabhash.substring(1);
                var tabpanel = '.panel' + tabhash;
                $(".wc-tabs li").each(function() {
                    if ( $(this).hasClass("active") ) {
                        $(this).removeClass("active");
                    }
                });
                $(tabli).addClass("active");
                $(".woocommerce-tabs .panel").css("display","none");
                $(tabpanel).css("display","block");
                $('html,body').animate({scrollTop:$(tabpanel).offset().top -150},'slow'); // Set your offset by changing -150 value
            });
        });
        </script>
    <?php
}

Maybe you need to send a link with the specific product reviews to someone and isntead of sending him/her the product link you can send the link to the review tab itself. So, use this snippet here below and send the link in a form https://yoursite.com&/demo-product/#tab-reviews

If you want to link to some other tab then just replace #tab-reviews with the correct tab link.

function direct_link_to_product_tabs() {
	if( is_product() ) {
	?>
		<script type="text/javascript">
			jQuery(document).ready(function($) {

				if( window.location.hash ) {
					// Vars
					var tab = window.location.hash.replace('#', '');

					// Tabs
					$( 'li.description_tab' ).removeClass( 'active' );
					$( 'a[href="#' + tab + '"]' ).parent( 'li' ).addClass( 'active' );

					// Tabs content
					$( '#tab-description' ).hide();
					$( '#tab-' + tab.replace( 'tab-', '' ) ).show();
				}

				// when the tab is selected update the url with the hash
				$( '.tabs a' ).click( function() { 
window.location.hash = 'tab-' + $(this).parent('li').attr("class").replace(' active', '').replace('_tab', '');
				});

			});
		</script>
	<?php
	}
}
add_action( 'wp_footer', 'direct_link_to_product_tabs', 30 );

How to display “You save” for sale price?

Take a look at the screenshot here below. This is what these snippets are doing for you.

Useful Woocommerce Single Product Page Hacks

So, in order to make it work like that use this snippet.

function you_save_text_for_product() {
	global $product;

	// works for Simple and Variable type
	$regular_price 	= get_post_meta( $product->get_id(), '_regular_price', true ); // 36.32
	$sale_price 	= get_post_meta( $product->get_id(), '_sale_price', true ); // 24.99
		
	if( !empty($sale_price) ) {
	
		$saved_amount 		= $regular_price - $sale_price;
		$currency_symbol 	= get_woocommerce_currency_symbol();

		$percentage = round( ( ( $regular_price - $sale_price ) / $regular_price ) * 100 );
		?>
			<p class="you_save_price">You save: <?php echo $currency_symbol .''. number_format($saved_amount, 2, '.', ''); ?></p>				
		<?php		
	} 
		
}
add_action( 'woocommerce_single_product_summary', 'you_save_text_for_product', 12 ); // hook priority

If you would like to customize the look of it then take a look at the you_save_price CCS class. Now go to Customizer >> Additional CSS and add this small pies of CSS to customize it.

.you_save_price {
	background: #f9f9f9;
	padding: 10px;
	border: 1px dashed #ddd;
	width: 150px;
	font-size: 14px;
	font-weight: 600;
	margin-top: 10px;
}

Now, this code above shows saved amount only for simple products. If you would like to show it also for variable products, then add this piece of code.

// For product variations (on variable products)
add_filter( 'woocommerce_available_variation', 'variable_product_saving_amount', 10, 3 );
function variable_product_saving_amount( $data, $product, $variation ) {

    if( $variation->is_on_sale() ) {
        $saved_amount  = $data['display_regular_price'] - $data['display_price'];
        $percentage    = round( $saved_amount / $data['display_regular_price'] * 100 );

        $data['price_html'] .= '<p id="you_save_price">'. __("You Save") .': ' . wc_price($saved_amount) . ' ('.$percentage.'%)</p>';
    }
    return $data;
}

How to add Back to category button on Woocommerce single product page?

This pieces of code will add Back to category button on Woocommerce single product page under the Meta block.

add_action ('woocommerce_share','add_back_product_category_button', 5);
function add_back_product_category_button(){

    // Get the product categories set in the product
    $terms = wp_get_post_terms( get_the_id(), 'product_cat' );

    // Check that there is at leat one product category set for the product
    if(sizeof($terms) > 0){
        // Get the first product category WP_Term object
        $term = reset($terms);
        // Get the term link (button link)
        $link = get_term_link( $term, 'product_cat' );

        // Button text
        $text = __('← Back to category','woocommerce') . ' <strong>' . $term->name . '</strong>';

        // Output
        echo '<div class="back-to-category"><a href="'.esc_url($link).'" title="'.$text.'" '.$term->slug.'">'.$text.'</a></div>';
    }
}

If you woulkd like to customize this Woocommerce Back to category button then use this piece of CSS code.

.back-to-category {
	margin-top: 1.5em;
	border: 1px solid #ddd;
	border-radius: 50px;
	padding: 7px 20px;
	text-align: center;
	transition: border-color 0.5s ease;
}
.back-to-category:hover {
	border: 1px solid #1e1e1e;
}

How to change Woocommerce add to cart button text if product is in backorder?

I have had customers who are confused about the backorders and they haven’t realized that the product is out of stock and it need to be pre-ordered. Therefore I needed to change Woocommerce add to cart button text for backorder products. Now, if I combine it with the custom field (hack #1 above) then the end result will look like this:

How to change Woocommerce add to cart button text if product is in backorder?

Looks good, isn’t it? So, use this code snippet.

add_filter( 'woocommerce_product_single_add_to_cart_text', 'wc_ninja_change_backorder_button', 10, 2 );
function wc_ninja_change_backorder_button( $text, $product ){
	if ( $product->is_on_backorder( 1 ) ) {
		$text = __( 'Pre-order', 'woocommerce' );
	}
	return $text;
}

add_filter( 'woocommerce_product_add_to_cart_text', 'wc_ninja_change_backorder_button1', 10, 2 );
function wc_ninja_change_backorder_button1( $text, $product ){
    if ( $product->is_on_backorder( 1 ) ) {
        $text = __( 'Pre-order', 'woocommerce' );
    }
    return $text;
  }

How to add NEW badge for the Woocommerce products newer than 30 days?

This snippet here below will add NEW badge for the Woocommerce products that are newer than 30 days. If you want it to be more or less than 30 days then change Newness in days number.

// New badge
add_action( 'woocommerce_single_product_summary', 'new_badge', 5 );
          
function new_badge() {
   global $product;
   $newness_days = 30; // Newness in days 
   $created = strtotime( $product->get_date_created() );
   if ( ( time() - ( 60 * 60 * 24 * $newness_days ) ) < $created ) {
      echo '<span class="itsnew">' . esc_html__( 'NEW', 'woocommerce' ) . '</span>';
   }
}

Now let’s customize this Woocommerce NEW badge. Add this piece of CSS into Additional CSS box.

.itsnew {
	background: #f37b21;
	padding: 5px 10px;
	font-size: 12px;
	font-weight: 700;
	color: #fff;
}

How to add estimated delivery date and time on your Woocommerce single product page?

With the help of this snippet you will be able to add a estimated delivery date and time on your Woocommerce single product page. Take a look at the screenshot here below.

How to add estimated delivery date and time on your Woocommerce single product page?
add_action('woocommerce_after_add_to_cart_button', 'delivery_estimate');

function delivery_estimate() {
    date_default_timezone_set('Europe/Tallinn');

    // if FRI/SAT/SUN delivery will be MON
    if (date('N') >= 5) {
        $del_day = date("l jS F", strtotime("next monday"));
        $order_by = "Monday";
    }

    // if MON/THU after 4PM delivery will be day after tomorrow
    elseif (date('H') >= 16) {
        $del_day = date("l jS F", strtotime("tomorrow + 2 days"));
        $order_by = "day after tomorrow";
    }

    // if MON/THU before 4PM delivery will be TOMORROW
    else {
        $del_day = date("l jS F", strtotime("tomorrow"));
        $order_by = "today";
    }

    $html = "<br><div class='woocommerce-message' style='clear:both'>Order by 4PM {$order_by} for delivery on {$del_day}</div>";

    echo $html;
}

How to show estimated delivery date for specific category?

If you need to show estimated delivery date for specific product category then you need to add two lines of code. So, add this line just below your function name row. Also, you would need to add } sign to the last line.

 if ( has_term( 'furniture', 'product_cat' ) ) { // Change "furniture" with your own category slug

Just replace “furniture” slug with your own product category slug. So, this is the full code that will show estimated delivery date for Furniture category.

add_action( 'woocommerce_after_add_to_cart_form', 'specific_category_delivery_estimate' );
    
function specific_category_delivery_estimate() {
  if ( has_term( 'furniture', 'product_cat' ) ) { // Change "furniture" with your own category slug
   date_default_timezone_set( 'Europe/Tallinn' );  
    
   // if FRI/SAT/SUN delivery will be MON
   if ( date( 'N' ) >= 5 ) {
      $del_day = date( "l jS F", strtotime( "next tuesday" ) );
      $order_by = "Monday";
   } 
    
   // if MON/THU after 4PM delivery will be day after tomorrow
   elseif ( date( 'H' ) >= 16 ) {
      $del_day = date( "l jS F", strtotime( "tomorrow + 1 day" ) );
      $order_by = "tomorrow";
   } 
    
   // if MON/THU before 4PM delivery will be TOMORROW
   else {
      $del_day = date( "2 jS F", strtotime( "tomorrow" ) );
      $order_by = "today";
   }
 
   $html = "<br><div class='woocommerce-message' style='clear:both'>Order by 4PM {$order_by} for delivery on {$del_day}</div>";
    
   echo $html;
}
}

How to show estimated delivery date for specific category or product?

Now, if you need to show this on a specific product page then it works similarly as with the categories byt this time add this row instead and replace “426” with your own product ID.

 if ( is_single( '426' ) ) { // Replace "426" with your own product ID

And the full code for a specific product is this.

add_action( 'woocommerce_after_add_to_cart_form', 'specific_product_delivery_estimate' );
    
function specific_product_delivery_estimate() {
 if ( is_single( '426' ) ) {
   date_default_timezone_set( 'Europe/Tallinn' );  
    
   // if FRI/SAT/SUN delivery will be MON
   if ( date( 'N' ) >= 5 ) {
      $del_day = date( "l jS F", strtotime( "next tuesday" ) );
      $order_by = "Monday";
   } 
    
   // if MON/THU after 4PM delivery will be day after tomorrow
   elseif ( date( 'H' ) >= 16 ) {
      $del_day = date( "l jS F", strtotime( "tomorrow + 1 day" ) );
      $order_by = "tomorrow";
   } 
    
   // if MON/THU before 4PM delivery will be TOMORROW
   else {
      $del_day = date( "2 jS F", strtotime( "tomorrow" ) );
      $order_by = "today";
   }
 
   $html = "<br><div class='woocommerce-message' style='clear:both'>Order by 4PM {$order_by} for delivery on {$del_day}</div>";
    
   echo $html;
}
}

How to add Woocommerce product enquiry form?

This snippet here adds a button under your Add to cart button. If you click on the button then the contact form opens up. Just replace the contact form shortcode inside this snippet (line 6).

add_action( 'woocommerce_single_product_summary', 'enquiry_form', 30 );
function enquiry_form() {

echo '<button type="submit" id="trigger_cf" class="button alt" style="margin-bottom: 20px;">Send us your enquiry</button>';
echo '<div id="product_inq" style="display:none">';
echo do_shortcode('[your-shortcode-here]');
echo '</div>';
}
add_action( 'woocommerce_single_product_summary', 'enquiry_form_1', 40);
function enquiry_form_1() {
  ?>
    <script type="text/javascript">
        jQuery('#trigger_cf').on('click', function(){
        if ( jQuery(this).text() == 'Send us your enquiry' ) {
                    jQuery('#product_inq').css("display","block");
            jQuery("#trigger_cf").html('Close');
        } else {
            jQuery('#product_inq').hide();
            jQuery("#trigger_cf").html('Send us your enquiry');
        }
        });
    </script>
    <?php    
}

You can also use conditionals. For example, for the Clothing category products I’m showing one form and for all other products another form. just replace the category slug inside “clothing” part of the code.

add_action( 'woocommerce_single_product_summary', 'enquiry_form', 30 );
function enquiry_form() {
	if ( has_term( 'clothing', 'product_cat' ) ) {
echo '<button type="submit" id="trigger_cf" class="button alt">Send us your enquiry</button>';
echo '<div id="product_inq" style="display:none">';
echo do_shortcode('');
echo '</div>';
} else {
echo '<button type="submit" id="trigger_cf" class="button alt" style="margin-bottom: 20px;">Send us your enquiry</button>';
echo '<div id="product_inq" style="display:none">';
echo do_shortcode('');
echo '</div>';
}
}
add_action( 'woocommerce_single_product_summary', 'enquiry_form_1', 40);
function enquiry_form_1() {
  ?>
    <script type="text/javascript">
        jQuery('#trigger_cf').on('click', function(){
        if ( jQuery(this).text() == 'Send us your enquiry' ) {
                    jQuery('#product_inq').css("display","block");
            jQuery("#trigger_cf").html('Close');
        } else {
            jQuery('#product_inq').hide();
            jQuery("#trigger_cf").html('Send us your enquiry');
        }
        });
    </script>
    <?php    
}

How to disable (grey out) selection of out-of-stock variation?

For your customers it is much easier to choose only the variations that are available. Therefore, I’ll show you how to disable /grey out) selection of out-of-stock product variations.

add_filter( 'woocommerce_variation_is_active', 'disable_variations_out_of_stock', 10, 2 );
 
function disable_variations_out_of_stock( $is_active, $variation ) {
    if ( ! $variation->is_in_stock() ) return false;
    return $is_active;
}

How to include a product thumbail alongside the name and price of Woocommerce grouped products?

This small piece of code will add a product thumbnail for the Woocommerce product grouped products table. If you wan to change the image size then just modify the 40, 40 part.

add_action( 'woocommerce_grouped_product_list_before_price', 'woocommerce_grouped_product_thumbnail' );

function woocommerce_grouped_product_thumbnail( $product ) {
    $image_size = array( 40, 40 );  // array( width, height ) image size in pixel 
    $attachment_id = get_post_meta( $product->id, '_thumbnail_id', true );
    ?>
    <td class="label">
        <?php echo wp_get_attachment_image( $attachment_id, $image_size ); ?>
    </td>
    <?php
}

How to remove Woocommerce reviews tab?

Also an easy task. Use this snippet here to remove Woocommerce reviews tab.

add_filter( 'woocommerce_product_tabs', 'woo_remove_product_tabs', 98 );

function woo_remove_product_tabs( $tabs ) {
    unset( $tabs['reviews'] ); // Remove the reviews tab
    return $tabs;
}

How to hide Woocommerce product price for out of stock products?

This snippet here below hides Woocommerce product price for out of stock products

add_filter( 'woocommerce_get_price_html', 'wpsh_hide_price', 9999, 2 );
 
function wpsh_hide_price( $price, $product ) {
   if ( is_admin() ) return $price; // BAIL IF BACKEND
   if ( ! $product->is_in_stock() ) {
      $price = apply_filters( 'woocommerce_empty_price_html', '', $product );
   }
   return $price;
}

Do you want more useful Woocommerce tips?

Do you want to thank me and buy me a beer?

Every donation is entirely welcome but NEVER required. Enjoy my work for free but if you would like to thank me and buy me a beer or two then you can use this form here below.

Donation Form (#2)

Here are some of my favorite WordPress tools

Thanks for reading this article! I hope it's been useful as you work on your own websites and e-commerce sites. I wanted to share some tools I use as a WordPress developer, and I think you'll find them helpful too.

Just so you know, these are affiliate links. If you decide to use any of them, I'll earn a commission. This helps me create tutorials and YouTube videos. But honestly, I genuinely use and recommend these tools to my friends and family as well. Your support keeps me creating content that benefits everyone.

Themes: Over the past few years, I've consistently relied on two primary themes for all sorts of projects: the Blocksy theme and the Kadence Theme. If you explore this website and my YouTube channel, you'll come across numerous tutorials that delve into these themes. If you're interested in obtaining a 10% discount for both of these themes, then:

Code Snippets Manager: WPCodeBox allows you to add code snippets to your site. Not only that, but it also provides you with the capability to construct and oversee your WordPress Code Snippets library right in the cloud. You can grab it with the 20% discount here (SAVE 20% Coupon: WPSH20).

Contact forms: There are hundreds of contact forms out there but Fluent Forms is the one I like the most. If you need a 20% discount then use this link (save 20% coupon is WPSH20).

Gutenberg add-ons: If I need a good Gutenberg blocks add-on then Kadence Blocks is the one I have used the most. You’ll get a 10% discount with the coupon SIMPLEHACKS here.

Website migration: While building a website you probably need a good plugin that can help you with the migration, backups, restoration, and staging sites. Well, WpVivid is the one I have used for the last couple of years. If you use this link along with the WPSH20 coupon you’ll get a 20% discount.

Woocommerce extensions: There are a bunch of Woocommerce extensions that I like but the one that stands out is Advanced Dynamic Pricing. Once again, you’ll get a 20% discount if you use this link here (save 20% coupon is WPSH20)

Web Hosting: If you would like to have a really fast and easy-to-use managed cloud hosting, then I recommend Verpex Hosting (see my review here). By the way, this site is hosted in Verpex.)

To see all my most up-to-date recommendations, check out this resource that I made for you!

Janek T.
Janek T.

Improve this text: {CLIPBOARD}

- I have been passionate about Wordpress since 2011, creating websites and sharing valuable tips on using Wordpress and Woocommerce on my site.
- Be the first to receive notifications about new tutorials by subscribing to my Youtube channel .
- Follow me on Twitter here

Articles: 140