The Architect's Toolkit.
Repositório definitivo de snippets de alta performance, queries complexas e limites de plataforma para Salesforce Marketing Cloud.
01. Data Retrieval & SQL
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')
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
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)=%%,
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>
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
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>
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. |