How to customize Woocommerce Single Product Page | 14 Useful Hacks
September 4, 2024
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.
WpCodeBox is my favorite code snippets manager for WordPress. This is a premium plugin and if you’re interested, then grab WPCodeBox with a nice 20% discount here (SAVE 20% Coupon WPSH20).
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.
So, just grab this code and use it accordingly.
<span role="button" tabindex="0" data-code="// 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 . '
// Add custom field to Woocommerce backend under General tabadd_action( 'woocommerce_product_options_general_product_data', 'wpsh_add_text_field' );functionwpsh_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 valuesadd_action( 'woocommerce_admin_process_product_object', 'wpsh_save_field', 10, 1 );functionwpsh_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 pagesadd_action( 'woocommerce_product_meta_end', 'wpsh_display_on_single_product_page', 10 );functionwpsh_display_on_single_product_page() {global $product;// Is a WC productif ( is_a( $product, 'WC_Product' ) ) {// Get meta $text = $product->get_meta( '_shipping_time' );// NOT emptyif ( !empty ( $text ) ) {echo'<div class="woocommerce-message">Estimated shipping time: '. $text .'</div>'; } }}// Display this custom field on Woocommerce archive pagesadd_action( 'woocommerce_after_shop_loop_item', 'wpsh_display_on_archive_page', 10 );functionwpsh_display_on_archive_page() {global $product;// Is a WC productif ( is_a( $product, 'WC_Product' ) ) {// Get meta $text = $product->get_meta( '_shipping_time' );// NOT emptyif ( !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' );functioncustom_tab( $tabs ) { // Adds the new tab $tabs['form'] =array('title'=>__( 'Send us an enquiry', 'woocommerce' ),'priority'=>30,'callback'=>'custom_tab_content' );return $tabs;}functioncustom_tab_content() {// The new tab contentecho'<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>';echodo_shortcode( '' );}
How to move Woocommerce related products and upsells product in a tab?
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 locationremove_action( 'woocommerce_after_single_product_summary', 'woocommerce_output_related_products', 20);// Create a new custom tabadd_filter( 'woocommerce_product_tabs', 'related_product_tab' );functionrelated_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 tabfunctionrelated_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 locationremove_action( 'woocommerce_after_single_product_summary', 'woocommerce_upsell_display', 15 );// Create a new custom tabadd_filter( 'woocommerce_product_tabs', 'upsells_product_tab' );functionupsells_product_tab( $tabs ) { $tabs['upsells-products'] =array('title'=>__( 'Compatible products', 'woocommerce' ),'priority'=>50,'callback'=>'upsells_tab_content');return $tabs;}// Add upsells inside new tabfunctionupsells_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.
// 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>
add_action( 'woocommerce_single_product_summary', 'scroll_to_product_tab', 21 );functionscroll_to_product_tab() {global $post, $product; // LINK TO SCROLL TO DESC TABif ( $post->post_content ) {echo'<p><a class="jump-to-tab" href="#tab-description">'.__( 'Read more', 'woocommerce' ) .' →</a></p>'; }// LINK TO SCROLL TO ADDITIONAL INFO TABif ( $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 TABif ( 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();vartabhash= $(this).attr("href");vartabli='li.'+tabhash.substring(1);vartabpanel='.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}
How to create a direct link to your product tab?
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.
// 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>
functiondirect_link_to_product_tabs() {if( is_product() ) {?><scripttype="text/javascript">jQuery(document).ready(function($) {if( window.location.hash ) {// Varsvartab=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.
So, in order to make it work like that use this snippet.
<span role="button" tabindex="0" data-code="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 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.
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.
<span role="button" tabindex="0" data-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 ) {
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.
<span role="button" tabindex="0" data-code="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>';
add_action ('woocommerce_share','add_back_product_category_button', 5);functionadd_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 productif(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>';// Outputecho'<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.
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 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.
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.
add_action('woocommerce_after_add_to_cart_button', 'delivery_estimate');functiondelivery_estimate() {date_default_timezone_set('Europe/Tallinn');// if FRI/SAT/SUN delivery will be MONif (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 tomorrowelseif (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 TOMORROWelse { $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' );functionspecific_category_delivery_estimate() {if ( has_term( 'furniture', 'product_cat' ) ) { // Change "furniture" with your own category slugdate_default_timezone_set( 'Europe/Tallinn' ); // if FRI/SAT/SUN delivery will be MONif ( 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 tomorrowelseif ( date( 'H' ) >=16 ) { $del_day =date( "l jS F", strtotime( "tomorrow + 1 day" ) ); $order_by ="tomorrow"; } // if MON/THU before 4PM delivery will be TOMORROWelse { $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' );functionspecific_product_delivery_estimate() {if ( is_single( '426' ) ) {date_default_timezone_set( 'Europe/Tallinn' ); // if FRI/SAT/SUN delivery will be MONif ( 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 tomorrowelseif ( date( 'H' ) >=16 ) { $del_day =date( "l jS F", strtotime( "tomorrow + 1 day" ) ); $order_by ="tomorrow"; } // if MON/THU before 4PM delivery will be TOMORROWelse { $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 );functionenquiry_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">';echodo_shortcode('[your-shortcode-here]');echo'</div>';}add_action( 'woocommerce_single_product_summary', 'enquiry_form_1', 40);functionenquiry_form_1() {?><scripttype="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 );functionenquiry_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">';echodo_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">';echodo_shortcode('');echo'</div>';}}add_action( 'woocommerce_single_product_summary', 'enquiry_form_1', 40);functionenquiry_form_1() {?><scripttype="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.
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.