Product Icon

WooCommerce

Sell online with the flexible, customizable ecommerce platform designed to grow with your business. From your first sale to millions in revenue, Woo is with you. See why merchants trust us to power 4+ million online stores.

discount percentage block

In the new block styles, it is missing a percentage discount block that you can put on some places on the schema of a page or a query loop.

Also, it is important to have one in the upsells and crossells loops.

I have created a shortcode for that:

add_shortcode( ‘scuento’, function( $atts ) {
global $product;

if ( ! is_a( $product, ‘WC_Product’ ) || ! $product->is_on_sale() ) {
return ”;
}

$regular_price = (float) $product->get_regular_price();
$sale_price = (float) $product->get_sale_price();

if ( $product->is_type( ‘variable’ ) ) {
$regular_price = (float) $product->get_variation_regular_price( ‘min’ );
$sale_price = (float) $product->get_variation_sale_price( ‘min’ );
}

if ( $regular_price ”,
‘sufijo’ => ‘% OFF’,
‘color’ => ‘#ffffff’,
‘fondo’ => ‘red’,
‘padding’ => ‘4px 8px’,
‘radius’ => ‘4px’,
‘size’ => ’12px’,
‘weight’ => ‘700’,
], $atts );

$style = sprintf(
‘display:inline-block;background:%s;color:%s;padding:%s;border-radius:%s;font-size:%s;font-weight:%s;line-height:1;vertical-align:middle;margin:5px 0;’,
esc_attr( $atts[‘fondo’] ),
esc_attr( $atts[‘color’] ),
esc_attr( $atts[‘padding’] ),
esc_attr( $atts[‘radius’] ),
esc_attr( $atts[‘size’] ),
esc_attr( $atts[‘weight’] )
);

return sprintf(
‘%s-%d%s’,
$style,
esc_html( $atts[‘prefijo’] ),
$percent,
esc_html( $atts[‘sufijo’] )
);
});

And another for upsells:

add_filter( ‘woocommerce_get_price_html’, ‘agregar_porcentaje_solo_en_upsells’, 100, 2 );

function agregar_porcentaje_solo_en_upsells( $price, $product ) {
// 1. Si estamos en el admin, no hacer nada
if ( is_admin() ) {
return $price;
}

// 2. OBTENER EL ID DEL PRODUCTO PRINCIPAL (EL QUE EL USUARIO ESTÁ VISITANDO)
$queried_object = get_queried_object();
$current_page_product_id = ( is_product() && $queried_object ) ? $queried_object->ID : 0;

// 3. VALIDACIÓN CRÍTICA:
// Solo procedemos si el ID del producto actual del loop NO ES el ID de la página que estamos viendo.
// Esto hace que se salte el producto “Padre” y solo actúe en los productos de las listas de abajo (Upsells).
if ( $product->get_id() === $current_page_product_id ) {
return $price;
}

// 4. Si el producto no está en oferta, no hacer nada
if ( ! $product->is_on_sale() ) {
return $price;
}

// Calcular precios (Simples y Variables)
if ( $product->is_type( ‘variable’ ) ) {
$prices = $product->get_variation_prices();
$regular_price = max( $prices[‘regular_price’] );
$sale_price = min( $prices[‘sale_price’] );
} else {
$regular_price = $product->get_regular_price();
$sale_price = $product->get_sale_price();
}

if ( $regular_price > 0 ) {
$percentage = round( ( ( floatval($regular_price) – floatval($sale_price) ) / floatval($regular_price) ) * 100 );

// Estilos Inline
$container_style = ‘display: block; margin-top: 8px; line-height: 1;’;
$badge_style = ‘background-color: #e20000; color: #ffffff; font-weight: bold; padding: 4px 8px; border-radius: 4px; font-size: 13px; display: inline-block; text-transform: uppercase;’;

$percentage_html = ”;
$percentage_html .= ‘-‘ . $percentage . ‘% OFF’;
$percentage_html .= ”;

return $price . $percentage_html;
}

return $price;
}

But this should be in the native woocommerce blocks imho.

I commented this in a thread: https://wordpress.org/support/topic/percentage-of-discount/?view=all#post-18901247

Screenshots

Author

alvaro

Current Status

Open

Last updated: May 8, 2026

0 comments

Log in to comment on this feature request.

Use of your personal data
We and our partners process your personal data (such as browsing data, IP Addresses, cookie information, and other unique identifiers) based on your consent and/or our legitimate interest to optimize our website, marketing activities, and your user experience.