Skip to main content

Marketing Cloud: principios desde producción

Trece principios que aplicamos en cada implementación de Marketing Cloud, con código concreto y los tipos de errores que muerden a escala. Operativos, no aspiracionales.

Nota de producción·Actualizado 2026-05-01·Escrito por Lira · Editado por German Medina

Trece principios que aplicamos cuando abrimos Email Studio, escribimos AMPscript, configuramos Journeys o firmamos un Send. Cada uno viene con un ejemplo concreto de código o una decisión — anclado en trabajo de implementación, no en slides de best-practice. Donde la experiencia de Cleon difiere del best-practice genérico, lo decimos.

La lista de abajo es lo que sobrevive cuando los Sends de producción tocan millones de contactos y una sola asunción incorrecta se convierte en un post-mortem a las 2 de la mañana.


Los principios

1. Lo bello es mejor que lo feo.

El código SFMC que sobrevive a la próxima lectura del próximo dev es el que ya te parecía limpio a vos. Lo bello acá es operativo, no estético — es lo que permite que la próxima persona haga un cambio chico sin romper el resto.

%%[
  /* MAL — rápido de tipear, lento de leer */
  var @x = AttributeValue("foo")
  IF EMPTY(@x) OR @x == "0" OR LOWER(@x) == "n" THEN
    SET @x = ""
  ENDIF
]%%

%%[
  /* LIMPIO — misma lógica, nombres que significan algo */
  /* Normalizamos el flag de loyalty a un booleano usable downstream. */
  VAR @loyaltyRaw, @hasLoyalty
  SET @loyaltyRaw = AttributeValue("loyalty_status")
  SET @hasLoyalty = IIF(
    EMPTY(@loyaltyRaw) OR @loyaltyRaw == "0" OR LOWER(@loyaltyRaw) == "n",
    "false",
    "true"
  )
]%%

La primera versión es más rápida de tipear. La segunda es más rápida de debuggear a las 11 de la noche. AMPscript y SSJS se escriben rápido bajo deadline y se quedan en producción años — escribí pensando en la versión de vos que durmió tres horas y necesita encontrar el bug ahora.

2. Lo explícito es mejor que lo implícito.

Nombrá el data extension. Nombrá el campo. Nombrá la versión del Journey. SFMC tiene demasiados defaults implícitos — cada uno es un incidente futuro esperando a que un dev junior lo pise sin querer.

DE_Mkt_LoyaltySends_v3        ← prefijo, dueño, propósito, versión
Subscribers_v2_final          ← prefijo no especificado, sin dueño, versión sin terminar

El primero sobrevive un hand-off. El segundo es una nota de rehén del pasado.

3. Lo simple es mejor que lo complejo.

Cuantos menos Decision Splits tiene un Journey, menos investigaciones a las 11 de la noche. Cada condicional que agregás es un test path que tiene que sobrevivir al próximo cambio del modelo de datos. Si un Journey no se puede dibujar en una sola hoja, ya es rehén de mantenimiento.

KISS — Keep It Simple, Stupid

Un Journey con un entry, un Send y una espera es más fácil de diagnosticar que uno con un entry, un Send, tres Splits, dos Engagement Splits y una espera. Si los dos entregan el mismo outcome de negocio hoy, el primero entrega el mismo outcome en seis meses también.

YAGNI — You Aren't Gonna Need It

El "framework para casos de uso futuros" es el código más caro que Cleon heredó. El caso de uso que estás imaginando para el próximo trimestre rara vez aparece; la abstracción que escribiste para soportarlo siempre.

4. Lo complejo es mejor que lo complicado.

Hay problemas que son genuinamente complejos — orquestación multi-canal, consent en tiempo real, deduplicación entre fuentes. Para esos, abrazá la complejidad pero acotala con interfaces claras.

SOC — Separation of concerns

BIEN                                           MAL
Automation: Build_Daily_Audience               Automation: Daily_Stuff
  ├ SQL Query: rebuild_master_de               (SQL + filter + send + cleanup
  └ Verify row count                            en un solo query de 800 líneas)

Automation: Send_Daily_Audience
  ├ Trigger Send Definition: TS_Daily
  └ Log to DE: de_log_daily_sends

Dos Automations planas y nombradas le ganan a un orchestrator que mezcla data prep, envío y logging. El próximo dev que necesite pausar los envíos sin pausar la construcción de datos te lo va a agradecer.

DRY — Don't Repeat Yourself

Los Code Resources existen por algo. El día que tenés el mismo check de consent de 40 líneas pegado en cuatro CloudPages, te debés a vos mismo un refactor.

5. Plano es mejor que anidado. Disperso es mejor que denso.

Tres Automations planas le ganan a un orchestrator anidado. Tres queries SQL con nombres descriptivos le ganan a una query de 200 líneas con sub-selects.

-- Plano: tres pasos, cada uno una pregunta con un nombre

-- 1) elegibilidad
INSERT INTO eligible_subs
SELECT s.SubscriberKey
FROM master s
WHERE s.Status = 'Active' AND s.LoyaltyTier IN ('gold','silver');

-- 2) supresión
INSERT INTO send_audience
SELECT e.*
FROM eligible_subs e
LEFT JOIN suppression x ON e.SubscriberKey = x.SubscriberKey
WHERE x.SubscriberKey IS NULL;

-- 3) deduplicación por email
INSERT INTO send_audience_dedup
SELECT MAX(SubscriberKey) AS SubscriberKey
FROM send_audience
GROUP BY EmailAddress;

Cada paso se puede debuggear solo. Cada conteo de filas te dice qué paso perdió subscribers. Tres queries planas con outputs nombrados le ganan a una query con tres capas de WHERE y una CTE que nadie testeó.

6. La legibilidad cuenta.

Código sin comentarios donde el POR QUÉ no es obvio es la mitad de un código. El CÓMO está en el código mismo; el POR QUÉ está en por qué existe esta rama, por qué este throttle, por qué este fallback.

// MAL
if (n > 50000) Platform.Function.Sleep(2000);

// BIEN
// Throttle: la API transaccional de envíos de SFMC tira requests
// arriba de ~25k/min bajo el cuota actual del MID. Dormimos 2s
// cada 50k filas para quedar abajo de eso — medido 2026-03 contra
// el tenant de producción después de un pico de soft-bounce.
// Revisar cuando cambie el SAP.
if (n > 50000) Platform.Function.Sleep(2000);

La primera versión es una línea. La segunda es la misma línea más el recibo que le permite al próximo dev cambiarla con seguridad.

7. Las convenciones de nombres cuentan doble.

de_master_subscriber le dice al próximo dev qué representa la fila. Subscribers_v2_final_USE_THIS es una migración desde algún lugar sin especificar hacia algún lugar sin terminar.

Una implementación de Cleon tiene una convención de nombres escrita antes de crear el primer DE:

| Prefijo | Qué contiene | |---|---| | DE_ | Data Extension (master, propiedad de la implementación) | | de_stg_ | DE de staging — se reconstruye en cada corrida | | de_log_ | Log de corrida — append-only, indexado por fecha | | TS_ | Triggered Send Definition | | J_ | Journey | | Auto_ | Automation | | CR_ | Code Resource |

Decidí una vez, antes de que exista el primer DE. Renombrar 200 después es la alternativa.

8. Los casos especiales no son especiales como para romper las reglas. Aunque la practicidad le gana a la pureza.

La emergencia de deliverability significa que vas a saltearte tu propia regla de QA una vez. La campaña de adquisición necesita un Send para el jueves y el ciclo de testing es de cuatro días. Sí, vas a cortar un atajo.

9. Los errores nunca deberían pasar en silencio. A menos que los silencies a propósito.

// MAL — el error desaparece, el log queda mudo, te enterás por el cliente
try {
  Platform.Function.UpsertData("master_subs",
    ["SubscriberKey"], [key],
    ["Status","UpdatedAt"], [status, Now()]);
} catch (e) { /* ignorar */ }

// BIEN — silencioso solo después de loguear la razón
try {
  Platform.Function.UpsertData("master_subs",
    ["SubscriberKey"], [key],
    ["Status","UpdatedAt"], [status, Now()]);
} catch (e) {
  // Caso conocido: SubscriberKey rancia de un DE borrado.
  // Lo logueamos, no lo tiramos como excepción, porque el
  // Automation diario de reconciliación lo va a levantar.
  Platform.Function.UpsertData("de_log_errors",
    ["RunId","Step","Msg","Ts"],
    [runId, "upsert-master", e.message, Now()]);
}

El costo de la segunda versión es un DE más cuatro líneas de código. El ahorro es el próximo post-mortem que no tenés que hacer.

10. Frente a la ambigüedad, rechazá la tentación de adivinar. Incluso cuando estés seguro, testeá.

La documentación oficial de Salesforce está bien la mayoría del tiempo y se equivoca con la truncación por longitud de campo, el comportamiento del throttling bajo carga, y las reglas exactas de re-entry de un Journey en edge cases específicos.

La disciplina:

  1. Testeá contra tus datos reales, no contra una muestra de happy-path.
  2. Mandá a un seed antes de mandar a un millón.
  3. Leé el Send Log, no solo el resumen del dashboard.
  4. Cuando la doc no concuerda con el sistema, anotá cuál tuvo razón y la fecha.

11. Ahora es mejor que nunca. Aunque nunca suele ser mejor que ya mismo.

Entregá la pieza chica esta semana, no la plataforma perfecta el próximo trimestre. El AMPscript que funciona para un Email Send hoy es más útil que un "framework" que resuelve cada caso futuro pero nunca llega a revisión.

Pero: no entregues un SSJS "temporal" que después se convierta en fundamento. Marcá el código temporal con una fecha de expiración y un recordatorio en calendario.

// TEMPORAL — reemplazar antes del 2026-06-15
// (recordatorio en calendario seteado el 2026-05-15)
// Razón: sender ID hard-codeado hasta que el nuevo SAP termine
// la verificación.
var senderId = 1234567;

El recordatorio es lo que hace que "temporal" sea honesto.

12. Si la implementación es difícil de explicar, es una mala idea. Si la implementación es fácil de explicar, puede ser una buena idea.

Si no podés explicar tu Journey a un stakeholder no técnico en 30 segundos — qué lo dispara, quién entra, qué recibe, cuándo sale — simplificá antes del launch.

El stakeholder que no puede seguir tu Journey hoy es el mismo que no va a poder defender su presupuesto el próximo trimestre. El test de los 30 segundos es no negociable en cada Journey de Cleon antes del go-live.

13. Documentar es una idea infernalmente buena — hagamos más.

Cada implementación que entrega Cleon tiene una doc operativa de una página que el equipo del cliente puede leer un lunes a la mañana. El template:

  • Qué hace este Journey — un párrafo en términos de negocio
  • Quién entra — nombre del Data Extension y criterio de entrada
  • Qué reciben — Email Send Definitions en orden de envío
  • Cuándo salen — criterio de salida y duración esperada
  • Cómo pausarlo — nombre de la Automation, nombre del botón, screenshot
  • Cómo hacer rollback del último Send — comando de revert, tiempo de recuperación
  • A quién llamar — punto de contacto Cleon y cadena de escalación

Código sin docs es una situación de rehén — el dev tiene en la cabeza el conocimiento operativo que el cliente pagó. Cleon escribe la doc porque la implementación no está terminada hasta que la próxima persona puede correrla sin nosotros.


Cierre

No son reglas para memorizar. Son el músculo que se construye cuando los mismos tipos de errores vuelven a morder a escala. Las implementaciones de MC que entrega Cleon están escritas con esto en la cabeza — y también las que van a producción en nuestros clientes.

Si encontrás una violación a alguno de estos principios en nuestro trabajo, escribinos a hello@wearecleon.com — lo corregimos y lo decimos.