I am trying to add save amount total on the sale flash badge using this snippet here below but there is something wrong since it is not working.
Any advice would be really appreciated.
// Add save amount on the sale badge.
add_filter( 'woocommerce_sale_flash', 'woocommerce_custom_badge', 10, 2 );
function woocommerce_custom_badge( $price, $product ) {
$saved = wc_price( $product->regular_price - $product->sale_price );
return $price . sprintf( __(' <div class="savings">Save %s</div>', 'woocommerce' ), $saved );
}
Thanks
Added WC 3+ compatibility
You don't have the correct arguments in your filter ($price doesn't exist for example), see here the related source code for woocommerce_sale_flash filter hook to understand better:
/*
* The filter hook woocommerce_sale_flash is located in:
* templates/loop/sale-flash.php and templates/single-product/sale-flash.php
*/
<?php if ( $product->is_on_sale() ) : ?>
<?php echo apply_filters( 'woocommerce_sale_flash', '<span class="onsale">' . esc_html__( 'Sale!', 'woocommerce' ) . '</span>', $post, $product ); ?>
So your working code is going to be something like:
add_filter( 'woocommerce_sale_flash', 'woocommerce_custom_badge', 10, 3 );
function woocommerce_custom_badge( $output_html, $post, $product ) {
// Added compatibility with WC +3
$regular_price = method_exists( $product, 'get_regular_price' ) ? $product->get_regular_price() : $product->regular_price;
$sale_price = method_exists( $product, 'get_sale_price' ) ? $product->get_sale_price() : $product->sale_price;
$saved_price = wc_price( $regular_price - $sale_price );
$output_html = '<span class="onsale">' . esc_html__( 'Save', 'woocommerce' ) . ' ' . $saved_price . '</span>';
return $output_html;
}
The Code goes in function.php file of your active child theme (or theme) or also in any plugin file.
This code is tested and works.
Related
Looking for a bit of help here, we have simple product in woocommerce and we want to display a you save % and amount on the product page for any discount we offer.
We have it set up for a variable product already but not for a simple product can anyone help with this.
Here is the code we have for the variable product.
add_filter( 'woocommerce_variable_price_html', 'imti_variation_price_format_310', 10, 2 );
function imti_variation_price_format_310( $price, $product ) {
// Getting the clean numeric prices (without html and currency)
$min_var_reg_price = $product->get_variation_regular_price( 'min', true );
$min_var_sale_price = $product->get_variation_sale_price( 'min', true );
$price_diff = $min_var_reg_price - $min_var_sale_price ;
$currency_symbol = get_woocommerce_currency_symbol();
// Percentage calculation and text
$percentage = round( ( $min_var_reg_price - $min_var_sale_price ) / $min_var_reg_price * 100 ).'%';
$percentage_txt = __('<br/><p class="you-save"><small style="color:#d1461c; font-size:12.8px; font-weight:bold;"> You Save '.$percentage. ' (- '.$currency_symbol. ''.$price_diff. ') </small></p>' , 'woocommerce' );
return '<del>' . wc_price( $min_var_reg_price ) . '</del> <ins>' . wc_price( $min_var_sale_price ) . $percentage_txt . '</ins>';
}
Thanks
Jamie
Okay. The easy way it changes your hook to woocommerce_get_price_html. But I want to explain the problem with your solution. I suggest to move in another way. Firstly create a function which works with product independent this is variation product or simple:
function discount_message( $product ) {
$sale_price = 'variable' === $product->get_type()
? $product->get_variation_sale_price( 'min' )
: $product->get_sale_price();
$regular_price = 'variable' === $product->get_type()
? $product->get_variation_regular_price( 'min' )
: $product->get_regular_price();
$discount = round( $sale_price / $regular_price * 100 );
echo '<p class="you-save"><small>';
echo sprintf(
__( 'You Save %1$s (-%2$s)', 'your-domain' ),
absint( $discount ) . '%',
wc_price( absint( $regular_price - $sale_price ) )
);
echo '</small></p>';
}
Then create a function that will separately from product price (or you can also use filter woocommerce_get_price_html but I don't like this idea):
function single_product_discount_message() {
global $product;
discount_message( $product );
}
add_action( 'woocommerce_single_product_summary', 'single_product_discount_message', 9 );
When you will add the single_product_discount_message to hook woocommerce_single_product_summary you can change priority number(9) to another to move this label on your product cart.
I'm trying to change the price for a specific product so that it shows the price with VAT (as opposed to other products where the price is shown without VAT)
I have managed to get this to work with the variable products themselves, by using the following code from https://tomjesch.com/display-woocommerce-products-with-and-without-tax/
function edit_selected_variation_price( $data, $product, $variation ) {
if(is_singular('product') && $product->get_id() == 68719 ) {
$price = $variation->price;
$price_incl_tax = $price + round($price * ( 20 / 100 ), 2);
$price_incl_tax = number_format($price_incl_tax, 2, ",", ".");
$price = number_format($price, 2, ",", ".");
$display_price = '<span class="price">';
$display_price .= '<span class="amount">£ ' . $price_incl_tax .'<small class="woocommerce-price-suffix"> incl VAT</small></span>';
$display_price .= '</span>';
$data['price_html'] = $display_price;
}
return $data;
}
add_filter( 'woocommerce_available_variation', 'edit_selected_variation_price', 10, 3);
This works when an option is chosen. However, before an option is chosen, there is a price that says FROM: £xxx which I now also want to change to say "FROM: £xxx inc VAT"
However, I can't seem to do anything to change it. So I have added the following to setup the html for the price:
function cw_change_product_html( $price_html, $product ) {
if ( $product->get_id() == 68719 ) {
$price_incl_tax = $product->price + round($price * ( 20 / 100 ), 2);
$price_incl_tax = number_format($price_incl_tax, 2, ",", ".");
$price_html = '<span class="amount">From ' . $price_incl_tax . 'incl VAT</span>';
}
echo $price_html;
}
And then I tried using these three different hooks.
add_filter( 'woocommerce_get_price_html_from_to', 'cw_change_product_html', 10, 2 );
add_filter( 'woocommerce_get_price_html', 'cw_change_product_html', 10, 2 );
add_filter('woocommerce_variable_price_html', 'cw_change_product_html', 10, 2);
Only the second one seems to trigger the code but then it outputs all of the prices for all the different variants.
Do I need to use a different hook or is there a way I can run the above code once?
There are some mistakes in your code. woocommerce_variable_price_html is best hook to be used. Also instead of using custom tax calculations, you can use WC_Tax methods to get dynamically the tax amount. Finally wc_price() is the formatted price function to be used in WooCommerce.
The code:
add_filter( 'woocommerce_variable_price_html', 'filter_wc_variable_price_html', 10, 2 );
function filter_wc_variable_price_html( $price_html, $product ) {
// only for variable product 68719
if( $product->get_id() != 68719 )
return $price_html;
$min_price = $product->get_variation_price( 'min' );
$tax_rates = WC_Tax::get_rates( $product->get_tax_class() );
$taxes = WC_Tax::calc_tax( $min_price, $tax_rates, false );
return sprintf(
__( 'From %s %s', 'woocommerce' ),
wc_price( $min_price + array_sum( $taxes ) ),
'<small class="woocommerce-price-suffix">' . __( 'incl VAT', 'woocommerce' ) . '</small>'
);
}
As your other code is a bit outdated and complicated, you can try the following instead:
add_filter( 'woocommerce_available_variation', 'filter_wc_available_variation_price_html', 10, 3);
function filter_wc_available_variation_price_html( $data, $product, $variation ) {
// only for variable product 68719
if( $product->get_id() != 68719 )
return $data;
$price = $data['display_price'];
$tax_rates = WC_Tax::get_rates( $variation->get_tax_class() );
$taxes = WC_Tax::calc_tax( $price, $tax_rates, false );
$data['price_html'] = sprintf( '%s %s',
wc_price( $price + array_sum( $taxes ) ),
'<small class="woocommerce-price-suffix">' . __( 'incl VAT', 'woocommerce' ) . '</small>'
);
return $data;
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.
You are calling the right hook (woocommerce_get_price_html) but there are several flaws in your code.
Lets address your problem of running the code only for the price display at the top. Make sure the id you are checking for is the parent id.
Don't access values of the product object directly. WooCommerce provides getter functions for a lot of data. So instead use $product->get_price().
You have an undefined variable $price which will crash your code.
You can retrieve the tax percentage of the parent product, instead of hard coding it into the calculation in your function.
You can use the wc_price() function to output a formatted price.
The final code should look something like this:
add_filter( 'woocommerce_get_price_html', 'cw_change_product_html', 10, 2 );
function cw_change_product_html( $price_html, $product ) {
if ( $product->get_id() == 68719 ) {
$tax_rates = WC_Tax::get_rates( $product->get_tax_class() );
//Check the product tax rate of parent
if ( !empty( $tax_rates ) ) {
$tax_rate = reset($tax_rates);
$price_incl_tax = $product->get_price() + ( $product->get_price() * $tax_rate['rate'] / 100 );
$price_html = sprintf( 'From %s incl VAT', wc_price( $price_incl_tax, array( 'currency' => get_woocommerce_currency() ) ) );
}
}
return $price_html;
}
So i have products at the store that have was now and save prices with custom html.
Now i need to change product price without those attributes, that have only single price(regular price).
Problem is they have the same class and for some reason when i change html only the was-now-save class get's changed but the product with regular price do not.
add_filter( 'woocommerce_get_price_html', 'bbloomer_simple_product_price_format', 10, 2 );
function bbloomer_simple_product_price_format( $price, $product ) {
$str = "Ušteda:";
if ( $product->is_on_sale() && $product->is_type('simple') ) {
$price = sprintf( __( '<div class="was-now-save"><ul>
<li>
<div class="was">
<span class="text">MP cena:</span>%1$s</div>
</li><li><div class="save"><span class="text">' . $str . '</span>%3$s</div></li></li><div class="now"><span class="text">Cena:</span>%2$s</div></li></ul></div>', 'woocommerce' ), wc_price ( $product->get_regular_price() ), wc_price( $product->get_sale_price() ), wc_price( $product->get_regular_price() - $product->get_sale_price() ) );
}
return $price;
}
I am having a custom plugin which is used to show accessories. I want to display total savings of main product and accessories combined. my saving works if the main product is simple if the main product is variable the savings shows null. can someone update my code, please
I tried this code to show saving but it is just working for simple products
function you_save_echo_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 id="saving_total_price">You Save: <span class="symbol"><?php echo $currency_symbol; ?></span> <span class="amount"><?php echo $saved_amount; ?></span>.00</p>
<?php
}
}
add_action( 'woocommerce_single_product_summary', 'you_save_echo_product', 11 );
I expect to show total savings for my accessories with the main product as a variable
I have revisited your code as it's is a bit outdated and old… On variable products there is 2 prices, a price range and the selected variation price, so you need something completely different to display the saving amount of the selected variation price.
I have added also the saving percentage (that you can remove if you don't need it).
// For simple products
add_action( 'woocommerce_single_product_summary', 'simple_product_saving_amount', 11 );
function simple_product_saving_amount() {
global $product;
if( $product->is_type('simple') && $product->is_on_sale() ) {
$regular_price = (float) wc_get_price_to_display( $product, array('price' => $product->get_regular_price() ) );
$active_price = (float) wc_get_price_to_display( $product, array('price' => $product->get_sale_price() ) );
$saved_amount = $regular_price - $active_price;
$percentage = round( $saved_amount / $regular_price * 100 );
echo '<p id="saving_total_price">'. __("You Save") .': ' . wc_price($saved_amount) . ' ('.$percentage.'%)</p>';
}
}
// 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="saving_total_price">'. __("You Save") .': ' . wc_price($saved_amount) . ' ('.$percentage.'%)</p>';
}
return $data;
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.
In the functions file I have added a filter hook to add a custom label before the variation product "min" price.
How can I get the label in the same line as the price?
See my code and the screenshot below:
add_filter( 'woocommerce_variable_sale_price_html', 'wc_wc20_variation_price_format', 10, 2 );
add_filter( 'woocommerce_variable_price_html', 'wc_wc20_variation_price_format', 10, 2 );
function wc_wc20_variation_price_format( $price, $product ) {
$min_price = $product->get_variation_price( 'min', true );
$price = sprintf( __( 'From%1$s', 'woocommerce' ), wc_price( $min_price ) );
return $price;
}
Since WooCommerce 3, woocommerce_variable_sale_price_html hook is deprecated and not anymore useful. If you don't care about "min" sale price (when the min price is on sale), you can use this:
add_filter( 'woocommerce_variable_price_html', 'custom_min_max_variable_price_html', 10, 2 );
function custom_min_max_variable_price_html( $price, $product ) {
$prices = $product->get_variation_prices( true );
$min_price = current( $prices['price'] );
$min_price_html = wc_price( $min_price ) . $product->get_price_suffix();
$price = sprintf( __( 'From %1$s', 'woocommerce' ), $min_price_html );
return $price;
}
Code goes in function.php file of your active child theme (or theme) or also in any plugin file.
Tested and works on WooCommerce 3+. You will get something like this:
If you care about "min" sale price (when the min price is on sale), and you want to display both prices, you should use this code instead:
add_filter( 'woocommerce_variable_price_html', 'custom_min_max_variable_price_html', 10, 2 );
function custom_min_max_variable_price_html( $price, $product ) {
$prices = $product->get_variation_prices( true );
$min_price = current( $prices['price'] );
$min_keys = current(array_keys( $prices['price'] ));
$min_price_regular = $prices['regular_price'][$min_keys];
$min_price_html = wc_price( $min_price ) . $product->get_price_suffix();
if( $min_price_regular != $min_price ){ // When min price is on sale (Can be removed)
$min_price_regular_html = '<del>' . wc_price( $min_price_regular ) . $product->get_price_suffix() . '</del>';
$min_price_html = $min_price_regular_html .'<ins>' . $min_price_html . '</ins>';
}
$price = sprintf( __( 'From %1$s', 'woocommerce' ), $min_price_html );
return $price;
}
Code goes in function.php file of your active child theme (or theme) or also in any plugin file.
Tested and works on WooCommerce 3+. You will get something like this:
To handle when all variations prices are the same:
WooCommerce variable products: Display the min price with a custom text for different prices