Basics — Fundamentos de SSJS en Marketing Cloud
Dónde corre SSJS en Marketing Cloud, qué runtime tenés realmente (SpiderMonkey 1.7), y los dos contextos principales — rendering de CloudPage vs Script Activity de Automation — que deciden los patrones que usás.
SSJS (Server-Side JavaScript) es el lenguaje de scripting que Marketing Cloud usa donde AMPscript no llega: CloudPages dinámicas, callouts complejos, orquestación multi-paso en Automations, manipulación programática de DEs. Corre sobre SpiderMonkey 1.7 — el motor JavaScript de 2007 — con una API Platform.* específica de Salesforce encima. La mayoría de lo que escribís es la API Platform; el JS de abajo es mayormente plomería.
Esta página es la orientación. El resto del catálogo SSJS (Platform, WSProxy, categorías de funciones, Style Guide) se construye sobre este modelo mental.
Sintaxis oficial
Un bloque SSJS vive adentro de tags <script runat="server">...</script>. Puede aparecer en tres contextos:
<!-- 1. CloudPage — output HTML rendereado -->
<!DOCTYPE html>
<html>
<body>
<script runat="server">
Platform.Load("Core", "1.1.5");
var name = Request.GetQueryStringParameter("name");
Write("<h1>Hola, " + name + "</h1>");
</script>
</body>
</html>
<!-- 2. Script Activity de Automation Studio — corre en una Automation scheduleada -->
<script runat="server">
Platform.Load("Core", "1.1.5");
var subscriberKey = "12345";
var rows = Platform.Function.LookupRows(
"master_subscribers",
"SubscriberKey",
subscriberKey
);
Platform.Function.UpsertData(
"de_log_runs",
["RunId"], [Platform.Function.GUID()],
["Step","Ts"], ["lookup", Now()]
);
</script>
<!-- 3. Bloque script de Email Studio — raro, mayormente para casos AMPscript-too-complex -->
<script runat="server" language="javascript">
Platform.Load("Core", "1.1.5");
var personalized = Variable.GetValue("@firstName") + ", welcome";
</script>La primera línea de cada bloque SSJS tiene que ser Platform.Load("Core", "1.1.5"). Sin esto, el namespace Platform.* entero no está definido y el script falla con un error confuso Platform is not defined (ver gotchas — #2).
La superficie de lenguaje soportada:
| Feature | Disponible |
|---|---|
| var, function, loops tradicionales | ✓ |
| Math, métodos básicos de String / Array / Date (era ES5) | ✓ |
| try / catch / throw | ✓ |
| Expresiones regulares | ✓ |
| let / const | ✗ (SyntaxError) |
| Arrow functions | ✗ |
| Template literals | ✗ |
| Destructuring / spread / rest | ✗ |
| Promise / async / await | ✗ |
| JSON.parse / JSON.stringify | ✗ en tenants viejos — usá Platform.Function.ParseJSON() |
| console.log | ✗ — usá Write() (CloudPage) o escrituras a DE de log (Automation) |
Referencia:
- Salesforce Developer — Overview de SSJS ↗
- Salesforce Developer — Referencia de Platform Functions ↗
- Salesforce Help — SSJS en mensajes de email ↗
Lo que sobrevive en producción
Dos contextos, dos modelos mentales
El mismo código SSJS se comporta distinto según dónde corra. Tené el modelo mental correcto antes de escribir el script.
SSJS en CloudPage:
- El output va al HTML rendereado vía
Write()(y output automático del HTML literal entre bloques de script). - Un usuario hizo click en un link; tenés ~30 segundos antes de que el browser se rinda (bien debajo del límite duro de 30 min, pero la UX importa).
- Los errores rendean en la página misma salvo que los atrapes.
- Stateless por request — sin sesión salvo que la construyas vos con cookies + storage en DE.
Script Activity de Automation Studio:
- Sin output que nadie vea. Todo "logging" son escrituras a un Data Extension
de_log_*. - Timeout duro de 30 minutos (ver gotchas — #3).
- Corre como parte de una cadena de Automation (típicamente: SQL Query → Script → Send → Log).
- Los errores fallan el paso de la Activity pero no se propagan al siguiente paso salvo que leas el status de la Activity y reacciones.
Los patrones que usás difieren. Una CloudPage usa Write() para output; una Script Activity loguea a un DE. Una CloudPage maneja input de usuario vía Request.GetQueryStringParameter(); una Script Activity lee inputs de un DE de "config" que la Automation upstream escribió.
Platform.* es la API; todo lo demás es plomería
El namespace de API específico de Salesforce (Platform.*) es lo que te permite hacer trabajo real. JS plano te da control flow, math, loops; Platform.Function.* te da DE Lookup/Add/Update/Delete, generación de GUID, encriptación, parseo de JSON, fecha actual, y el resto. Casi cada línea SSJS interesante es una llamada Platform.Function.*.
Platform.Load("Core", "1.1.5");
// JS plano — control flow
var subKey = "12345";
var status = "Active";
// Platform.* — trabajo real
var rows = Platform.Function.LookupRows("master_subs", "SubscriberKey", subKey);
if (rows.length > 0) {
Platform.Function.UpdateData(
"master_subs",
["SubscriberKey"], [subKey],
["Status", "UpdatedAt"], [status, Now()]
);
} else {
Platform.Function.InsertData(
"master_subs",
["SubscriberKey"], [subKey],
["Status", "CreatedAt"], [status, Now()]
);
}La referencia de qué llamadas Platform.Function.* existen vive en el link de arriba y en la página dedicada de referencia de este catálogo.
WSProxy para acceso a la SOAP API — cuando Platform.Function.* no alcanza
Platform.Function.* es un wrapper de alto nivel sobre un subset de la SOAP API. Cuando necesitás la superficie completa — operaciones bulk, recuperar objetos de Salesforce más allá del scope del wrapper, operaciones async — bajás a WSProxy.
Platform.Load("Core", "1.1.5");
var prox = new Script.Util.WSProxy();
// Recuperar subscribers vía SOAP
var result = prox.retrieve("Subscriber", ["EmailAddress", "Status"], {
Property: "SubscriberKey",
SimpleOperator: "equals",
Value: "12345"
});WSProxy tiene su propia trampa de expiración de auth-token (ver gotchas — #8) y está documentado en la próxima página de referencia de WSProxy.
Output: Write() para CloudPages, escrituras a DE para Automations
No hay console. Los dos mecanismos de output son:
Write("text")— appendea al output de la página (CloudPage) o al Output de la Activity (Automation, pero rara vez visible)Platform.Function.UpsertData("de_log_*", ...)— escribe una fila a un DE de log que vos controlás
La convención Cleon: cada SSJS de producción escribe a un Data Extension de_log_ssjs_runs en cada paso significativo (start, lookup completado, escritura completada, end), con un RunId (típicamente Platform.Function.GUID()), nombre de Step, Message, y Ts. Cuando algo se ve raro, queryeás el log en lugar de tratar de reconstruir desde logs que no existen.
Decisión rápida
Andá con SSJS Script Activity cuando:
- Necesitás control flow que SQL no puede expresar (branching por fila, callouts, orquestación multi-paso).
- Necesitás llamar una API externa y reaccionar a la respuesta.
- Necesitás combinar múltiples lecturas + escrituras de Data Extension en una operación lógica.
Andá con SSJS en una CloudPage cuando:
- Estás construyendo una landing page dinámica (preference center, formulario de supresión, contenido dinámico).
- La página necesita leer o escribir Data Extensions basado en parámetros de URL.
- AMPscript pega contra sus límites (iteración compleja, lógica condicional que se vuelve un quilombo).
Andá con SQL Query Activity cuando:
- El trabajo es lectura + transformación + escritura bulk a través de un Data Extension. SQL es más rápido y más claro para operaciones set-based.
Andá con AMPscript cuando:
- El trabajo es personalización por mensaje en momento de send. AMPscript corre inline en el email, SSJS no.
No uses SSJS cuando:
- En realidad necesitás concurrencia / async real — SSJS es single-threaded síncrono (ver gotchas — #10). Partí el trabajo entre Script Activities paralelas orquestadas por Automation Studio en su lugar.
Relacionado
- MC SSJS gotchas — lo que rompe a escala en cada script
- MC SQL Basics — la página de orientación de la subcategoría hermana
- MC SQL gotchas — muchas de las mismas disciplinas operativas aplican
Próximas páginas de referencia SSJS: Platform Functions · WSProxy · Variable + Util · Funciones de String / Date / Util · Style Guide.
Más snippets how-to para patrones comunes de producción — DE add/update/upsert, manejo de errores, paginación de callouts, etc.