GTM — Abandoned Cart
Script inyectado desde Google Tag Manager en las páginas de checkout y ThankYouPage. Captura los datos del carrito y del usuario según van rellenando el formulario de envío y los envía al servicio externo sfccabandonedcart.hawkersco.net.
Cuándo se ejecuta
El script se activa condicionado al valor de la variable GTM {{DLV - page_type}}:
Valor de page_type | Comportamiento |
|---|---|
ThankYouPage | Recupera el carrito guardado en sessionStorage, añade el número de pedido y lo envía a la API. |
| Cualquier otro (checkout) | Elimina el carrito previo de sessionStorage y registra listeners en los campos del formulario. |
Endpoints y credenciales
| Variable | Valor | Descripción |
|---|---|---|
endpointGetToken | https://sfccabandonedcart.hawkersco.net/oauth/token | Obtención de token OAuth. |
endpointAbandonedCart | https://sfccabandonedcart.hawkersco.net/push | Envío del carrito abandonado. |
tokenUsername | sfccabandoned (Base64) | Usuario para autenticación Basic. |
tokenPassword | sfcc@b@nd0ned (Base64) | Contraseña para autenticación Basic. |
authTokenApi | c2ZjY2FiYW5kb25lZC1jbGllbnQ6c2ZjY0BiQG5kMG5lZA== | Token estático incluido en el payload. |
maxRetries | 3 | Reintentos en caso de invalid_token (401). |
El endpoint endpointAbandonedCart apunta al entorno de staging. Hay un comentario // TODO: Cambiar cuando salgamos a producción pendiente de resolver antes del go-live.
Selectores de campos
El script tiene dos modos según si el usuario está identificado o es guest. La detección se hace leyendo el input oculto [name="gtmAbandonedCartUserIsLogged"].
- Guest (no logado)
- Usuario logado
| Campo | Selector |
|---|---|
#email | |
| Nombre | #name |
| Apellido | #lastname |
| Fiscal ID | #fiscalId |
| País de envío | #countryCode |
| Provincia | #stateCode |
| Ciudad | #city |
| Dirección | #address1 |
| Código postal | #cp |
| Prefijo teléfono | #phonePrefix |
| Teléfono | #phone |
| Botón continuar | .js-form-shipping__button-submit |
Los campos del usuario logado se localizan relativos a [name="addressUUID"]:checked (la dirección seleccionada):
| Campo | Selector |
|---|---|
[name="gtmAbandonedCartShippingDataEmail"] | |
| Nombre | ...checked ~ [name="gtmAbandonedCartShippingDataName"] |
| Apellido | ...checked ~ [name="gtmAbandonedCartShippingDataLastName"] |
| Fiscal ID | ...checked ~ [name="gtmAbandonedCartShippingDataFiscalId"] |
| País | ...checked ~ [name="gtmAbandonedCartShippingDataCountryCode"] |
| Provincia | ...checked ~ [name="gtmAbandonedCartShippingDataStateCode"] |
| Ciudad | ...checked ~ [name="gtmAbandonedCartShippingDataCity"] |
| Dirección | ...checked ~ [name="gtmAbandonedCartShippingDataAddress1"] |
| Código postal | ...checked ~ [name="gtmAbandonedCartShippingDataPostalCode"] |
| Prefijo teléfono | ...checked ~ [name="gtmAbandonedCartShippingDataPhonePrefix"] |
| Teléfono | ...checked ~ [name="gtmAbandonedCartShippingDataPhone"] |
| Botón continuar | .js-form-customer-addresses__button-submit, .js-form-customer-shipment__button-submit |
Estructura del carrito guardado
El carrito se guarda en sessionStorage bajo la clave abandonedCart. La base de datos de productos viene del elemento #abandonedCartData[data-json] (generado por SFCC); el script le añade los campos del usuario:
{
"...": "campos de producto provenientes de #abandonedCartData[data-json]",
"user": {
"email": "usuario@ejemplo.com",
"name": "Nombre",
"lastname": "Apellido",
"fiscalId": "12345678A",
"gdpr": {
"statistics": true,
"marketing": false
},
"shippingInfo": {
"country": "ES",
"state": "MA",
"city": "Madrid",
"address": "Calle Mayor 1",
"zipCode": "28001",
"phone": "600000000"
}
},
"timestamp": 1720000000000,
"token": "c2ZjY2FiYW5kb25lZC1jbGllbnQ6c2ZjY0BiQG5kMG5lZA==",
"orderNumber": ""
}
En ThankYouPage, orderNumber se rellena con el contenido de .summary-details.order-number antes de enviarlo.
GDPR
Los datos de consentimiento se leen de la cookie HW_allow_privacy_policy (valor Base64). La función getGdprData() la parsea y devuelve un objeto { [id]: boolean } con las categorías y su estado de aceptación.
Flujo de funciones
CHECKOUT (page_type ≠ ThankYouPage)
│
├─ Elimina carrito previo de sessionStorage
│
├─ focusout en email / name / lastname
│ └─ launchAbandonedCart()
│ └─ isValidEmail() → updateAbandonedCart()
│ ├─ Si hay carrito en sessionStorage → actualiza campos + timestamp + guarda + envía
│ └─ Si no → setAbandonedCart() → lee #abandonedCartData + getUserData() + guarda
│
├─ change en país / provincia
│ └─ launchAbandonedCart()
│
└─ click en botón continuar
└─ launchAbandonedCart()
THANKYOUPAGE (page_type === 'ThankYouPage')
│
└─ Lee sessionStorage → añade orderNumber → sendAbandonedCartToPi()
Funciones de referencia
| Función | Descripción |
|---|---|
getAuthenticationBasic(user, pass) | Construye el header Authorization: Basic ... decodificando los valores Base64 y recodificando el par user:pass. |
isValidEmail(email) | Valida el email con regex RFC-compatible. Devuelve boolean. |
getGdprDataFromCookies() | Lee la cookie HW_allow_privacy_policy y decodifica su valor Base64. |
getGdprData() | Parsea el resultado anterior en { [id]: boolean }. |
getShippingInfoData() | Lee los campos de envío del DOM y devuelve el objeto shippingInfo. El teléfono se limpia de caracteres no numéricos (replace(/[^0-9-]/g, '')). |
getUserData() | Agrega email, nombre, apellido, fiscalId, gdpr y shippingInfo en un objeto user. |
setAbandonedCart() | Crea el objeto de carrito completo leyendo #abandonedCartData[data-json] y lo guarda en sessionStorage. |
updateAbandonedCart() | Actualiza los campos de usuario y envío en el carrito ya existente en sessionStorage y llama a sendAbandonedCartToPi. |
saveAbandonedCart(data) | Serializa y guarda el carrito en sessionStorage['abandonedCart']. |
sendAbandonedCartToPi(data) | Envía el carrito via POST con autenticación Basic. Si recibe 401 + invalid_token, decrementa maxRetries (máx. 3 intentos). |
launchAbandonedCart() | Punto de entrada desde los listeners: valida email y llama a updateAbandonedCart. |