VP_ARCHITECT

The Architect's Toolkit.

Repositório definitivo de snippets de alta performance, queries complexas e limites de plataforma para Salesforce Marketing Cloud.

CTRL + K
ℹ Smart Copy: Clique em "Copy Clean" nos cards para exportar apenas a sintaxe funcional para sua clipboard, ignorando textos didáticos.

01. Data Retrieval & SQL

Dissecar ↗

Deduplicação Determinística

Garante que apenas o registro mais recente sobreviva ao filtro.

/* 1. Subquery cria 'rn' (Row Number) particionado por Email.
2. ORDER BY ModifiedDate DESC garante que o mais recente seja rn = 1.
3. A query externa filtra apenas os registros principais. */
SELECT
    SubscriberKey,
    EmailAddress,
    Status
FROM (
    SELECT
        SubscriberKey,
        EmailAddress,
        Status,
        ROW_NUMBER() OVER(
            PARTITION BY EmailAddress 
            ORDER BY ModifiedDate DESC
        ) AS rn
    FROM [Base_Principal]
) AS sub
WHERE rn = 1

Anti-Join (Filtro de Exclusão)

Padrão mais eficiente para exclusão (Ex: Quem NÃO abriu nos últimos 30 dias).

/* 1. LEFT JOIN com a Data View alvo.
2. Filtro de data posicionado na condição do JOIN (ON).
3. WHERE IS NULL isola os contatos sem correspondência. */
SELECT 
    s.SubscriberKey,
    s.EmailAddress
FROM [Base_Envio_Ativa] s
LEFT JOIN [_Open] o 
    ON s.SubscriberKey = o.SubscriberKey
    AND o.EventDate >= DATEADD(day, -30, GETDATE())
WHERE o.SubscriberKey IS NULL

Journey Builder Tracking Join

Mapeamento para associar um envio ao nome específico da Jornada e da Atividade.

/* A chave de ligação é o TriggererSendDefinitionObjectID.
Sempre inclua ja.ActivityType IN ('EMAIL','EMAILV2') para evitar duplicidades. */
SELECT
    s.SubscriberKey,
    s.EventDate AS SendDate,
    j.JourneyName,
    ja.ActivityName
FROM [_Sent] s
INNER JOIN [_JourneyActivity] ja 
    ON s.TriggererSendDefinitionObjectID = ja.JourneyActivityObjectID
INNER JOIN [_Journey] j 
    ON ja.VersionID = j.VersionID
WHERE j.JourneyName = 'Welcome_Journey_2026'
AND ja.ActivityType IN ('EMAIL', 'EMAILV2')
Dissecar ↗

Random Split para A/B Testing

Uso de NTILE para dividir uma base aleatoriamente em percentuais exatos (Holdout/Test).

/* 1. NTILE(X) divide a base em X grupos iguais.
2. ORDER BY NEWID() garante a aleatoriedade da amostragem. */
SELECT 
    SubscriberKey,
    EmailAddress,
    CASE 
        WHEN SplitGroup = 1 THEN 'Grupo_A'
        WHEN SplitGroup = 2 THEN 'Grupo_B'
        ELSE 'Grupo_C'
    END AS Test_Variant
FROM (
    SELECT 
        SubscriberKey,
        EmailAddress,
        NTILE(3) OVER(ORDER BY NEWID()) AS SplitGroup
    FROM [Base_Elegivel_Campanha]
) AS Amostragem

02. Personalization & AMPscript

Dissecar ↗

Lookup Defensivo + Erro Controlado

Impede erros de renderização globais. Isola a falha apenas no registro afetado.

%%[
/* 1. Declaração limpa o escopo na iteração do Batch */
VAR @subKey, @rows, @rowCount, @row, @nome
SET @subKey = AttributeValue("_subscriberkey")

IF NOT EMPTY(@subKey) THEN
    SET @rows = LookupRows("Customer_Data", "Id", @subKey)
    SET @rowCount = rowcount(@rows)

    IF @rowCount > 0 THEN
        SET @row = row(@rows, 1)
        SET @nome = field(@row, "FirstName")
    ELSE
        SET @nome = "Cliente"
    ENDIF
ELSE
    /* RaiseError com 'true' aborta apenas este e-mail, preservando o Job */
    RaiseError("SubscriberKey não encontrado", true)
ENDIF
]%%
Olá %%=v(@nome)=%%,
Dissecar ↗

Iteração NATIVA de JSON (API Events)

Varrer arrays enviados via API de Injeção usando BuildRowsetFromJson.

%%[
/* Payload ex: {"Carrinho": [{"Item":"Celular","Preco":2000}]} */
VAR @jsonPayload, @carrinhoRowset, @i, @item, @preco

SET @jsonPayload = AttributeValue("Carrinho_String_JSON")

IF NOT EMPTY(@jsonPayload) THEN
    SET @carrinhoRowset = BuildRowsetFromJson(@jsonPayload, "$.Carrinho[*]", 1)
    
    IF rowcount(@carrinhoRowset) > 0 THEN
        FOR @i = 1 TO rowcount(@carrinhoRowset) DO
            SET @row = row(@carrinhoRowset, @i)
            SET @item = field(@row, "Item")
            SET @preco = field(@row, "Preco")
            
            Output(Concat("<br>Produto: ", @item, " | R$ ", @preco))
        NEXT @i
    ENDIF
ENDIF
]%%

03. SSJS & WSProxy

WSProxy UpsertData Batch

Insere ou atualiza múltiplos registros via SOAP API (Alta performance).

<script runat="server">
Platform.Load("Core", "1.1.1");
try {
    var prox = new Script.Util.WSProxy();
    var deCustomerKey = "Log_Transacional";
    
    var rows = [
        {
            CustomerKey: deCustomerKey,
            Properties: [
                { Name: "LogID", Value: Platform.Function.GUID() },
                { Name: "Status", Value: "Processado" }
            ]
        }
    ];

    var options = { SaveOptions: [{ PropertyName: "*", SaveAction: "UpdateAdd" }] };
    var res = prox.updateBatch("DataExtensionObject", rows, options);

} catch(e) {
    Write("Error: " + Stringify(e));
}
</script>
Dissecar ↗

HTTP Request POST (Webhooks)

Fundamental para integrações externas em Script Activities (n8n/API).

<script runat="server">
Platform.Load("Core", "1.1.1");

var payload = Stringify({
    event: "sync_trigger",
    timestamp: new Date()
});

var req = new Script.Util.HttpRequest("https://seu-endpoint.com/webhook");
req.emptyContentHandling = 0;
req.retries = 1;
req.continueOnError = true;
req.contentType = "application/json";
req.method = "POST";
req.postData = payload;
req.setHeader("Authorization", "Bearer token_secure_aqui");

var resp = req.send();
</script>

04. Email Dev & Campaign Ops

Dissecar ↗

Bulletproof Email Boilerplate

Suporte a Dark Mode e correção de DPI Scaling no Outlook via VML.

%%[
/* Sempre inicialize variáveis de sistema para evitar quebras em Preview */
VAR @subscriberKey, @emailAddress
SET @subscriberKey = AttributeValue("_subscriberkey")
SET @emailAddress = AttributeValue("emailaddr")
]%%
<!DOCTYPE html>
<html lang="pt-BR" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="color-scheme" content="light dark">
    <meta name="supported-color-schemes" content="light dark">
    
    <!--[if mso]>
    <xml>
      <o:OfficeDocumentSettings>
        <o:AllowPNG/>
        <o:PixelsPerInch>96</o:PixelsPerInch>
      </o:OfficeDocumentSettings>
    </xml>
    <style>table {border-collapse: collapse;}</style>
    <![endif]-->
    
    <style>
        body, table, td, a { -webkit-text-size-adjust: 100%; -ms-text-size-adjust: 100%; }
        table, td { mso-table-lspace: 0pt; mso-table-rspace: 0pt; }
        img { -ms-interpolation-mode: bicubic; border: 0; outline: none; }
    </style>
</head>
<body style="margin: 0; padding: 0; background-color: #f4f4f4;">
    <!-- Ghost Table fixa a largura no Outlook Windows -->
    <!--[if mso | IE]>
    <table role="presentation" border="0" cellpadding="0" cellspacing="0" width="600" align="center" style="width:600px;">
      <tr><td style="line-height:0px;font-size:0px;mso-line-height-rule:exactly;">
    <![endif]-->
    
    <div style="max-width: 600px; margin: 0 auto;">
        <!-- Conteúdo do E-mail -->
    </div>

    <!--[if mso | IE]>
      </td></tr>
    </table>
    <![endif]-->
</body>
</html>
Dissecar ↗

Dynamic Tracking URLs (UTMs)

Geração de links parametrizados preservando o encapsulamento nativo de cliques do SFMC.

%%[
VAR @baseUrl, @campanha, @finalUrl
SET @baseUrl = "https://www.site.com.br/promo"
SET @campanha = AttributeValue("Nome_Campanha")

/* Concatena URL base com tags UTMs dinâmicas */
SET @finalUrl = Concat(@baseUrl, "?utm_source=sfmc&utm_medium=email&utm_campaign=", @campanha)
]%%

<!-- A função RedirectTo() é obrigatória para o SFMC rastrear o clique -->
<a href="%%=RedirectTo(@finalUrl)=%%" alias="Botao_Principal">
    Aproveitar Oferta
</a>

05. Platform Limits Cheat Sheet

Componente / Data View Limitação (Hard/Soft) Observação Técnica
SQL Query Activity 30 minutos (Timeout) Queries em DEs > 10M linhas sem Primary Keys indexadas falham por Timeout quase sempre.
Data Views (_Open, _Click, _Sent) Retenção = 6 Meses Para tracking histórico contínuo, é mandatório automatizar a extração para Data Extensions de Log.
Script Activity (SSJS) 30 minutos (Timeout) Evite loops com `DataExtension.Retrieve()`. Use `WSProxy RetrieveBatch()` para evitar timeouts.
Journey Builder API Entry ~ 2.5M eventos por hora A velocidade de injeção cai dependendo do número de Decision Splits no início da jornada.