Hay un momento en el proceso de compra que casi nadie cuida tanto como debería: el carrito. Nos obsesionamos con la ficha de producto, con las fotos, con la descripción perfecta que convierte… y luego el cliente llega al carrito y ahí ya no le contamos nada. Es la sala de espera antes de pagar, y en las salas de espera silenciosas es donde más dudas le entran a la gente.
Uno de esos silencios que puede jugarte una mala pasada es el del precio. Un cliente añade un producto al carrito, se distrae (le suena el móvil, tiene que ir a buscar la tarjeta, se lo piensa dos días…) y cuando vuelve, el precio ha cambiado. Puede haber bajado por una oferta que has lanzado mientras tanto, o puede haber subido porque has actualizado tarifas. Sea cual sea el motivo, si no le dices nada, el cliente lo puede interpretar como que le estás intentando colar algo. Y en ecommerce, cliente que sospecha es venta que se cae.
La solución que os traigo hoy lo habéis visto en Amazon seguro: un aviso destacado arriba del carrito que compara el precio actual del producto con el precio que tenía cuando el cliente lo añadió, y le dice claramente si ha subido o ha bajado, y cuánto. Es prima hermana de ese aviso de cuánto falta para el envío gratis que ya os enseñé hace tiempo: mismo sitio, mismo objetivo, distinta información.
Índice
¿Qué hace exactamente esta funcionalidad?
Cuando el cliente entra a la página de su carrito, si alguno de los productos que lleva ha cambiado de precio desde que lo metió en la cesta, le aparece un aviso justo arriba, antes de la tabla de productos. Algo así:
🟡 ¡Buena noticia! El precio de Taza professional Nº12 ha bajado un 20% desde que lo añadiste al carrito. Ha pasado de 15,00€ a 12,00€.
O, si el precio ha subido:
🔴 Atención: el precio de Camiseta premium 180/240 ha subido un 10% desde que lo añadiste al carrito. Ha pasado de 8,00€ a 8,80€.
Cada aviso lleva su propio color y su propio icono para que se distinga a simple vista si la noticia es buena o mala para el cliente, sin que tenga que leerse el párrafo entero para enterarse. Obteniendo el siguiente resultado final como os muestro en el vídeo:

Y esto funciona tanto si tu carrito usa el shortcode clásico [woocommerce_cart] (repasa aquí todos los shortcodes de WooCommerce si no los tienes controlados) como si usas el bloque de carrito de Gutenberg (que ahora mismo es el que trae por defecto cualquier instalación reciente de WooCommerce). Ya sabéis que muchas veces una funcionalidad que os funciona en el carrito clásico se rompe en el de bloques, así que le he dedicado un apartado técnico más abajo a explicaros por qué a mí me funciona en los dos.
Cuándo tiene sentido implementarla
No todas las tiendas necesitan esto, y os lo digo siempre: antes de meter código en vuestra web, preguntaos si esa funcionalidad os va a aportar algo real o si es «postureo técnico» o «he visto que queda chulo que lo ha subido Diego a Youtube». Dicho esto, hay varios escenarios donde sí que le veo mucho sentido:
- Tiendas con ofertas flash o precios que cambian a menudo. Si lanzáis descuentos puntuales, rebajas de stock o promociones de fin de semana, es muy probable que un cliente tenga un producto en el carrito justo cuando baja el precio. Avisarle de la bajada es casi gratis en términos de esfuerzo y puede ser el empujón final para que complete la compra.
- Catálogos con proveedores externos (dropshipping). Si sincronizáis precios con vuestros proveedores (aquí os hablé de cómo hacerlo), los precios os pueden cambiar sin que vosotros hagáis nada. El cliente merece saberlo antes de pagar, y a vosotros os evita algún que otro correo de «oye, esto no me costaba esto ayer».
- Negocios B2B con tarifas variables. En ventas a empresas, donde los precios pueden depender de acuerdos, temporadas o volumen, este tipo de transparencia genera mucha confianza. Y en B2B la confianza vale más que el propio precio.
- Carritos con tiempos de conversión largos. Si vuestro público suele tardar días en decidirse (típico en tickets altos), cuanta más información honesta le deis en cada paso, menos fricción tendrá al final.
Un caso real: a una alumna mía que vende productos de temporada le pasaba que actualizaba precios los lunes por la mañana, y cada semana le llegaban un par de quejas de clientes que habían dejado el carrito abandonado el domingo. Con este aviso, en vez de sorpresa desagradable, el cliente ve la bajada, sonríe, y compra. Ese es el efecto que buscamos.
Cuándo NO la recomiendo
Aquí toca ser honesto, como siempre: no todo lo que se puede programar conviene programarlo.
- Si tus precios son estáticos. Si no tocas los precios de tu catálogo salvo una vez al año, esta funcionalidad no le va a servir a nadie. Es código extra corriendo en cada visita al carrito para una comprobación que casi nunca va a dar resultado. Ahorraos el peso.
- Si tu ciclo de compra es de segundos. Tiendas de compra impulsiva, donde el cliente añade y paga en el mismo minuto, no tienen tiempo material para que el precio cambie entre medias. Aquí el aviso simplemente no va a aparecer casi nunca, así que no merece la pena mantenerlo.
- Si no vais a cuidar el tono del aviso de subida. Esto es importante: avisar de que el precio ha subido es honesto, pero mal presentado puede sonar como una amenaza («cómpralo ya antes de que suba más»). Yo prefiero un tono neutro e informativo, no de urgencia forzada. Si vais a usar esto como táctica de presión psicológica en vez de transparencia real, mejor no lo implementéis, porque se nota, y el cliente que se siente manipulado no vuelve.
Como veis, mi recomendación no es «instaladlo todos», es «instaladlo si os aporta algo real a vosotros y a vuestro cliente». Y es que aunque lo tenga Amazon y otras tiendas grandes, no significa que sea algo fundamental en una tienda online:

Antes de implementar esta funcionalidad…
Sí os he convencido, antes de daros el código, os cuento brevemente las decisiones técnicas que he tomado, porque creo que entender el «por qué» os va a ayudar mucho si luego queréis tocar u os encontráis con warnings raros en algún caso concreto.
¿De dónde saco el precio «guardado»? En el momento en que el cliente añade el producto al carrito, guardo el precio de ese instante junto con el resto de datos de esa línea del carrito. Es un dato que viaja con la sesión, así que aunque el cliente cierre el navegador y vuelva al día siguiente (si tenéis persistencia de carrito activada), la comparación sigue siendo correcta.
¿Por qué leo el precio actual «en frío», sin caché? Porque me encontré con un problema muy típico en hostings con caché de objetos persistente (Redis, Memcached…): cuando cambiabas solo el precio normal de un producto, sin tocar el precio de oferta, WooCommerce no siempre invalidaba la caché con la misma agresividad que cuando activas una oferta. Resultado: el aviso no detectaba bajadas de precio normal. La solución es forzar una lectura fresca del producto justo antes de comparar, ignorando cualquier caché.
¿Por qué no uso wc_add_notice()? Esta es importante si alguna vez habéis intentado mostrar avisos personalizados en el carrito de bloques. wc_add_notice() es la función nativa de WooCommerce para avisos, y funciona genial en el carrito clásico… pero WooCommerce tiene un bug conocido (documentado en su propio repositorio de GitHub) por el que esos avisos no se muestran en el carrito de bloques. Así que en vez de pelearme con eso, inyecto el HTML del aviso directamente en el filtro the_content, que es uno más de los muchos hooks que tiene WooCommerce para meter contenido donde queramos, justo antes del contenido de la página. Como tanto el shortcode como el bloque de carrito se renderizan dentro del contenido de la página, este truco funciona igual para los dos sin duplicar lógica.
El código paso a paso
Aquí tenéis la funcionalidad completa. Como siempre, os recomiendo pegarla en el functions.php de vuestro child theme, o mejor aún, en un plugin de funcionalidades propio (aquí os explico cómo montaros uno con el plugin Code Snippets, que es justo lo que uso yo en mis proyectos).
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
// Umbral (%) a partir del cual se avisa de una BAJADA de precio.
if ( ! defined( 'DL_UMBRAL_BAJADA' ) ) {
define( 'DL_UMBRAL_BAJADA', 15 );
}
// Umbral (%) a partir del cual se avisa de una SUBIDA de precio.
// Por defecto en 0, para avisar de cualquier subida, por pequeña que sea.
if ( ! defined( 'DL_UMBRAL_SUBIDA' ) ) {
define( 'DL_UMBRAL_SUBIDA', 0 );
}
// 1) Guardamos el precio del producto en el momento en que se añade al carrito.
add_filter( 'woocommerce_add_cart_item_data', 'dl_guardar_precio_al_anadir', 10, 3 );
function dl_guardar_precio_al_anadir( $cart_item_data, $product_id, $variation_id ) {
$id_para_precio = $variation_id ? $variation_id : $product_id;
$product = wc_get_product( $id_para_precio );
if ( $product ) {
$cart_item_data['dl_precio_guardado'] = (float) wc_get_price_to_display( $product );
}
return $cart_item_data;
}
// 2) Nos aseguramos de que ese dato persista al recuperar el carrito de la sesión.
add_filter( 'woocommerce_get_cart_item_from_session', 'dl_recuperar_precio_de_sesion', 10, 2 );
function dl_recuperar_precio_de_sesion( $cart_item, $values ) {
if ( isset( $values['dl_precio_guardado'] ) ) {
$cart_item['dl_precio_guardado'] = $values['dl_precio_guardado'];
}
return $cart_item;
}
// 3) Lee el precio "en frío", ignorando cualquier caché de objetos/posts.
function dl_obtener_precio_actual_sin_cache( $product_id, $variation_id = 0 ) {
$id_real = $variation_id ? $variation_id : $product_id;
clean_post_cache( $id_real );
wp_cache_delete( $id_real, 'post_meta' );
wp_cache_delete( 'product-' . $id_real, 'products' );
$product_fresco = wc_get_product( $id_real );
if ( ! $product_fresco ) {
return null;
}
return (float) wc_get_price_to_display( $product_fresco );
}
// 4) Calculamos las diferencias de precio y devolvemos el HTML del aviso.
function dl_generar_html_avisos_precio() {
if ( ! function_exists( 'WC' ) || ! WC()->cart || WC()->cart->is_empty() ) {
return '';
}
$avisos = array();
foreach ( WC()->cart->get_cart() as $cart_item ) {
if ( empty( $cart_item['dl_precio_guardado'] ) ) {
continue;
}
$product = isset( $cart_item['data'] ) ? $cart_item['data'] : null;
if ( ! $product ) {
continue;
}
$precio_guardado = (float) $cart_item['dl_precio_guardado'];
$precio_actual = dl_obtener_precio_actual_sin_cache( $cart_item['product_id'], $cart_item['variation_id'] );
if ( null === $precio_actual || $precio_guardado <= 0 ) {
continue;
}
$diferencia_pct = ( ( $precio_actual - $precio_guardado ) / $precio_guardado ) * 100;
if ( $diferencia_pct < 0 && abs( $diferencia_pct ) < DL_UMBRAL_BAJADA ) {
continue;
}
if ( $diferencia_pct > 0 && $diferencia_pct < DL_UMBRAL_SUBIDA ) {
continue;
}
if ( 0 === (int) round( $diferencia_pct ) ) {
continue;
}
$nombre = $product->get_name();
$pct = round( abs( $diferencia_pct ) );
$precio_guardado_html = wc_price( $precio_guardado );
$precio_actual_html = wc_price( $precio_actual );
if ( $diferencia_pct < 0 ) {
$avisos[] = sprintf(
'<div class="dl-aviso-precio dl-aviso-bajada">
<span class="dl-aviso-icono">🟡</span>
<span class="dl-aviso-texto"><strong>¡Buena noticia!</strong> El precio de <strong>%1$s</strong> ha bajado un <strong>%2$d%%</strong> desde que lo añadiste al carrito. Ha pasado de %3$s a %4$s.</span>
</div>',
esc_html( $nombre ), $pct, $precio_guardado_html, $precio_actual_html
);
} else {
$avisos[] = sprintf(
'<div class="dl-aviso-precio dl-aviso-subida">
<span class="dl-aviso-icono">🔴</span>
<span class="dl-aviso-texto"><strong>Atención:</strong> el precio de <strong>%1$s</strong> ha subido un <strong>%2$d%%</strong> desde que lo añadiste al carrito. Ha pasado de %3$s a %4$s.</span>
</div>',
esc_html( $nombre ), $pct, $precio_guardado_html, $precio_actual_html
);
}
}
if ( empty( $avisos ) ) {
return '';
}
return '<div class="dl-avisos-precio-wrapper">' . implode( '', $avisos ) . '</div>';
}
// 5) Inyectamos el aviso justo antes del contenido de la página del carrito.
add_filter( 'the_content', 'dl_inyectar_aviso_precio_en_carrito', 20 );
function dl_inyectar_aviso_precio_en_carrito( $content ) {
if ( is_admin() || ! function_exists( 'is_cart' ) || ! is_cart() ) {
return $content;
}
if ( ! in_the_loop() || ! is_main_query() ) {
return $content;
}
$html_aviso = dl_generar_html_avisos_precio();
if ( $html_aviso ) {
$content = $html_aviso . $content;
}
return $content;
}
// 6) Estilos del aviso.
add_action( 'wp_head', 'dl_estilos_aviso_precio_carrito' );
function dl_estilos_aviso_precio_carrito() {
if ( ! function_exists( 'is_cart' ) || ! is_cart() ) {
return;
}
?>
<style>
.dl-avisos-precio-wrapper { margin: 0 0 24px 0; }
.dl-aviso-precio {
display: flex; align-items: center; gap: 12px;
padding: 16px 20px; border-radius: 8px; font-size: 15px;
line-height: 1.5; margin-bottom: 12px;
box-shadow: 0 2px 6px rgba(0,0,0,0.08);
animation: dl-aviso-aparece 0.35s ease-out;
}
.dl-aviso-icono { font-size: 22px; line-height: 1; flex-shrink: 0; }
.dl-aviso-bajada { background-color: #e6f7ee; border: 2px solid #1e7e34; color: #145523; }
.dl-aviso-subida { background-color: #fdeeee; border: 2px solid #c62828; color: #7a1414; }
@keyframes dl-aviso-aparece {
from { opacity: 0; transform: translateY(-6px); }
to { opacity: 1; transform: translateY(0); }
}
</style>
<?php
}
Obteniendo el siguiente resultado(recuerda que al implementarlo empieza de cero, pruébalo con un producto que hayas añadido al carrito posteriormente):

Mi consejo personal: no lo activéis directamente en producción sin probarlo antes. Añadid un producto al carrito, cambiadle el precio desde el escritorio de WordPress en otra pestaña y volved al carrito para comprobar que el aviso sale bien, con el color correcto y el texto que esperáis.
Cómo personalizarlo
Las dos cosas que más me vais a preguntar en comentarios, así que os las adelanto:
- Cambiar el umbral. Arriba del todo del código tenéis dos constantes:
DL_UMBRAL_BAJADA(15% por defecto, para no avisar de bajadas insignificantes) yDL_UMBRAL_SUBIDA(0% por defecto, avisa de cualquier subida). Cambiad esos números al gusto de vuestro negocio. - Cambiar los textos o los colores. Los textos están dentro de las dos plantillas
sprintf(), y los colores en la hoja de estilos del final. Si tenéis una paleta de marca definida, os recomiendo adaptar esos colores para que el aviso no desentone con el resto de vuestra tienda. Si además jugáis con prefijos y sufijos personalizados en el precio, aseguraos de que el texto del aviso queda coherente con esos añadidos.
Y si en algún momento os interesa ir un paso más allá y guardar un histórico de estas variaciones de precio (para analizar cuántas veces sube o baja un producto a lo largo del tiempo, por ejemplo), es una ampliación que también se puede hacer con una tabla propia en base de datos. Si os interesa ese enfoque, decídmelo en comentarios y le dedico un tutorial aparte.
Conclusiones
Esta es una de esas funcionalidades pequeñas que no vais a ver en ningún curso de «cómo vender más en WooCommerce», pero que en la práctica genera confianza, que es la moneda de cambio real en cualquier ecommerce. Como siempre, no la instaléis por instalar: valorad primero si de verdad os aporta algo a vosotros y a vuestros clientes según lo que hemos visto más arriba.
Si preferís que os lo instale y configure yo directamente en vuestra tienda, ya sabéis dónde encontrarme. Y si os habéis liado con algún paso, dejádmelo en comentarios, que como siempre os leo y os respondo.







Deja una respuesta