En muchas tiendas online se utilizan promociones de tipo «3×2», donde el usuario paga solamente por 2 de los 3 productos que elige, normalmente regalando el producto más barato. Este tipo de oferta es muy atractiva para los clientes y, puede aumentar el valor promedio del carrito. En el caso de WooCommerce, la implementación de estas promociones requiere instalar un plugin específico para esto o hacerlo como te explico en este tutorial con un poco de código personalizado.
En este artículo, te mostraré un snippet de código en PHP que permita identificar cuando en el carrito hay productos de 3 marcas distintas y, en ese caso, regalar automáticamente el producto más barato (o los productos más baratos, si se cumple el requisito varias veces). Además, aprenderás cómo funciona la lógica de agrupar los productos por marca y aplicar el descuento directamente en el cálculo de la compra.
¿Por qué hacer una promoción 3X2 específica para marcas?
- Incentivo a la variedad: Al requerir que el cliente seleccione productos de 3 marcas diferentes, promueves la diversidad de tu catálogo y animas a los usuarios a conocer más opciones.
- Aumenta el gasto promedio: Muchas veces, los usuarios añaden productos a su carrito de marcas que no tenían planeadas, con tal de acceder a la oferta.
- Control del margen de ganancia: Regalar el producto más barato limita de forma controlada lo que la tienda asume como costo de la promoción.
¿Qué necesitas?
- Tener WooCommerce instalado y funcionando en tu sitio web de WordPress.
- Conocer qué taxonomía utilizas para las marcas. En este ejemplo, se usa la taxonomía
pwb-brand
, que pertenece al plugin Perfect Brands for WooCommerce. Si utilizas otra taxonomía distinta (por ejemplo,product_brand
u otra), deberías adaptar la variable$brand_taxonomy
en el código.
¿Necesitas un desarrollo web a medida?
Me especializo en desarrollar sitios webs avanzados, programando soluciones personalizadas para proyectos web.
Empezamos…
El siguiente snippet de PHP lo puedes agregar directamente en el archivo functions.php
de tu tema hijo o en un plugin específico para funciones personalizadas, haz las modificaciones directamente en el código y cuando todo te funcione como quieres sustituye estos datos por campos personalizados:
class WC_Brand_Discount_3x2 {
public function __construct() {
add_action('woocommerce_cart_calculate_fees', [$this, 'apply_brand_discount']);
}
public function apply_brand_discount($cart) {
if (is_admin() && !defined('DOING_AJAX')) {
return;
}
// Verifica si hay cupones aplicados
if ($cart->has_discount()) {
return; // Salimos si hay algún cupón aplicado
}
$brand_taxonomy = 'pwb-brand'; // Taxonomía utilizada para las marcas
$eligible_products = []; // Productos elegibles organizados por marca
// Organiza los productos del carrito por sus marcas
foreach ($cart->get_cart() as $cart_item_key => $cart_item) {
$product_id = $cart_item['product_id'];
// Obtiene la marca del producto
$brands = wp_get_post_terms($product_id, $brand_taxonomy);
if (!is_wp_error($brands) && !empty($brands)) {
$brand = $brands[0]->name; // Usa la primera marca encontrada
$eligible_products[$brand][] = $cart_item;
}
}
// Verifica si hay al menos 3 marcas distintas para aplicar el descuento
$brand_count = count(array_keys($eligible_products));
$discount_count = intdiv($brand_count, 3); // Número de descuentos a aplicar (1 por cada 3 marcas)
// Si hay al menos 3 marcas distintas, procedemos con el descuento
if ($discount_count > 0) {
$applied_discounts = 0;
$all_products = [];
// Recorre todos los productos y los agrega a una lista plana
foreach ($eligible_products as $brand_products) {
foreach ($brand_products as $product) {
$all_products[] = $product;
}
}
// Ordena los productos por precio base (sin impuestos)
usort($all_products, function ($a, $b) {
// Obtener precio base sin impuestos
$price_a = $a['data']->get_price_excluding_tax();
$price_b = $b['data']->get_price_excluding_tax();
return $price_a <=> $price_b;
});
// Aplica el descuento a los productos más baratos
foreach ($all_products as $product) {
if ($applied_discounts >= $discount_count) {
break; // Salimos si ya aplicamos todos los descuentos necesarios
}
// Obtener precio base sin impuestos
$product_price_excl_tax = $product['data']->get_price_excluding_tax();
// Aplicamos el descuento al producto más barato (sin impuestos)
$cart->add_fee(
__('Promoción en Marcas 3x2 (DESCUENTO del valor del Producto más barato)', 'woocommerce'),
-$product_price_excl_tax, // El descuento es igual al precio del producto más barato (sin impuestos)
false // No aplicamos impuestos sobre el descuento
);
$applied_discounts++;
}
}
}
}
new WC_Brand_Discount_3x2();
El código que acabamos de ver tiene algunos puntos muy interesantes que vamos a repasar:
- Con la función de WordPress
«if (is_admin() && !defined('DOING_AJAX'))»
verificamos si estamos en el backend de WordPress para que el código no afecte a los procesos internos del admin. - Con
«if ($cart->has_discount())»
Verificaremos si hay cupones aplicados. Si el usuario o la tienda aplicó algún cupón, la lógica de esta promoción se desactiva automáticamente. - Almacenaremos la taxonomía que previamente hemos localizado en la variable
«$brand_taxonomy = 'pwb-brand';»
. Cámbiala si trabajas con otra taxonomía. *Esto se puede controlar desde un campo personalizado de una página de opciones. - Añadimos una nueva variable
«$eligible_products = [];»
que recogerá en unarray
todos los productos organizados por marca. Para lo cual recorreremos lositems
del menú con unforeach
. - Usamos
«intdiv($brand_count, 3)»
para saber cuántas veces podemos regalar el producto más barato (1 vez si hay 3 marcas, 2 veces si hay 6, etc.). Cambia el número de marcas que necesita tu negocio para efectuar el descuento. *Esto se puede controlar desde un campo personalizado de una página de opciones. - Ordenamos los productos por su precio, así localizamos los más económicos primero.
- Aplicamos el descuento con
add_fee
, WooCommerce permite agregar recargos (fees) o descuentos (fees negativos). Para cada producto más económico, descontaremos su precio base sin impuestos. - Modifica o traduce a otros idiomas el texto para indicar la promoción mediante esta función:
__('Promoción en Marcas 3x2 (DESCUENTO del valor del Producto más barato)', 'woocommerce')
. *Esto se puede controlar desde un campo personalizado de una página de opciones. - Detenemos la iteración cuando hemos aplicado todos los descuentos correspondientes.

Posibles ajustes y recomendaciones
- Si tus marcas se gestionan con otra taxonomía, como
product_brand
de YITH Brands o cualquier otra, asegúrate de cambiar la variable$brand_taxonomy
. - Por defecto, hemos dejado el parámetro en
false
para la funciónadd_fee
. Esto indica que no se aplican impuestos al descuento. Si quieres que la operación de descuento sea gravada, puedes cambiarlo atrue
. - Si deseas que puedan coexistir cupones con esta promoción, elimina o comenta la línea:
if ($cart->has_discount()) { return; }
- Mejoras de rendimiento: Si tu sitio es muy grande o maneja un alto volumen de productos, considera optimizaciones adicionales (caché de precios, etc.). Sin embargo, para la mayoría de las tiendas la ejecución será muy rápida.
Si has completado el tutorial hasta aqui, deberias de ver el descuento bien hecho en el carrito y en el checkout.

Preguntas Frecuentes
¿Qué pasa si el carrito tiene 6 marcas distintas?
Automáticamente se aplicaría la promoción de regalar 2 productos más baratos, ya que intdiv(6, 3) = 2.
¿Qué ocurre si uno de los productos tiene variaciones?
El código se basa en el $cart_item['data']
, que maneja directamente la variación. Aun así, debes asegurarte de que tu producto variable conserve la taxonomía de la marca en el producto principal o en la variación.
¿Qué pasa si quiero que solo se aplique un descuento sin importar cuántas veces se alcance el mínimo de 3 marcas?
Puedes cambiar la línea:
$discount_count = intdiv($brand_count, 3);
por:
$discount_count = $brand_count >= 3 ? 1 : 0;
De esta forma, solo aplicará un descuento por cada 3 o más marcas, y no repetirá el patrón para 6, 9, etc.
¿Qué más puedo hacer?
- Modifica el código o introduce otras variables de descuento, 15% en todos los producto, si pasas de 200 te regalo X, compre X unidades y obtenga Y% de descuento, Descuento por categorías combinadas, oferta especial día del padre o de la madre… Dispones de infinitas posibilidades. Adáptalo a las necesidades de tu cliente.
- Usa IDs de términos en lugar de nombres para evitar problemas con caracteres especiales o marcas con nombres similares.
- Implementar un límite máximo de descuento para proteger el margen de beneficio.
- Haz que los mensajes de descuento sean más claros para el cliente.
- Guarda información de los descuentos aplicados para análisis posteriores.
- Mejora la gestión de impuestos según la configuración de la tienda.
- Sustituye los textos del código por campos personalizados controlándolos desde una buena página de opciones. Puedes ver un tutorial muy bueno de como crear paginas de opciones profesionales.
- Indícales a tus clientes que pueden activar y desactivar las promociones de una forma muy sencilla, solo tienen que completar los campos personalizados de la página de opciones y activar las funciones asociadas a las promociones, En este caso yo les tengo una para mostrar un modal de información. (En el próximo tutorial te enseño como hacer estos modales).

