Funciones de Subscriber + Profile — referencia de Marketing Cloud AMPscript
AttributeValue, _subscriberKey, _emailaddress, _jobid, _messagecontext, y el resto del contexto que AMPscript hereda del send que lo rodea. Qué devuelve cada uno, cuándo está disponible, y la diferencia entre Subscriber Attributes, columnas de DE, y variables locales.
La superficie de Subscriber y Profile es cómo AMPscript lee el contexto del render actual — quién es el destinatario, qué JobID está corriendo, si esto es un send real o un preview, qué hay en el perfil All Subscribers para esta persona. La mayoría de la superficie son variables especiales (el prefijo _var, sin paréntesis) más que llamadas a funciones. Compacta, predecible cuando sabés qué contextos populan qué valor, y una fuente mayor de confusión la primera vez que un bloque AMPscript en una CloudPage trata de usar _jobid y obtiene NULL.
Esta página es el inventario más lo que devuelve cada variable especial entre los contextos de render (email send vs CloudPage vs Mobile vs preview).
Sintaxis oficial
%%[
/* Variables especiales — sin prefijo @, sin paréntesis */
SET @subKey = _subscriberKey
SET @email = _emailaddress
SET @jobId = _jobid
SET @listId = _listid
SET @msgCtx = _messagecontext /* "Send" / "Preview" / "Test" */
SET @userId = _userid /* el usuario API/UI que lo disparó (si está disponible) */
/* AttributeValue — lee del perfil Subscriber Attribute,
NO de una columna de DE con el mismo nombre */
SET @firstName = AttributeValue("FirstName")
SET @region = AttributeValue("Region")
/* RetrieveSalesforceObjects — lee desde Sales/Service Cloud
(cubierto en detalle en la página de referencia de Cloud-write) */
SET @leadStatus = Field(
Row(
RetrieveSalesforceObjects(
"Lead",
"Status",
"Id", "=", @leadId
),
1
),
"Status"
)
]%%
<p>Hola %%=v(@firstName)=%% (Subscriber Key: %%=v(@subKey)=%%).</p>La superficie soportada:
| Nombre | Qué devuelve | Disponible en |
|---|---|---|
| _subscriberKey | El SubscriberKey del destinatario actual | Email send, Mobile, CloudPage con _subscriberkey en URL |
| _emailaddress | El email del destinatario actual | Solo email send; NULL en CloudPages a menos que se setee explícito |
| _jobid | El JobID del Send que está corriendo | Solo email send; NULL en preview y CloudPage |
| _listid | El ID de la List o DE que potenció el send | Solo email send |
| _messagecontext | "Send", "Preview", "Test", etc. | Email send + preview |
| _messagetypepreference | La preferencia HTML vs Text del destinatario | Solo email send |
| _userid | El usuario API/UI que disparó la acción | Frecuentemente NULL en sends normales |
| JobID() | Forma-función de _jobid | Mismas reglas de contexto |
| AttributeValue(attrName) | El valor del Subscriber actual para el Subscriber Attribute nombrado | Email send + CloudPage cuando _subscriberkey está presente |
Referencia:
- AMPscript Guide — referencia de funciones (sección subscriber/profile) ↗
- Salesforce Developer — funciones AMPscript ↗
Lo que sobrevive en producción
_subscriberKey vs _emailaddress — elegí uno como identificador estable
Un DE sendable tiene dos formas de identificar al destinatario:
- SubscriberKey — el ID interno estable de Marketing Cloud para el subscriber. Misma persona, misma key entre todos los sends.
- EmailAddress — el email. La misma persona puede cambiar de email (evento re-key); la dirección en sí puede cambiar.
AMPscript expone los dos vía _subscriberKey y _emailaddress. La convención Cleon: siempre keyeá la personalización y los lookups por _subscriberKey, nunca por _emailaddress. Las direcciones de email cambian; los subscriber keys están pensados para ser estables.
%%[
/* DURABLE — joinea sobre identificador estable */
SET @segment = Lookup("master_segments", "Tier", "SubscriberKey", _subscriberKey)
/* EN RIESGO — la dirección de email puede haber cambiado desde que se escribió la fila del segmento */
SET @segment = Lookup("master_segments", "Tier", "EmailAddress", _emailaddress)
]%%Si el DE sendable está keyeado por email (raro pero pasa en implementaciones legacy), la SQL Activity upstream debería ya haber computado SubscriberKey como columna. AMPscript lee esa columna, no el email crudo.
_jobid es NULL en preview y en CloudPages
El preview de Email Studio no corre un JobID real — _jobid resuelve a NULL. Las CloudPages no corren adentro de un Send, así que _jobid también es NULL ahí. Código que depende del JobID para writes de log o renderizado condicional falla silenciosamente fuera del send real.
%%[
/* EN RIESGO — _jobid es NULL en preview; la fila de log se escribe con
JobID = NULL, el cuerpo del email renderea bien, el bug se manifiesta
solo después del send de producción cuando las queries de auditoría
no pueden correlacionar filas por JobID */
InsertData(
"de_log_engagement",
"JobID", _jobid,
"SubscriberKey", _subscriberKey,
"Action", "render",
"Ts", Now()
)
/* DEFENSIVO — guardar contra render en preview-time */
IF NOT Empty(_jobid) THEN
/* solo loggear en sends reales */
InsertData(
"de_log_engagement",
"JobID", _jobid,
"SubscriberKey", _subscriberKey,
"Action", "render",
"Ts", Now()
)
ENDIF
]%%La variable _messagecontext es el chequeo más limpio: devuelve "Send" para sends reales y "Preview" para el path de preview. Ramificá sobre _messagecontext cuando el comportamiento renderado deba diferir.
_messagecontext es el único chequeo confiable de preview-vs-send
%%[
/* "Send", "Preview", "Test", etc. */
IF _messagecontext == "Send" THEN
/* Send de producción real — log + cloud-write son seguros de correr */
InsertData(
"de_log_engagement",
"JobID", _jobid,
"SubscriberKey", _subscriberKey,
"Action", "render",
"Ts", Now()
)
ENDIF
]%%Los valores son tenant-estables como para apoyarse en ellos, pero no case-estables entre tenants — "Send" en un tenant puede ser "send" en otro. Usá Lowercase() en la comparación para estar seguro:
%%[
IF Lowercase(_messagecontext) == "send" THEN
/* portátil entre tenants */
ENDIF
]%%Esta es la herramienta más útil sola para mantener limpio el comportamiento del preview. El preview nunca debería escribir a tus DEs de log, nunca llamar a UpdateSingleSalesforceObject, nunca entregar códigos de claim. Envolvé cada bloque con side-effects en un gate _messagecontext == "Send".
AttributeValue lee del perfil Subscriber Attribute, no de columnas de DE
Reforzado del gotcha #4 porque es el patrón más confuso solo en el lenguaje para devs nuevos de AMPscript:
AttributeValue("FirstName")lee del atributoFirstNamedel perfil All Subscribers. Esto no es lo mismo que la columnaFirstNamedel DE sendable.%%FirstName%%(inline, sin@) típicamente lee de la columna del DE sendable con ese nombre.%%=v(@FirstName)=%%lee la variable local.
Cuando las tres se llaman igual, la resolución en render time no siempre es intuitiva y te pasás una hora preguntándote por qué la personalización "se ve bien" pero matchea la fuente equivocada.
%%[
/* DURABLE — nombrá las fuentes distinto así la fuente es obvia */
SET @subFirstName = AttributeValue("FirstName") /* perfil */
SET @deFirstName = AttributeValue("DEFirstName") /* columna de DE con prefijo */
SET @localFirstName = "Mariana" /* local */
]%%La defensa que lista la página de gotchas: nombres distintos. La defensa que esta página agrega: elegí una fuente por email y quedate con ella. Si tu SQL Activity de audience-build está computando FirstName al DE sendable, esa es la fuente — leé %%[FirstName]%% y ignorá el perfil. Si querés leer del perfil, nombrá la columna del DE distinto para que la confusión sea imposible.
_listid es el ID de la fuente sendable, no la List de All Subscribers
_listid devuelve el ID del DE (o list rara) que potenció el send — no la list All Subscribers. Este naming es legacy de cuando las "Lists" eran la fuente primaria de audiencia; hoy casi cada send es desde un DE, y _listid devuelve el CustomerKey/ID del DE.
%%[
/* @listId es el ID del DE sendable, útil para audit logging */
SET @listId = _listid
InsertData(
"de_log_sends",
"JobID", _jobid,
"ListId", @listId,
"Action", "render",
"Ts", Now()
)
]%%No esperes que esto sea human-readable en tenants MC legacy; es un ID opaco. Usalo para cross-referenciar, no para mostrar a subscribers.
Nombres de Subscriber Attribute con espacios o caracteres especiales
El perfil All Subscribers permite nombres de atributo con espacios y caracteres inusuales ("First Name", "Customer ID #"). AttributeValue acepta el nombre exacto como string, así que el quoting maneja los espacios:
%%[
SET @firstName = AttributeValue("First Name") /* perfil legacy con espacio */
SET @customerId = AttributeValue("Customer ID #") /* legacy con chars especiales */
]%%La convención Cleon: cuando diseñes Subscriber Attributes nuevos, usá lowercase-snake-case o PascalCase sin espacios ni caracteres especiales. La falla del hand-off: un atributo de perfil llamado "First Name" (con espacio) aparece como un placeholder %%First Name%% en el email, que no interpola de la misma manera que un nombre sin espacio. El resolvedor de atributo inline de AMPscript tiene problemas con espacios. Las llamadas AttributeValue con quoting siempre funcionan.
_emailaddress en una CloudPage — usualmente NULL
En una CloudPage rendereada desde una URL como /cp/preferences?_subscriberkey=abc123, _subscriberKey se popula desde la URL pero _emailaddress no se resuelve automáticamente. Para conseguir el email en contexto de CloudPage, hacé un Lookup contra la list All Subscribers (o contra tu DE master):
%%[
/* Contexto CloudPage */
SET @subKey = _subscriberKey /* desde URL */
SET @email = _emailaddress /* frecuentemente NULL en CP */
IF Empty(@email) THEN
/* Fallback: buscar el email por SubscriberKey */
SET @email = Lookup("master_subscribers", "EmailAddress", "SubscriberKey", @subKey)
ENDIF
]%%La falla del hand-off: AMPscript copiado de un template de email que lee _emailaddress directo se cae en una CloudPage, el email aparece en blanco, y alguien se pasa una hora preguntándose por qué el mismo código andaba ayer. El contexto cambió; la disponibilidad de la variable cambió con él.
Decisión rápida
Usá _subscriberKey cuando:
- Necesitás un identificador estable per-destinatario. Siempre preferí este sobre
_emailaddress.
Usá _emailaddress cuando:
- Específicamente necesités la dirección de email en sí para personalización (el patrón "tu email en archivo"). Si no, preferí el patrón SubscriberKey + Lookup.
Usá _jobid cuando:
- Writes de logging o audit-trail que necesitan correlacionar filas al send específico. Guardalo con chequeo
Empty()o gate_messagecontext.
Usá _messagecontext cuando:
- Gateás código con side-effects (writes, claims, cloud-writes). Lowercaseá la comparación para portabilidad.
Usá AttributeValue cuando:
- El data vive en el perfil Subscriber Attribute y no en el DE sendable. Quoteá el nombre; maneja espacios y caracteres especiales.
Usá referencias de columna del DE sendable (%%Col%% o %%[Col]%%) cuando:
- El data está en el DE sendable que potenció el Send. Más rápido que
AttributeValue(sin lookup al perfil) y más claro sobre la fuente.
Usá un Lookup con _subscriberKey cuando:
- El data está en un DE distinto keyeado por SubscriberKey. Pre-formateá upstream donde se pueda para evitar lookups per-destinatario.
Relacionado
- Basics — superficie del lenguaje soportada
- Funciones de Data Extension —
Lookuppara resolver valores que no están en el DE sendable - Funciones de validación —
Empty()para defaultear lecturas deAttributeValue - Gotchas de MC AMPscript — ver #4 (confusión AttributeValue vs columna de DE vs var local) y #9 (preview ≠ send para variables de contexto)
- MC SSJS — Util / Variable / Request — la superficie SSJS hermana para leer contexto (
Variable.GetValue,Request.GetQueryStringParameter, el namespaceUtil.*)
Más páginas de referencia AMPscript en camino: Cloud-write · Encoding/Hashing · Style Guide.