Skip to main content

GTM — Countdown Promo Cart

Script que inyecta un countdown regresivo en el bloque de promoción del carrito (.hw-cart_list-item-first-applicable). Mientras la cuenta atrás está activa puede ocultar el mensaje promocional original. Cuando la fecha de fin llega, el countdown desaparece y restaura el estado inicial.


Variables GTM

Los textos y fechas se configuran desde variables del Data Layer en GTM, no en el código:

Variable GTMDescripción
{{countdown-cart-promo-message-intro}}Texto introductorio antes del countdown (ej. "¡Oferta termina en:").
{{countdown-cart-promo-start-date}}Fecha y hora de inicio — antes de esta fecha el countdown no se muestra. Formato JS Date válido (ej. "2025-07-20T00:00:00").
{{countdown-cart-promo-end-date}}Fecha y hora de fin — cuando se alcanza, el countdown se elimina.
{{countdown-cart-promo-label-days}}Etiqueta de días (ej. "días").
{{countdown-cart-promo-label-hours}}Etiqueta de horas (ej. "h").
{{countdown-cart-promo-label-minutes}}Etiqueta de minutos (ej. "min").
{{countdown-cart-promo-label-seconds}}Etiqueta de segundos (ej. "seg").

Flags de configuración

Variables booleanas/numéricas que controlan el comportamiento desde el código:

VariableValor por defectoDescripción
gtmCountdownPromoCartDelay1000Milisegundos de espera antes de inicializar. 0 = sin espera.
gtmCountdownPromoCartShowDaysfalseSi true, muestra la columna de días y las horas se calculan módulo 24. Si false, las horas acumulan días (pueden superar 24).
gtmCountdownPromoCartShowIntrotrueSi false, no inyecta el párrafo de texto introductorio.
gtmCountdownPromoCartHideOriginalMessagetrueSi true, oculta el mensaje original del carrito mientras el countdown está activo. Si false, añade además la clase gtm-html-cart-promo-message al contenedor para mostrar ambos apilados.

Elementos del DOM

SelectorDescripción
.hw-cart_list-item-first-applicableContenedor donde se inyecta el countdown.
.hw-cart_list-item-first-applicable span:nth-child(2)Mensaje de promoción original (se oculta si hideOriginalMessage es true).

Estructura HTML generada

<!-- Dentro de .hw-cart_list-item-first-applicable -->
<div class="gtm-js-countdown-content gtm-html-countdown-content">

<!-- Solo si gtmCountdownPromoCartShowIntro = true -->
<p class="gtm-js-countdown-intro gtm-html-countdown-intro">
{{countdown-cart-promo-message-intro}}
</p>

<!-- Countdown (comienza con skeleton, se reemplaza en el primer tick) -->
<div class="gtm-js-countdown gtm-html-countdown">
<div class="gtm-html-countdown-wrapper">

<!-- Días: solo si showDays = true Y days > 0 -->
<div class="gtm-html-countdown-element">
<p class="gtm-html-countdown-number">02</p>
<p class="gtm-html-countdown-label">días</p>
</div>
<p class="gtm-html-countdown-separator">:</p>

<!-- Horas: si hours > 0 O si hay días -->
<div class="gtm-html-countdown-element">
<p class="gtm-html-countdown-number">14</p>
<p class="gtm-html-countdown-label">h</p>
</div>
<p class="gtm-html-countdown-separator">:</p>

<!-- Minutos: siempre -->
<div class="gtm-html-countdown-element">
<p class="gtm-html-countdown-number">07</p>
<p class="gtm-html-countdown-label">min</p>
</div>
<p class="gtm-html-countdown-separator">:</p>

<!-- Segundos: siempre -->
<div class="gtm-html-countdown-element">
<p class="gtm-html-countdown-number">33</p>
<p class="gtm-html-countdown-label">seg</p>
</div>

</div>
</div>

</div>
Separadores

Los <p class="gtm-html-countdown-separator"> tienen display: none por CSS. Se incluyen en el DOM pero no son visibles — están preparados para activarse con una regla CSS si se necesita en el futuro.


Clases CSS

El script separa clases en dos namespaces para evitar colisiones:

ClaseElementoDescripción
gtm-html-cart-promo-messageContenedorAñade flex-wrap: wrap cuando el mensaje original no se oculta.
gtm-html-countdown-contentdivFila de countdown: flex, flex-wrap: wrap, gap: 4px 10px. Cuando está dentro de gtm-html-cart-promo-message, ocupa width: 100%.
gtm-html-countdown-intropTexto intro, color: currentColor.
gtm-html-countdown-wrapperdivFila interna de unidades: flex, gap: 0 4px.
gtm-html-countdown-elementdivPar número + etiqueta: flex, align-items: baseline, gap: 2px.
gtm-html-countdowndivWrapper del countdown, fuente NimbusSansDOTExtended.
gtm-html-countdown-numberpNúmero: font-size: 20px, font-weight: 700.
gtm-html-countdown-labelpEtiqueta: font-size: 8px.
gtm-html-countdown-separatorpSeparador :display: none por defecto.

Flujo de ejecución

Espera gtmCountdownPromoCartDelay ms (defecto: 1000ms)

└─ fnGtmInitCountdownPromoCart()

├─ fnGtmCountdownPromoCartToPreInitElements()
│ ├─ Busca container + originalMessage
│ └─ Si !hideOriginalMessage → añade gtm-html-cart-promo-message al container

├─ fnGtmCountdownPromoCartToInjectCode()
│ ├─ Crea div.content + p.intro (si showIntro) + div.countdown (con skeleton)
│ └─ Los añade al container (inicialmente ocultos con is-hidden)

├─ fnGtmCountdownPromoCartToInitElements()
│ └─ Recupera los nuevos elementos via gtm-js-* selectors

└─ fnGtmCountdownPromoCartToInitCountdown()
├─ Si now < startDate → no hace nada (countdown aún no debe mostrarse)
└─ Si now >= startDate Y diferencia > 0:
└─ fnGtmCountdownPromoCartToShowCountdown()
├─ Oculta originalMessage (si hideOriginalMessage)
├─ Muestra intro + countdown (quita is-hidden)
└─ setInterval cada 1000ms → fnGtmCountdownPromoCartToUpdateCountdown()
├─ Calcula días / horas / minutos / segundos restantes
├─ Construye HTML y actualiza countdown.innerHTML
└─ Si diferencia <= 0:
└─ fnGtmCountdownPromoCartToRemoveCountdown()
├─ Elimina intro + countdown del DOM
├─ Restaura originalMessage
└─ clearInterval

Lógica de horas según showDays

showDaysCálculo de horasEfecto
false (defecto)Math.floor(difference / 3600000)Las horas son el total acumulado (ej. 50h si quedan 2 días y 2h).
trueMath.floor((difference % 86400000) / 3600000)Las horas son módulo 24; los días se muestran en su propia columna.

Funciones de referencia

FunciónDescripción
fnGtmCountdownPromoCartToPreInitElementsLocaliza el contenedor y el mensaje original.
fnGtmCountdownPromoCartToInjectCodeCrea y añade la estructura HTML del countdown al DOM.
fnGtmCountdownPromoCartToInitElementsRecupera los elementos recién creados para manipularlos después.
fnGtmCountdownPromoCartToInitCountdownComprueba fechas y arranca el countdown si procede.
fnGtmCountdownPromoCartToShowCountdownHace visible el countdown e inicia el intervalo de actualización.
fnGtmCountdownPromoCartToRemoveCountdownElimina el countdown del DOM, restaura el mensaje original y detiene el intervalo.
fnGtmCountdownPromoCartToGetDifferenceDevuelve ms restantes hasta endDate.
fnGtmCountdownPromoCartToUpdateCountdownRecalcula y reescribe el HTML interno del countdown cada segundo.
fnGtmCountdownPromoCartToPadZero(n)Añade 0 inicial a números menores de 10.