C00 β Start Here & How to Win This Interview
π― Why Coforge cares: this is a Technical Lead, financial-services, run-the-platform role. They want someone who can build, troubleshoot, and lead β and who answers practically, not just in theory. This crash course is engineered for fast recall and hands-on confidence.
π§ One-screen mental model β the whole interview
COFORGE SFMC TECHNICAL LEAD
β
βββββββββββββββββΌββββββββββββββββ
BUILD RUN LEAD
(develop) (support) (own it)
β β β
Email Studio INC tickets design + trade-offs
Journey Bldr RCA + SLA mentoring
AMPscript troubleshoot stakeholder comms
DE/SQL/Auto MOD (CRM) financial-svc compliance
APIs critical issues estimation / peak
β β β
βββββ say it as: THEORY + "β¦and in practice I'dβ¦" βββββ
The one habit that wins this interview: every answer = a crisp definition β then "β¦and in practice, here's exactly what I'd click/write." That second half is what was missing last time. This course drills it into every module.
πΊοΈ The Coforge JD β which module
| JD line | Module(s) |
|---|---|
| Email campaigns & journeys (Email Studio + Journey Builder) | C05, C06 |
| Dynamic content via AMPscript + personalization | C04 |
| Data Extensions, SQL, Automation Studio | C02, C03 |
| Campaign validation, testing, preview, deployment | C07 (practical core) |
| Distributed marketing / advisor communications | C08 (JD-critical) |
| Data accuracy & segmentation | C02, C03 |
| Handle INC tickets (SFMC + MOD/CRM), RCA, SLA, critical issues | C10 (JD-critical) |
| SFMC APIs | C09 |
| Financial-services domain + Technical-Lead behaviours | C12 |
| Deliverability & compliance | C11 |
| Big-picture / draw-it-on-a-whiteboard | C01 |
| Cram everything | C13 (Memory Vault) |
| Fix the "too theoretical" problem | C14 (Practical Drills + Mock) |
π― The "Theory + Practical" answer formula (your LTM fix)
For ANY question, answer in 3 beats:
1. WHAT it is β one-sentence definition.
2. HOW it works β the mechanism / why.
3. IN PRACTICE β "I'd go to <Studio> > <screen> > <button>, set X,
test with Preview & Test, and verify in Tracking."
Example β "How do you personalise an email?"
- What: AMPscript resolves per-subscriber values at send time.
- How: Lookup/LookupOrderedRows pull from a DE; IF/ELSE branches content.
- In practice: "In Content Builder I drop an HTML block, paste the AMPscript, guard every value with EMPTY() + a fallback, then Preview & Test against a real subscriber row and send a proof to my seed list before scheduling."
β‘οΈ Practise this shape out loud for every rapid-fire Q in the course.
π§© Master mnemonics (the spine β full list in C13)
- BUILD / RUN / LEAD β the three hats this role wears (above).
- Send flow = CAESPST β Content β Audience β Exclusions β Send-class β Preview β Send β Track (C05).
- DE types = "Some Sendable Sharks Find Small Snacks" β Standard, Sendable, Shared, Filtered, Synchronized, Salesforce DE (C02).
- RCA = REPAIR-VP (RIRFVP) β Reproduce, Isolate layer, Root-cause, Fix, Verify, Prevent (C10).
- Isolate the layer = DCRDI β Data β Content β Render β Deliverability β Integration (C10).
- Auth = SPF/DKIM/DMARC β "who's allowed, did it change, what to do if it fails" (C11).
β 12 things you must be able to DO live (not just describe)
- [ ] Create a sendable DE + set the send relationship (click-path) β C02
- [ ] Write a dedup query (
ROW_NUMBER() β¦ rn=1) from memory β C03 - [ ] Write a suppression anti-join (
NOT EXISTS/LEFT JOIN β¦ IS NULL) β C03 - [ ] Build the LookupOrderedRows β RowCount β Row β Field loop blind β C04
- [ ] Preview & Test AMPscript against a real subscriber + debug a blank β C04/C07
- [ ] Build & send a campaign end-to-end; set up an A/B test β C05/C07
- [ ] Build a welcome / advisor-onboarding journey β C06
- [ ] Explain & set up a Distributed Marketing advisor send β C08
- [ ] Get an OAuth token + fire a journey event in Postman β C09
- [ ] Triage a Sev-1 send failure under SLA using RCA β C10
- [ ] Diagnose "delivered but in spam" β C11
- [ ] Tell a STAR story reframed for financial-services / lead lens β C12
π Suggested run order (~3 hours, paced by the timer)
First pass (memorise): C01 β C02 β C04 β C03 β C05 β C06 β C10 β C08. Second pass (depth): C07, C09, C11, C12. Final hour: C13 Memory Vault (all diagrams + mnemonics) β C14 mock out loud.
Tip: hit M to mark anything shaky; it collects in Marked for Review at the end.
π οΈ How to use this reader
- Dark by default (π toggles light). One subsection at a time.
- β / β or Prev/Next to move. / to search the whole course.
- β± Timer auto-paces each section (default 3h goal β change it in the bar). Space pauses for breaks.
- β Mark / M flags a section β see them all in Marked for Review.
- π¨ PDF exports everything if you want it on your phone.
β‘οΈ Next: C01_Big_Picture_Mental_Maps.md
C01 β The Big Picture (mental maps you can draw blind)
π― Why Coforge cares: as the SFMC Technical Lead you'll own campaigns, journeys, Data Extensions, automations and INC/RCA across multiple advisor BUs in a financial-services org β you must be able to whiteboard the whole platform and the data model on demand.
π§ One-screen mental model
βββββββββββββββββββββββββ SFMC (Engagement) βββββββββββββββββββββββββ
β β
STUDIOS = channels (do work) BUILDERS = setup (define data/logic/UI) β
βββββββββββββββββββββββββββββ ββββββββββββββββββββββββββββββββββββββββ β
β Email Studio (email) β β Contact Builder (Contacts, attrs, DEs)β β
β Mobile Studio (SMS/push) β β Journey Builder (orchestration) β β
β Web/Social/Adv Studio β β Content Builder (emails/blocks/images)β β
β Automation Studio (batch) β β Analytics Builder (reports) β β
βββββββββββββββββββββββββββββ ββββββββββββββββββββββββββββββββββββββββ β
β β
ACCOUNT TREE β β
Enterprise (top, shared) ββΆ Parent BU ββΆ Child BU (Advisors-East) ββΆ Child BU(...) β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
THE PERSON: Contact (1 per human, Contact Key) ββownsβββΆ Subscriber (email channel, Subscriber Key)
Contact Key == Subscriber Key (same string; keep it stable!)
THE FLOW: Data Extension ββ(audience)βββΆ Email (AMPscript pulls fields) ββSendβββΆ
SAP/MTA delivers βββΆ Tracking (Opens/Clicks/Bounces) βββΆ Data Views / reports
π Core in 60 seconds
- Studios DO, Builders DEFINE. Studios = channels that act (Email/Mobile/Web/Automation). Builders = where you set up data, journeys, content, reports (Contact/Journey/Content/Analytics).
- Automation Studio is the odd one β named "Studio" but it's your batch engine (scheduled SQL, imports, file drops). Treat it as the back-office workhorse.
- Account tree: Enterprise (top, can share data) β Parent BU β Child BUs. Each BU = a walled garden for users, data, sends. In FinServ you'll often have a BU per advisor segment / region / compliance.
- One human = one Contact (identified by Contact Key). When you email them, the email channel sees them as a Subscriber (identified by Subscriber Key). These two keys are the SAME string.
- All Contacts (Contact Builder, whole account) β All Subscribers (Email Studio). Every subscriber is a contact; not every contact is a subscriber.
- Email flow = DE β personalize β send β track. The DE is the audience + data; AMPscript pulls fields at send time; tracking lands in Data Views (
_Sent,_Open,_Click,_Bounce,_Subscribers). - Subscriber Key is sacred: stable, unique, never reuse, never put the email address in it for FinServ (PII + key churn). Use a CRM/MOD contact id.
π§© Mnemonics & memory hooks
- Studios vs Builders β "Build it, then Studio-use it." You Build the parts (Contact/Journey/Content/Analytics Builder), then a Studio puts them to work on a channel. Builders are nouns, Studios are verbs.
- The 4 Builders β "C-J-C-A: Cab Just Came Around." Contact, Journey, Content, Analytics.
- The Studios β "Every Morning Web Admins Automate" β E-M-W-A: Email, Mobile, Web, Automation. (Hook: an admin every morning automates the channels.)
- Account tree β "EPC: Every Parent's Children." Enterprise β Parent BU β Child BUs.
- Contact vs Subscriber β "Same key, two hats." One person, one Contact Key; put on the "email hat" and that same key is the Subscriber Key.
- Email flow β "D-P-S-T: Don't Push Send Twice." Data Extension β Personalize (AMPscript) β Send β Track.
- Data Views β "SOCBS" β Sent, Open, Click, Bounce, Subscribers. Hook: "Send Often, Check Bounces, Suppress."
π Skeletons to memorize
The signature move of the whole platform: pull a row from a DE and personalize. Memorize this β it proves you know how a DE feeds an email.
%%[
VAR @firstName, @advisor
SET @firstName = [FirstName] /* from sendable DE column */
SET @advisor = Lookup("Advisor_Lookup","AdvisorName","ContactKey", _subscriberkey)
]%%
Hi %%=v(@firstName)=%%, your advisor is %%=v(@advisor)=%%.
π Line by line:
- VAR @firstName, @advisor β declare the variables before using them.
- SET @firstName = [FirstName] β [FieldName] reads a column from the sendable DE (the audience row for this subscriber).
- Lookup("Advisor_Lookup","AdvisorName","ContactKey", _subscriberkey) β fetch one value from another DE (Advisor_Lookup), returning AdvisorName where ContactKey = the built-in _subscriberkey. This is the cross-DE join you'll use constantly in FinServ.
- %%=v(@advisor)=%% β v() outputs a variable's value into the rendered email.
The mental "schema" of any sendable Data Extension:
SubscriberKey | EmailAddress | FirstName | AdvisorName | ...
(unique key) (Email Addr (any custom personalization fields)
field role)
π Line by line:
- SubscriberKey β the column flagged as Subscriber Key (relationship field); must match Contact Key.
- EmailAddress β the column flagged with the Email Address field role; tells the engine where to send.
- Remaining columns β free-form personalization data (names, advisor, balances) read via [Column] in AMPscript.
π οΈ In practice (what you would actually click / do)
Find where you are (BU switch): top-right of SFMC β click the BU dropdown (shows current Business Unit) β pick the advisor/region BU. Everything you do is scoped to that BU.
Draw the data model live (Contact Builder): - App Switcher (top-left waffle / "Audience Builder" menu) β Contact Builder. - Tabs you'll point to: Data Designer (links DEs to the Contact via attribute groups), Data Extensions (the tables), All Contacts (the master person list).
Make a sendable DE (the audience): - Email Studio β Subscribers β Data Extensions β Create β choose Standard β name it β on the Send Relationship step set it Sendable and map the Subscriber Key field to Subscriber Key and the email column to Email Address. - Add fields (FirstName, AdvisorName...) β Save. Import rows via Import (file) or populate via an Automation Studio SQL Query activity.
Build & personalize the email (Content Builder):
- Content Builder β Create β Email β drag content blocks β in a block click </> (HTML/AMPscript) β drop the AMPscript skeleton above β use Preview & Test with a real DE row to confirm %%=v()=%% resolves.
Send & validate:
- In the email β Send (Guided Send) β choose the sendable DE as audience β apply Suppression / Exclusion lists (critical in FinServ: opt-outs, do-not-contact, restricted advisors) β schedule or send.
- After send: Email Studio β Tracking for opens/clicks/bounces; or query Data Views (_Sent, _Open, _Bounce) via an Automation SQL activity for RCA.
One-liner you can say: "I switch to the right BU, build a sendable DE in Email Studio, link it in Contact Builder, personalize in Content Builder with AMPscript, send via Guided Send with suppression applied, then validate in Tracking and Data Views."
π€ Rapid-fire
- Q: Studio vs Builder? A: Studios act on channels (Email/Mobile/Web/Automation); Builders define data/journeys/content/reports (Contact/Journey/Content/Analytics).
- Q: Is Automation Studio a channel? A: No β it's the scheduled batch engine (SQL, imports, file transfers, send-triggering). β¦and in practice: I schedule a nightly Automation: File Drop β Import β SQL Query β Send.
- Q: Contact Key vs Subscriber Key? A: Same unique string for one person; "Contact Key" in Contact Builder/other channels, "Subscriber Key" in Email Studio.
- Q: All Contacts vs All Subscribers? A: All Contacts = every person in the account; All Subscribers = the email-channel subset. Subscribers β Contacts.
- Q: What is a sendable DE? A: A DE marked sendable with a Subscriber Key relationship + an Email Address field, so it can be used as a send audience. β¦and in practice: I set it on the Data Extension's Send Relationship step.
- Q: Where does tracking live? A: In Tracking (UI) and Data Views (
_Open,_Click,_Bounce,_Sent,_Subscribers) queryable by SQL. β¦and in practice: I write a SQL Query activity joining_Sentand_Bouncefor an RCA report. - Q: Enterprise vs BU? A: Enterprise is the top account that can share content/data; BUs are isolated workspaces under it.
- Q: Why not use email as Subscriber Key? A: Emails change β key churn, duplicate contacts, broken history; and it spreads PII. Use a stable CRM/MOD id. β¦and in practice: I map the MOD ContactID into Subscriber Key on import.
β οΈ Gotchas / RCA hooks
- Wrong BU = "missing" data. A DE/email/automation exists, but you're in the wrong Business Unit. RCA: check the BU dropdown first; data is BU-scoped (only shared/Enterprise data crosses).
- Subscriber Key collisions / churn. Reusing or changing keys merges or splits people, corrupting tracking history. RCA: confirm the import maps a stable CRM/MOD id, not email; check for duplicate Contact Keys in All Contacts.
- Non-sendable DE picked as audience. Send fails or field "Email Address" missing. RCA: open the DE β Send Relationship β ensure Sendable + Subscriber Key + Email Address field role set.
- Personalization renders blank.
%%=v(@x)=%%empty because the field isn't in the sendable DE or theLookupmissed. RCA: Preview & Test with a real row; verify column names and the lookup key (_subscriberkey) match exactly. - Suppression not applied β compliance breach. In FinServ, sending to opt-outs/restricted advisors is a real incident. RCA: confirm Exclusion/Suppression list was attached in Guided Send; check All Subscribers status (Unsubscribed/Held) and publication-list opt-outs.
- Counts don't reconcile (Sent vs Contacts). Bounces, held addresses, and suppressions reduce sent volume. RCA: join
_Sent,_Bounce,_Subscribersin a SQL Query to explain the gap before raising it as a defect.
β‘οΈ Next: C02_Data_Extensions_and_Model.md
C02 β Data Extensions & the Data Model
π― Why Coforge cares: every advisor journey, suppression list and SQL query you'll run for financial-services clients lives in a Data Extension β if you can't build, relate, and govern DEs by click, you can't manage segmentation, data accuracy, or RCA on data failures.
π§ One-screen mental model
CONTACT BUILDER (the data brain)
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β ALL CONTACTS βββ ALL SUBSCRIBERS (one row per ContactKey) β
β (Contact mgmt) status: Active / Held / Bounced / β
β Unsubscribed β
βββββββββββββββββ¬ββββββββββββββββββββββββββββ¬βββββββββββββββββββ
β Send Relationship β Data Designer
β (SubscriberKey β All Subs) β (DE β DE links)
βΌ βΌ
βββββββββββββββββββββββββββββββββ βββββββββββββββββββββββββββββββββ
β SENDABLE DATA EXTENSION β β ATTRIBUTE / LOOKUP DEs β
β ββββββββββββββ¬βββββββββββββββ β β Accounts, Holdings, Prefs... β
β β Field β PK? Null? Len β β β joined on AdvisorID/ClientID β
β ββββββββββββββΌβββββββββββββββ€ β βββββββββββββββββββββββββββββββββ
β β ClientID β PK No 18 β β
β β EmailAddr β No 254 β β LIST (legacy) ββ tiny, by Email,
β β FirstName β Yes 100 β β no PK, profile attrs only.
β ββββββββββββββ΄βββββββββββββββ β Use DEs for everything serious.
β + Retention policy (delete) β
βββββββββββββββββββββββββββββββββ
π Core in 60 seconds
- DE = a database table. Columns (fields) + rows (records). It is the unit of everything in modern SFMC: sends, journeys, SQL, imports.
- List vs DE: List = old, keyed on Email, flat profile attributes, slow, no relationships. DE = relational, keyed on any field you choose, scales, supports SQL/Data Designer. In FS, always DEs.
- A DE becomes Sendable when you (a) tick "Is Sendable" and (b) set a Send Relationship: "This DE field" β relates to Subscribers on β
_SubscriberKeyin All Subscribers. - Send Relationship purpose: tells SFMC who a row is (the Subscriber/Contact) so it can dedupe, honor unsubscribes, and write tracking back. Best practice = a stable ID (ClientID / ContactID), not email.
- Primary Key (PK): makes a field unique β enables overwrite/update on import instead of duplicate rows. No PK = append-only (duplicates pile up).
- Nullable: field can be empty. Required (not null) rows fail import if blank.
- Retention policy: auto-deletes data (whole DE, all records, or row-by-row by date). Critical for FS data minimization/compliance.
- DE types (6): Standard, Filtered, Random, plus the flavors Sendable, Shared, Synchronized (+ Salesforce DEs created by sync). Filtered & Random are derived from a source DE.
- Contact Builder = where contacts, attributes, and DE relationships (Data Designer) live. Data Designer = the canvas where you link DEs into one Contact data model.
π§© Mnemonics & memory hooks
- DE types β "Stan Filled Random Shared Sync'd Salesforce" β Standard, Filtered, Random, Shared, Synchronized, Salesforce DE. Hook: "Stan filled random shared sync'd Salesforce drawers." Six drawers in the data cabinet.
-
Standard = you build the columns. Filtered = a saved WHERE clause over a source DE. Random = % sample for A/B. Shared = one DE visible across Business Units (Enterprise). Synchronized = a read-only mirror of a CRM object (via MC Connect). Salesforce DE = the sendable copy you build from a synchronized DE.
-
Sendable in 2 ticks β "TICK + LINK": TICK "Is Sendable", then LINK the field to All Subscribers
_SubscriberKey. Hook: "Tick the box, link the soul." -
Field config β "P.N.R.D." (sounds like "pin-ride"): Primary key? Nullable? Required? Default/Data-type/length. Hook: "PNRD every column before you save."
-
All Subscribers statuses β "A-HUB": Active, Held, Unsubscribed, Bounced. Hook: "Every contact parks in the A-HUB."
π Skeletons to memorize
A DE is built in the UI, but you must know its shape + how AMPscript writes to it and how SQL keys it.
1. The mental "CREATE TABLE" of a sendable DE (what the UI is really doing):
-- Conceptual shape of a sendable DE: Advisor_Clients
ClientID VARCHAR(18) PRIMARY KEY NOT NULL -- send relationship field
EmailAddress VARCHAR(254) NOT NULL -- the email column
FirstName VARCHAR(100) NULL
AdvisorID VARCHAR(18) NOT NULL -- used to join in Data Designer
OptInStatus VARCHAR(20) NULL
-- Send Relationship: ClientID -> Subscribers (_SubscriberKey) on All Subscribers
-- Retention: delete individual records 730 days after [LastModified]
π Line by line:
- ClientID ... PRIMARY KEY NOT NULL β the unique, stable key; PK lets imports update a client instead of duplicating, and it's the field we make the send relationship.
- EmailAddress VARCHAR(254) NOT NULL β every sendable DE must have an email-type field populated, else the row can't be mailed.
- FirstName ... NULL β personalization field, allowed to be blank (nullable) so imports don't reject partial rows.
- AdvisorID NOT NULL β the foreign-key-style field you'll link in Data Designer to the Advisor/Holdings DEs.
- OptInStatus β FS marketing-preference flag you can filter on for compliant sends.
- Send Relationship comment β points ClientID at _SubscriberKey in All Subscribers so tracking + unsubscribes reconcile.
- Retention comment β auto-purges rows 730 days after last change = data minimization for compliance.
2. AMPscript: write a row into a DE (e.g. log a suppression / preference):
%%[
UpsertData("Suppression_Master", 1,
"ClientID", @clientId,
"SuppressedReason", "CustomerRequest",
"SuppressedDate", Now())
]%%
π Line by line:
- UpsertData("Suppression_Master", 1, ...) β insert-or-update the DE named Suppression_Master; the 1 = number of key columns that follow.
- "ClientID", @clientId β the key field + its value; because it's first and key-count is 1, an existing ClientID is updated, a new one is inserted (needs PK on ClientID).
- "SuppressedReason", "CustomerRequest" β a non-key column written every time.
- "SuppressedDate", Now() β stamps the suppression time; lets a retention/RCA query show when a client was suppressed.
3. SQL: build a sendable audience that EXCLUDES suppressions (the FS pattern):
SELECT c.ClientID, c.EmailAddress, c.FirstName, c.AdvisorID
FROM Advisor_Clients c
LEFT JOIN Suppression_Master s ON s.ClientID = c.ClientID
WHERE s.ClientID IS NULL -- not in suppression list
AND c.OptInStatus = 'Subscribed'
π Line by line:
- SELECT c.ClientID... β pull only the fields the send/journey needs (ClientID is the send-relationship key).
- FROM Advisor_Clients c β the master sendable DE.
- LEFT JOIN Suppression_Master s ON s.ClientID = c.ClientID β attach any suppression row for that client.
- WHERE s.ClientID IS NULL β keep only clients with no suppression match (anti-join = exclusion).
- AND c.OptInStatus = 'Subscribed' β extra compliance gate so only opted-in advisors/clients are mailed.
π οΈ In practice (what you would actually click / do)
A) Create a Data Extension (Email Studio path β most common):
1. Email Studio β Email β Subscribers β Data Extensions.
2. Pick a folder β Create (top right).
3. Choose Standard (or Filtered / Random / From Template) β OK.
4. Properties step: Name (Advisor_Clients), External Key (auto), folder; tick "Is Sendable" here if you know it's a send audience. Optionally tick "Is Testable".
5. Data Retention Policy step (toggle On):
- Choose scope: Delete All Records, Delete Individual Records (by a date field), or Delete Records and Data Extension.
- Set the period (e.g. Individual records, 730 days, based on LastModified). Save.
6. Fields step: add each field β set Name, Data Type, Length, Nullable?, Primary Key?, Default. Mark ClientID as Primary Key + not nullable. Add an EmailAddress (Email type) field.
7. Send Relationship step (appears because Is Sendable): set "Send using" the EmailAddress field, and "Relates to Subscribers on" = ClientID β _SubscriberKey (or Email if no key). Create.
Contact Builder path is equivalent: Contact Builder β Data Extensions β Create β same wizard. Use Contact Builder when the DE will be related in Data Designer.
B) Make an existing DE sendable / fix the relationship: - Open the DE β Edit / Properties β tick Is Sendable β go to Send Relationship β choose the send field + the All-Subscribers key field β Save. (If greyed out: the DE has no email-type field β add one first.)
C) Relate DEs in Data Designer (Contact Builder):
1. Contact Builder β Data Designer.
2. Find your starting point (a populated attribute group / the Advisor_Clients DE) β Create Relationship / drag a link.
3. Set cardinality (One-to-One, One-to-Many) and the join fields (e.g. Advisor_Clients.AdvisorID β Advisor_Master.AdvisorID).
4. Save. Now Contact Builder treats them as one model and you can build attribute-based journeys/segments across them.
D) Validate the data (so you don't repeat the "theory-only" miss):
- DE β Records tab to spot-check rows; Import to load a file (map columns, choose Overwrite / Add & Update β Add&Update needs the PK).
- Query Studio / SQL Activity to count rows: SELECT COUNT(*) FROM Advisor_Clients.
- Before a send: Send Preview / Preview & Test in Content Builder to confirm AMPscript pulls the right DE fields per ClientID.
π€ Rapid-fire
- Q: List vs DE β when a List? A: Almost never now; only tiny legacy email-keyed lists. DEs for anything relational/scaled/compliant.
- Q: What makes a DE sendable? A: "Is Sendable" ticked and a Send Relationship to All Subscribers via a key field. β¦and in practice: Edit DE β Properties β tick β Send Relationship tab β map ClientID β
_SubscriberKeyβ Save. - Q: Why use ClientID not Email as the send relationship? A: Stable across email changes, dedupes per person, cleaner cross-BU reconciliation; FS clients change emails but not their ID.
- Q: Primary Key effect? A: Enforces uniqueness β enables update-on-import; without it, re-imports create duplicate rows.
- Q: Filtered vs Random DE? A: Filtered = saved WHERE-clause subset of a source DE; Random = % sample for A/B testing.
- Q: Synchronized vs Salesforce DE? A: Synchronized = read-only mirror of a CRM object via MC Connect; you build a sendable Salesforce DE from it to actually mail. β¦and in practice: Contact Builder β Salesforce Data Extensions β select object β create the sendable copy.
- Q: All Subscribers statuses? A: Active, Held, Unsubscribed, Bounced (A-HUB).
- Q: How do you suppress clients globally? A: Maintain a Suppression_Master DE, LEFT JOIN-exclude it in the send SQL, or add it as an Exclusion/Suppression list on the send definition. β¦and in practice: in the Guided Send, the Suppression Lists step lets you attach a DE to remove those rows.
- Q: Retention policy options? A: Delete all records / delete individual records by date / delete records + the DE itself; on a period you set.
β οΈ Gotchas / RCA hooks
- "Send Relationship" greyed out / DE not sendable β no Email-type field exists. RCA: add an Email data-type field, re-open Send Relationship.
- Duplicate rows after every import β DE has no Primary Key. RCA: check field config; recreate DE with PK (you can't add a PK to a populated DE β you re-create + reload).
- Import rows rejected β a Required (non-nullable) field was blank, or value exceeds Length, or PK collision. RCA: open Import Activity logs / error file, check the failing column.
- Data silently disappears β a Retention Policy is purging it. RCA: DE β Properties β Data Retention; confirm period + the date field it keys on. Common surprise in FS where someone set aggressive minimization.
- Send to suppressed/opted-out client (compliance incident) β suppression DE not joined or not attached as a suppression list, or join key mismatch (Email vs ClientID). RCA: verify the exclusion JOIN keys match and the suppression DE is on the send definition; re-run the audience query and diff counts.
- Synced DE looks stale β MC Connect sync paused or object not in the sync; RCA: Contact Builder β Data Sources β Synchronized Data Sources β check status/last run.
- Cross-BU data missing β DE is local, not Shared. RCA: recreate in the Shared folder / Shared Data Extensions so child BUs see it.
β‘οΈ Next: C03_SQL_and_Automation_Studio.md
C03 β SQL & Automation Studio
π― Why Coforge cares: this is the engine room of the JD β segmentation, data accuracy, scheduled advisor sends, and the RCA muscle to explain why a query emptied a DE or blew the SLA on a financial-services campaign.
π§ One-screen mental model
SOURCE DEs / DATA VIEWS SQL QUERY ACTIVITY TARGET DE
βββββββββββββββββββββ ββββββββββββββββββββ ββββββββββββββββ
β Advisors_Master β SELECT ... β runs SQL on the β writes β β Send_Audienceβ
β _Sent / _Open ... β ββββββββββββββββΆ β source, picks β βββββββββββΆ β (must exist β
β Transactions_DE β FROM / JOIN β Overwrite/ β β already!) β
βββββββββββββββββββββ WHERE β Update/Append β ββββββββββββββββ
ββββββββββββββββββββ β
SFMC SQL = SELECT-ONLY. No UPDATE/DELETE/INSERT statements. β feeds
You never "write SQL into" a DE β you SELECT and the activity LANDS the rows. βΌ
Journey / Send
AUTOMATION STUDIO = the conveyor belt that runs activities in ORDER:
ββββββββ ββββββββββ βββββββββ ββββββββββββ ββββββββββββββββ ββββββββ
βImportββββΆβ Query ββββΆβFilter ββββΆβVerify(DE)ββββΆβ Send Email ββββΆβExtractβ
ββββββββ ββββββββββ βββββββββ ββββββββββββ ββββββββββββββββ ββββββββ
Trigger: β° Scheduled (calendar) OR π File-Drop (file lands on SFTP)
π Core in 60 seconds
- SFMC SQL is a T-SQL subset, SELECT-only. No
UPDATE/DELETE/INSERT/MERGE/stored procs/temp tables/CTEs-with-writes. You SELECT; the activity writes the result. - The write happens via the Query Activity's Target DE + Update Type β not in the SQL.
- 3 update types β pick deliberately:
- Overwrite = truncate target, then load. (Zero rows returned β target ends EMPTY.)
- Update = match on the target DE's Primary Key, update matches + insert new (upsert-ish).
- Append = add rows, no delete (can create duplicates / PK errors).
- Target DE must already exist with matching column names; the query maps result columns β target columns by name.
- Data Views = system tables of send/engagement history:
_Sent,_Open,_Click,_Bounce,_Unsubscribe,_Subscribers,_Job. Underscore prefix, ~6 months retention. - Join engagement data on
SubscriberKey+JobID(JobID = one send). SubscriberKey alone mixes sends together. - Automation Studio runs activities sequentially; failure of one step (by default) stops the chain.
- Two trigger types: Scheduled (run at a time/recurrence) or File-Drop (run when a file lands on the Enhanced FTP / Import directory).
- Verification activity = a safety gate: stop/email if target DE row count is too low/high/zero β your anti-disaster guard for advisor sends.
π§© Mnemonics & memory hooks
- Update types β "OUA = Obliterate, Upsert, Add":
- Obliterate β Overwrite (wipes first β dangerous on empty results)
- Upsert β Update (matches PK)
- Add β Append (piles on, dup risk)
- Automation activities β "I Query For Sweet Verified Emails, Wait, eXtract & Transfer" β I-Q-F-S-V-E-W-X-T:
- Import Β· Query (SQL) Β· Filter Β· Script (SSJS) Β· Verification Β· Email (Send) Β· Wait Β· eXtract (Data Extract) Β· Transfer (File Transfer)
- Sticky line: "I query for sweet, verified emails, wait, then extract & transfer."
- Data Views β "SOCUB-J": Sent Β· Open Β· Click Β· Unsub Β· Bounce Β· Job. (Hook: "so-cub-j" = the cub cubs that track every send.)
- Join key β "Same person, same SEND": SubscriberKey + JobID. (Hook: who + which send.)
- Trigger types β "Clock or Drop": β° Scheduled vs π File-Drop.
π Skeletons to memorize
1) Dedup β keep newest row per advisor (ROW_NUMBER)
SELECT SubscriberKey, EmailAddress, AdvisorID, ModifiedDate
FROM (
SELECT
SubscriberKey, EmailAddress, AdvisorID, ModifiedDate,
ROW_NUMBER() OVER (
PARTITION BY SubscriberKey
ORDER BY ModifiedDate DESC
) AS rn
FROM Advisors_Master
) ranked
WHERE rn = 1
π Line by line:
- SELECT ... FROM ( ... ) ranked β outer query reads from an inner derived table aliased ranked.
- ROW_NUMBER() OVER (...) β numbers rows 1,2,3β¦ within each group.
- PARTITION BY SubscriberKey β restart the numbering for every distinct subscriber.
- ORDER BY ModifiedDate DESC β newest record gets number 1.
- AS rn β name that number column.
- WHERE rn = 1 β keep only the single freshest row per subscriber β deduped.
2) Anti-join suppression β eligible advisors NOT bounced/unsubbed
SELECT a.SubscriberKey, a.EmailAddress, a.AdvisorID
FROM Advisors_Master a
LEFT JOIN Suppression_DE s
ON a.SubscriberKey = s.SubscriberKey
WHERE s.SubscriberKey IS NULL
π Line by line:
- FROM Advisors_Master a β main audience, aliased a.
- LEFT JOIN Suppression_DE s β keep ALL advisors, attach suppression match if any.
- ON a.SubscriberKey = s.SubscriberKey β match the two on the key.
- WHERE s.SubscriberKey IS NULL β keep only rows with no match in suppression β the safe, sendable list. (This is the classic "anti-join".)
3) Engagement join β who OPENED a specific send (SubscriberKey + JobID)
SELECT s.SubscriberKey, s.EmailAddress, o.EventDate
FROM _Sent s
INNER JOIN _Open o
ON s.SubscriberKey = o.SubscriberKey
AND s.JobID = o.JobID
WHERE s.JobID = 12345
π Line by line:
- FROM _Sent s β start from the send log (one row per send-to-subscriber).
- INNER JOIN _Open o β keep only subscribers who have a matching open.
- ON ... SubscriberKey AND ... JobID β match on both so you don't blend other campaigns.
- WHERE s.JobID = 12345 β scope to one specific send (Job). Swap _Open for _Click/_Bounce for other metrics; LEFT JOIN ... WHERE o.SubscriberKey IS NULL = sent but did NOT open.
π οΈ In practice (what you would actually click / do)
A. Build a Query Activity
1. Automation Studio β Activities β Query β Create Activity (or build it inside an Automation's canvas via Add Activity β SQL Query β Create New).
2. Name + External Key (use a naming convention, e.g. QRY_Advisor_Eligible_Daily).
3. Write SQL in the editor β click Validate Syntax (catches T-SQL errors before runtime).
4. Target Data Extension: pick the existing DE (or Create New DE from the wizard β define columns + Primary Key here; PK drives Update behavior).
5. Data Action (Update Type): choose Overwrite / Update / Append (see OUA mnemonic).
6. Save. Run once standalone (Start) to test; check the target DE β Records tab for row count.
B. Chain it into an Automation
1. Automation Studio β Overview β New Automation.
2. Drag a Schedule (β°) or File Drop (π) trigger into the Starting Source slot.
- File Drop: set the Filename pattern + the FTP folder to watch (e.g. /Import/advisors_*.csv).
3. On the canvas, drag activities into Steps in order, e.g. Step 1 Import File β Step 2 SQL Query β Step 3 Verification β Step 4 Send Email β Step 5 Data Extract β Step 6 File Transfer. (Activities in the same step run in parallel; separate steps run in sequence.)
4. Click each activity tile β Choose an existing one or Create New inline.
C. Add a Verification step (the safety gate) 1. Add activity β Verification. 2. Pick the target DE to check (your Send_Audience). 3. Set the rule, e.g. Record count is less than 1 β Action: Stop the automation and notify, enter your alert email. 4. Place it after the Query, before the Send so a bad/empty audience never reaches advisors.
D. Schedule it 1. Open the automation β Schedule button (top-right) β set Start date/time, time zone, recurrence (e.g. Daily 06:00) and end condition. 2. Activate the schedule. For File-Drop, just Activate β it now fires on file arrival. 3. Monitor under Automation Studio β Overview (status: Running/Complete/Error) and the Activity log.
E. Test/validate before deploy - Run the Query standalone first; eyeball the target DE record count and a few rows. - Use a test/staging target DE with Overwrite off (use Append) until counts look right. - Add a Verification gate, then a single full dry-run of the automation in a lower BU before activating the schedule.
π€ Rapid-fire
- Q: Can SFMC SQL do an UPDATE statement? β A: No β SELECT only. You "update" by selecting rows into a target DE with Update action. β¦and in practice: the row matching uses the target DE's Primary Key; no PK β Update behaves like insert/dup.
- Q: Overwrite vs Update vs Append? β A: Overwrite wipes-then-loads; Update upserts on PK; Append adds without deleting. β¦and in practice: I default daily audiences to Overwrite, but guard it with a Verification step so an empty result can't blank the DE.
- Q: How do you join send to opens? β A:
_Sentβ_Openon SubscriberKey AND JobID. β¦and in practice: JobID scopes it to one send; SubscriberKey alone double-counts across campaigns. - Q: How long do Data Views keep data? β A: ~6 months (rolling). Persist longer by querying into your own DE on a schedule.
- Q: Same-step vs separate-step activities? β A: Same step = parallel; separate steps = sequential. β¦and in practice: I put Query and Send in different steps so the send never starts before the audience is built.
- Q: Scheduled vs File-Drop? β A: Scheduled runs on a clock; File-Drop runs when a file lands on Enhanced FTP. β¦and in practice: advisor lists from an upstream system β File-Drop; nightly refresh β Scheduled.
- Q: How do you stop a bad audience reaching advisors? β A: A Verification activity that stops + emails on row-count < 1 (or an unexpected spike), placed before Send.
- Q: How do you get data OUT of SFMC? β A: Data Extract (DE/data view β file) then File Transfer to the SFTP. (Mnemonic tail: β¦eXtract & Transfer.)
β οΈ Gotchas / RCA hooks
- Empty audience (0 rows sent). RCA: open the Query β run standalone β check returned count. Common causes: a
WHEREfilter on a date/flag, aJOINthat became an inner-join filter, or the source DE didn't import (Import step failed earlier). Fix: validate each step's row count top-to-bottom; add a Verification gate so it's caught next time. - Overwrite wiped a DE. RCA: the Query returned 0 rows (failed join, bad import, source empty) and Overwrite truncated first β DE ends empty. Fix: switch critical loads to Update, or front it with Verification (count < 1 β stop); restore from a backup DE / re-run upstream import.
- Query timeout (~30 min limit). RCA: huge cross-join, missing
WHERE, dedup over a giant DE, non-sargable filters. Fix: filter early, dedup into a smaller staging DE first, index the matching/PK fields on DEs used in joins, split into multiple queries. - Duplicates in target. RCA: Append without a PK, or a one-to-many JOIN fanning out rows. Fix: use the ROW_NUMBER dedup skeleton; set a Primary Key + use Update.
- Column not populating. RCA: result column name β target DE column name (mapping is by name). Fix: alias in SQL (
SELECT x AS TargetColName). - Automation stuck/errored. RCA: check Automation Studio β Overview β Error + the failing activity's run log; File-Drop didn't fire β wrong filename pattern/FTP folder. Fix: correct pattern, re-drop file, confirm Enhanced FTP path.
- SLA breach on an INC. Triage order: Is data there? (source DE/import) β Did the query return rows? β Did the send/journey fire? β Was anyone suppressed wrongly? Tie the finding to a single failing step for a crisp RCA.
β‘οΈ Next: C04_AMPscript_and_Dynamic_Content.md
C04 β AMPscript & Dynamic Content
π― Why Coforge cares: the JD is built on "dynamic content via AMPscript + personalization" for advisor communications β you must show you can hand-build a personalized, compliant financial-services email, not just describe it.
π§ One-screen mental model
SENDABLE DE / Journey data Reference DEs (lookups)
FirstName, AdvisorId, Tier Advisors, Accounts, Disclosures
| |
v v
%%FirstName%% / AttributeValue("..") Lookup() / LookupRows()
| |
+------------------+---------------------+
v
%%[ AMPscript block ]%% <-- logic, VAR/SET/IF, loops
|
v
%%=v(@var)=%% / ContentBlockByKey("..") <-- OUTPUT
|
v
RENDERED HTML (per subscriber, at send/render time)
|
+--------+--------+
v v
EMAIL SEND CLOUDPAGE
(sendable DE ctx) (RequestParameter / no send ctx)
- AMPscript runs server-side, once per subscriber, at render time. Recipient sees only HTML.
π Core in 60 seconds
- Three delimiters:
%%[ logic ]%%(no output) Β·%%=v(@x)=%%(inline output) Β·%%FieldName%%(personalization string). %%field%%vsAttributeValue("field")β same source (send context), butAttributeValue()is callable inside a block and accepts a dynamic name;%%field%%is a literal token only.- Lookup family returns from reference DEs (not the sendable DE):
Lookup= one value Β·LookupRows/LookupOrderedRows= a rowset you loop. - 2,000-row cap: ordered lookups return all matching rows up to 2,000 when the count arg is
<1. Always pass a sanenumRows. ContentBlockByKeypulls a Content Builder block by its Customer Key = modular/reusable content (legal footers, disclosures).- Dynamic Content block (drag-drop, rules in UI) vs AMPscript β UI for marketers/simple rules; AMPscript for data-driven, multi-DE, looped logic.
- Send context vs CloudPage context β email send has a subscriber + sendable DE; a CloudPage does not, so you use
RequestParameter()and explicit lookups.
π§© Mnemonics & memory hooks
- Lookup family β "1 ROW, ROWS, ORDER":
Lookup= 1 value (one field, first match).LookupRows= ROWS (a set, unordered).LookupOrderedRows= ROWS in ORDER (you give the sort).- Hook: "One, many, many-sorted."
- The Rows loop β "C-R-F" = Count, Row, Field:
RowCountβRow(@rs, i)βField(@row, "Col"). Hook: "Count the Rows, then Fetch each Field." - Block anatomy β "V-S-I-O" = VAR, SET, IF, Output: declare, assign, branch, emit. Hook: "Very Smart If Output."
- Output safely β
v()thenEmpty(): wrap vars inv(), guard withEmpty()/IIF(). Hook: "V for visible, E for empty-check." - 2,000 = the wall: ordered lookups stop at 2,000 rows by default β "two grand and you're grounded."
π Skeletons to memorize
1) Greeting + fallback (the #1 warm-up)
%%[
VAR @first, @greeting
SET @first = AttributeValue("FirstName")
IF Empty(@first) THEN
SET @greeting = "Hello"
ELSE
SET @greeting = Concat("Hello ", @first)
ENDIF
]%%
<p>%%=v(@greeting)=%%, thank you for banking with us.</p>
π Line by line:
- VAR @first, @greeting β declare two script variables (every var starts with @).
- SET @first = AttributeValue("FirstName") β pull FirstName from the send context; returns "" (not an error) if the column is missing.
- IF Empty(@first) THEN β true when null/blank; this is your fallback guard.
- SET @greeting = "Hello" β safe default so no "Hello ," with a missing name.
- ELSE ... Concat("Hello ", @first) β personalize when we have a name.
- %%=v(@greeting)=%% β v() outputs a variable inline into the HTML.
2) Single Lookup (one value from a reference DE)
%%[
VAR @advisorName
SET @advisorName = Lookup("Advisors", "FullName", "AdvisorId", AttributeValue("AdvisorId"))
]%%
<p>Your advisor is %%=v(@advisorName)=%%.</p>
π Line by line:
- Lookup("Advisors", "FullName", ...) β args = DE name, column to return, filter column, filter value.
- AttributeValue("AdvisorId") β the subscriber's advisor id from send data is the filter value.
- Returns the first match's single field; "" if no match β so guard it before display.
3) LookupOrderedRows β RowCount β Row β Field loop
%%[
VAR @rows, @count, @i, @row, @amt
SET @rows = LookupOrderedRows("Accounts", 5, "Balance DESC", "CustomerId", AttributeValue("CustomerId"))
SET @count = RowCount(@rows)
IF @count > 0 THEN
FOR @i = 1 TO @count DO
SET @row = Row(@rows, @i)
SET @amt = Field(@row, "Balance")
]%%
<tr><td>%%=v(Field(@row,"AccountName"))=%%</td><td>%%=v(@amt)=%%</td></tr>
%%[
NEXT @i
ENDIF
]%%
π Line by line:
- LookupOrderedRows("Accounts", 5, "Balance DESC", ...) β args = DE, max rows (5, NOT 0/blank or you risk the 2,000 cap), ORDER BY string, filter col, filter val.
- RowCount(@rows) β how many rows came back; always check > 0 before looping (no rows = skip, no error).
- FOR @i = 1 TO @count DO β AMPscript loops are 1-based.
- Row(@rows, @i) β grab the i-th row object.
- Field(@row, "Balance") β read a named column from that row.
- The <tr> lives outside the block (between ]%% and %%[) so HTML renders each iteration; logic resumes in the next %%[.
4) Conditional content IF / ELSEIF / ELSE (account tier)
%%[
VAR @tier, @offer
SET @tier = AttributeValue("AccountTier")
IF @tier == "Platinum" THEN
SET @offer = ContentBlockByKey("offer-platinum")
ELSEIF @tier == "Gold" THEN
SET @offer = ContentBlockByKey("offer-gold")
ELSE
SET @offer = ContentBlockByKey("offer-standard")
ENDIF
]%%
%%=v(@offer)=%%
π Line by line:
- SET @tier = AttributeValue("AccountTier") β read the segmentation field driving the branch.
- IF ... ELSEIF ... ELSE ... ENDIF β exactly one branch wins; ENDIF is mandatory.
- ContentBlockByKey("offer-platinum") β pulls a reusable Content Builder block by its Customer Key, so marketers edit the block, not the code.
- %%=v(@offer)=%% β emit the chosen block's rendered HTML.
5) Write-back: UpsertData / UpsertDE (log the send)
%%[
UpsertData("SendLog", 1, "SubscriberKey", _subscriberkey,
"LastSent", Now(), "Campaign", "Q3-AdvisorUpdate")
]%%
π Line by line:
- UpsertData("SendLog", 1, ...) β args = target DE, # of key columns (1), then key col/value pairs, then update col/value pairs.
- "SubscriberKey", _subscriberkey β the 1 key column + its value (_subscriberkey is a built-in system var).
- "LastSent", Now() / "Campaign", "..." β non-key columns to write; Upsert = update if key exists, else insert.
- Use for per-subscriber audit/suppression logging β critical for financial-services compliance trails.
π οΈ In practice (what you would actually click / do)
Where AMPscript lives (the click-path):
1. Content Builder β open the email β drop an HTML block (or Code Resource for a CloudPage). AMPscript goes inside an HTML/Code block β there is no "AMPscript block" tile.
2. Type the %%[ ]%% logic at the top, output with %%=v()=%% / %%field%% in the body.
3. For reusable pieces, create the disclosure/footer as its own Content Builder block, copy its Customer Key (right-click block β properties, or set it on save), and call ContentBlockByKey("that-key").
Preview & Test against a real subscriber (this is what tripped you up β say it out loud):
1. In the email editor click Preview and Test.
2. Set the "Preview using" data source to your sendable Data Extension (or paste a Subscriber Key) β this is how AMPscript gets real values; with no data source AttributeValue() returns blank.
3. Step through different subscribers (Platinum vs Standard, advisor present vs missing) to prove each branch.
4. Send Preview / Test Send to a seed/test address to confirm the rendered HTML, then validate with Salesforce Marketing Cloud's email-validation/ "Validate" before deployment.
Debug a BLANK personalization (the RCA you must narrate):
1. Open Preview and Test, pick a subscriber you know has the value β still blank? β it's the data source / context, not the code.
2. Check the exact field name & casing in AttributeValue("FirstName") matches the DE column.
3. Confirm the field is in the sendable DE / Journey entry data β a reference-only field needs a Lookup, not %%field%%.
4. Add a temporary debug line %%=v(@first)=%% or output AttributeValue("...") raw to see what render time actually has.
5. For lookups: verify the DE name + filter value match (whitespace, leading zeros on AdvisorId) β wrong filter = empty rowset, not an error.
Dynamic Content block vs AMPscript β how you decide on the spot: simple "if Region = X show banner Y" with marketer-editable rules β Dynamic Content block (Content Builder β drag the Dynamic Content tile, define rules in the UI). Multi-DE lookups, loops, write-back, or compliance logic β AMPscript in an HTML block.
π€ Rapid-fire
- Q: Difference between
LookupandLookupRows? A:Lookupreturns one field value;LookupRows/LookupOrderedRowsreturn a rowset you loop with RowCount/Row/Field. β¦and in practice: I useLookupfor "advisor name",LookupOrderedRowsfor "last 5 transactions, newest first." - Q:
%%field%%vsAttributeValue("field")? A: Same send-context source;AttributeValue()works inside a block and takes a dynamic name,%%field%%is a literal token. β¦and in practice: inside%%[ ]%%I always useAttributeValue(). - Q: What's the 2,000-row thing? A: Ordered lookups cap at 2,000 rows when the count arg is
<1. β¦and in practice: I always pass an explicitnumRowsand let SQL/Automation do bulk work, not AMPscript. - Q: How do you make content reusable? A: Build it as a Content Builder block and call
ContentBlockByKey("customerKey"). β¦and in practice: disclosures/footers live in one block so legal edits hit every email at once. - Q: What does
TreatAsContentdo? A: It re-processes stored AMPscript that you pulled from a DE/block as live AMPscript instead of plain text. β¦and in practice: if a footer stored in a DE contains AMPscript, I wrap the output inTreatAsContent()so it actually runs. - Q: AMPscript runs where/when? A: Server-side, per subscriber, at send/render time β never client-side.
- Q: How do you test it? A: Preview and Test with the sendable DE as the data source, step subscribers, test-send a seed. β¦and in practice: I deliberately test the empty/fallback case, not just the happy path.
- Q: Email vs CloudPage context? A: Email has subscriber + sendable DE; a CloudPage has no send context, so I read
RequestParameter()and do explicitLookups.
β οΈ Gotchas / RCA hooks
- Blank personalization β 90% data/context, not code. RCA: Preview with a known-good subscriber; if still blank, the field isn't in send data β Lookup it.
- Field name / casing / whitespace mismatch β silent empty string. RCA: compare
AttributeValue("...")literal to the DE column; check leading zeros on IDs (AdvisorId). - Forgetting the
RowCount > 0guard β loop on an empty set or odd output. RCA: always branch on count beforeFOR. numRows < 1on ordered lookups β silently capped at 2,000, partial data. RCA: pass an explicit count; for big sets use SQL.- Stored AMPscript renders as raw text β you forgot
TreatAsContent(). RCA: wrap DE-sourced content that contains AMPscript. - Wrong
ContentBlockByKeykey β block doesn't render / errors. RCA: re-copy the Customer Key from the block's properties; keys are case/space-sensitive. - Compliance trap (financial services): never expose full account numbers / SSNs in
%%field%%; mask in SQL/AMPscript and confirm suppression lists applied before send. RCA on a misfire: pull the SendLog write-back to prove who received what. - Unbalanced
%%[ ]%%or missingENDIF/NEXTβ render error or leaked code. RCA: validate fences and that every IF/FOR is closed before deploy.
β‘οΈ Next: C05_Email_Studio_and_Content_Builder.md
C05 β Email Studio & Content Builder
π― Why Coforge cares: this is the JD's core engine β you "run email campaigns, do dynamic content + personalization, validate/preview/test/deploy, and pick the right send classification" for advisor & financial-services comms where a wrong From-line or missing suppression is a compliance incident.
π§ One-screen mental model
ββββββββββββββββββββββββββββββββββββββββ
β EMAIL STUDIO β
ββββββββββββββββββββββββββββββββββββββββ
CONTENT BUILDER THE SEND FLOW (left β right)
βββββββββββββββββ
β Template β 1.CONTENT 2.AUDIENCE 3.EXCLUDE 4.CLASSIFY
β β Slots β βββββββββ ββββββββββ ββββββββββ βββββββββββββββ
β β Blocks β βββΊ β Email βββΊβ DE / βββΊβ Suppr. βββΊβ Send Class. β
β (free-form / β β (HTML β β List / β β + Excl β β Sender + β
β AMPscript) β β +AMP) β β Filter) β β lists β β Delivery + β
βββββββββββββββββ βββββββββ ββββββββββ ββββββββββ β Comm/Trans β
ββββββββ¬βββββββ
7.TRACK 6.SEND/SCHED 5.PREVIEW/TEST β
ββββββββββ ββββββββββββ βββββββββββββββ β
β Opens βββ Send Now βββ VAWP + Proofββββ
β Clicks β β /Scheduleβ β (test send) β
β Bounce β ββββββββββββ βββββββββββββββ
ββββββββββ
HOW IT'S TRIGGERED:
User-Initiated (Guided Send) β’ Triggered Send (TSD, event) β’ Transactional API (REST, 1:1)
π Core in 60 seconds
- Send flow = CAESPST: Content β Audience β Exclusions β Send-classification β Preview/test β Schedule/send β Track.
- Send Classification = Sender Profile + Delivery Profile + CAN-SPAM type.
- Sender Profile = WHO it's from: From Name, From Email, Reply-to.
- Delivery Profile = HOW it ships: IP/sending domain, header & footer (physical address + unsubscribe).
- Type = Commercial (marketing β footer + unsub honored) vs Transactional (receipts/OTP/statements β bypasses unsub & some suppression).
- 3 ways to send: User-Initiated (manual Guided Send), Triggered (TSD fires on an event), Transactional (REST API, real-time 1:1, no unsub footer).
- Native A/B test: ONE variable, a % test split, winner by open or click rate, remainder auto-gets the winner. Tie β Condition A wins.
- Content Builder hierarchy: Template β Slots β Blocks. Blocks hold the content (text, image, HTML, free-form/AMPscript).
- VAWP = "View As Web Page" β the browser version of the email; relies on the email being rendered/accessible. Blank VAWP is a classic RCA.
- Preview & Test = render against a DE row + send a proof/test before the real send. Always do it for advisor sends.
π§© Mnemonics & memory hooks
- Send flow β "CAESPST": "Calm Advisors Expect Safe Precise Sends, Tracked." (Content, Audience, Exclusions, Send-class, Preview, Send, Track.)
- Send Classification 3 parts β "S-D-C" = "Sender, Delivery, Compliance." Who / How / Legal.
- Sender vs Delivery β "Sender = the FACE, Delivery = the TRUCK." Face = From/Reply-to; Truck = IP, domain, footer.
- 3 send modes β "U-T-T" = "User, Triggered, Transactional." "You Type, Trigger Trips, Trans Talks." (manual / event-fired / API 1:1.)
- Commercial vs Transactional β "Transactional = no unsubscribe." Statements/OTP must arrive even if they opted out of marketing.
- A/B β "One knob, small split, winner ships." Change ONE variable, test a slice, send remainder the winner.
- Content Builder β "TSB = Templates have Slots, Slots hold Blocks." Russian-doll: T β S β B.
π Skeletons to memorize
Personalized greeting + compliance-safe fallback (Content Builder free-form block / AMPscript):
%%[
VAR @firstName, @advisor
SET @firstName = AttributeValue("FirstName")
SET @advisor = AttributeValue("AdvisorName")
IF EMPTY(@firstName) THEN SET @firstName = "Valued Client" ENDIF
]%%
Dear %%=v(@firstName)=%%,
Your advisor, %%=v(@advisor)=%%, has an update on your portfolio.
π Line by line:
- VAR @firstName, @advisor β declare the two variables you'll use.
- SET @firstName = AttributeValue("FirstName") β pull the subscriber's first name from the sendable DE/profile attribute.
- SET @advisor = AttributeValue("AdvisorName") β pull the advisor name (key for distributed/advisor comms).
- IF EMPTY(@firstName) ... ENDIF β fallback so a NULL never renders as "Dear ," (looks broken + unprofessional in financial comms).
- %%=v(@firstName)=%% β output the variable into the HTML body.
Make VAWP work β add the View-As-Web-Page link in the email body:
<a href="%%view_email_url%%">View this email in your browser</a>
π Line by line:
- %%view_email_url%% β built-in SFMC personalization string that resolves to the hosted web-page version of THIS send.
- Put it near the top; if VAWP is blank, the #1 cause is content that only renders with subscriber data the web view can't resolve.
Suppress before send (SQL query activity feeding an exclusion DE):
SELECT s.SubscriberKey, s.EmailAddress
FROM Send_Audience s
WHERE s.SubscriberKey NOT IN (SELECT SubscriberKey FROM Global_Optout)
AND s.CountryConsent = 'Y'
π Line by line:
- SELECT s.SubscriberKey, s.EmailAddress β the minimum a sendable DE needs.
- FROM Send_Audience s β your raw target population.
- NOT IN (SELECT SubscriberKey FROM Global_Optout) β drop anyone on the master opt-out list (compliance).
- AND s.CountryConsent = 'Y' β extra consent gate common in financial services; only keep explicitly-consented records.
π οΈ In practice (what you would actually click / do)
A) Build & send a user-initiated campaign (full click-path): 1. Email Studio β Content (Content Builder). Click Create β Email Message β Template-based. Pick a template, click into slots, drag blocks in, drop your AMPscript in a free-form/HTML block. 2. Save. Top-right β Preview and Test. In the Preview tab pick a Data Extension and a subscriber row β confirm personalization + fallbacks render. 3. Still in Preview/Test β Send Test tab β enter your address / a test DE β Send the proof. Open it on desktop + mobile + click VAWP link. 4. Back to the email β Send (Guided Send wizard opens). Step Define Properties β name the send. 5. Select Audience: choose the sendable DE / list / filter. Add Exclusion and Suppression Lists here (e.g., Global_Optout, advisor-region suppression). 6. Configure Delivery: pick the Send Classification (this auto-fills Sender Profile + Delivery Profile + Commercial/Transactional). Set subject line, dedupe option. 7. Schedule or Send: Send Now or Schedule (date/time/timezone). Review the summary β Send. 8. Track: Email Studio β Tracking (or Analytics Builder β Email Tracking) β open the job β read Sent / Delivered / Opens / Clicks / Bounces (hard vs soft) / Unsubscribes / Complaints.
B) Set up a native A/B test: - Content Builder β Create β A/B Test (or from a send choose A/B). Pick the ONE variable: Subject Line, From Name, Content, or Send Time/Date. - Build Version A and Version B (differ ONLY by that variable). - Choose the test split % (e.g., 10%/10%, remaining 80% gets winner) and the audience. - Pick winner criteria: highest Open Rate or highest Click-Through Rate. - Set test duration / "Declare Winner by" time β choose auto-send winner to remainder (or manual). - Send. After the window, winner ships to the rest. Tie β Condition A.
C) Triggered vs Transactional (when JD says "advisor comms / API"):
- Triggered Send: Email Studio β Interactions β Triggered Sends β create TSD, attach email + send classification, Start/Publish it; it fires per event (e.g., welcome). Subject to unsub/suppression.
- Transactional via API: use Transactional Messaging REST API (/messaging/v1/email/messages/{key}) for real-time 1:1 (OTP, statement-ready). No unsub footer required; immediate; tracked via the API events.
D) Sender/Delivery/Classification setup (Admin task): - Email Studio β Admin β Send Management β create Sender Profile (From name/email/reply-to), Delivery Profile (IP, header/footer w/ physical address), then Send Classification binding both + Commercial/Transactional.
π€ Rapid-fire
- Q: What's in a Send Classification? A: Sender Profile + Delivery Profile + CAN-SPAM type (Commercial/Transactional). β¦and in practice: I pick it in the Guided Send "Configure Delivery" step so From-line and footer are correct in one shot.
- Q: Sender vs Delivery Profile? A: Sender = From/Reply-to (the face); Delivery = IP, sending domain, header/footer (the truck).
- Q: When Transactional? A: Receipts, OTP, password resets, statement-ready alerts β must deliver even to marketing opt-outs; no unsub footer. β¦and in practice: I'd send these via Transactional API or a TSD with a Transactional classification.
- Q: 3 ways to send? A: User-Initiated (manual), Triggered (event/TSD), Transactional (REST API, 1:1).
- Q: Native A/B rules? A: One variable, % test split, winner by open or click rate, remainder gets winner, tie β A.
- Q: Content Builder hierarchy? A: Template β Slots β Blocks. β¦and in practice: AMPscript lives in a free-form/HTML block inside a slot.
- Q: What is VAWP? A: View As Web Page β hosted browser version via
%%view_email_url%%. - Q: How do you test before sending? A: Preview against a DE row, then send a proof/test, check render + VAWP + links on multiple clients. β¦and in practice: I never skip the proof for advisor/financial sends.
- Q: Where do exclusions go? A: In Guided Send "Select Audience" β Exclusion + Suppression lists (and pre-built into the sendable DE via SQL).
- Q: Where do you read results? A: Email Studio Tracking / Analytics Builder β Sent, Delivered, Opens, Clicks, Bounces, Unsubs, Complaints.
β οΈ Gotchas / RCA hooks
- VAWP is blank. Likely the body renders only with subscriber/DE context the web view can't resolve, an AMPscript error, or content blocked. RCA: open the email, run Preview against a real row, check for AMPscript runtime errors / missing
AttributeValuefallbacks, confirm%%view_email_url%%link present; fix the unguarded NULL/personalization. - Wrong audience sent. Sent to the raw target, not the suppressed/consented set. RCA: trace the sendable DE back to its SQL/filter, confirm exclusion + suppression lists were attached in Guided Send, check dedupe; in financial services verify consent flag β re-pull audience and re-validate before resend.
- Classification mistake (Commercial vs Transactional). Marketing email sent Transactional (skips unsub β CAN-SPAM/consent breach) OR an OTP sent Commercial (gets suppressed, customer locked out). RCA: check the Send Classification used on the job; correct the binding; for compliance breaches log the INC, document RCA, add a validation step / restrict who can send Transactional.
- From-line / footer wrong. Caused by the wrong Sender/Delivery Profile. RCA: Admin β Send Management β verify the profile fields and the classification it's bound to.
- Proof looked fine, real send broke. Proof used a hardcoded test row; production rows had NULLs. RCA: preview against MULTIPLE real rows incl. edge cases (empty advisor name) before send.
- A/B "no winner"/tie confusion. Remember: tie defaults to Condition A, and changing more than one variable invalidates the test.
β‘οΈ Next: C06_Journey_Builder.md
C06 β Journey Builder
π― Why Coforge cares: the JD is "run email campaigns & journeys, advisor/Distributed-Marketing communications, data accuracy & segmentation, troubleshoot campaign/data/integration failures under SLA" β Journey Builder is the orchestration engine where all of that runs and breaks.
π§ One-screen mental model
A journey is a pipe: contacts enter on the left, flow through activities, and either hit the exit/goal or get filtered out by decisions.
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
ENTRY β JOURNEY CANVAS β GOAL / EXIT
SOURCE βββββββΊβ [Wait] ββΊ [Email] ββΊ <Decision Split?> ββYesββΊ [Email] ββΊ ββββΊ π― Goal met
(DE/API/ β β β OR β Exit criteria
SF event/ β βββNoβββΊ [Update Contact] ββββββΊβ OR end-of-flow
CloudPage) β β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β² snapshot taken HERE = JOURNEY DATA (frozen for whole run)
CONTACT DATA = live, re-read from DEs/Contact model anytime
Journey Data vs Contact Data β the single most-tested practical concept:
π Core in 60 seconds
- Anatomy: Entry Source β Activities β Goals/Exit. One entry source per journey version.
- Entry sources: Data Extension (scheduled batch), API Event (REST fires entry), Salesforce Data Event (MOD/CRM record create/update via Marketing Cloud Connect), CloudPage / Audience / Event.
- Activities: Messages (Email, SMS), Flow control (Wait, Splits, Join), Update Contact, Custom/Sales & Service (Create/Update SF object β for advisors logging to CRM).
- Splits: Decision (attribute logic), Engagement (opened/clicked?), Random (% A/B/n), Einstein (AI: STO / engagement freq / split).
- Journey Data = frozen snapshot at entry. Contact Data = live, re-read every step. Choose deliberately.
- Re-entry: No re-entry / Re-entry anytime / Re-entry only after exiting.
- Goal: a metric target (e.g. "advisor completed profile"). Exit criteria: kick contacts out mid-flow (e.g. unsubscribed, became non-compliant).
- Versioning: you cannot edit a running version. Edit = create a new version β activate β old version goes "Finishing" β drains β "Stopped". New entrants hit the new version.
- Test mode: dry-run the path with a test contact before activating (no live sends to the real audience source).
π§© Mnemonics & memory hooks
- Journey anatomy β "E-A-G-E" = "EAGER": Entry β Activities β Goals β Exit. An eager contact runs the pipe.
- Entry sources β "DASC" = "Data-Always-Starts-Contacts": Data Extension, API event, Salesforce data event, CloudPage.
- Splits β "DERE" said as "DEAR-E": Decision, Engagement, Random, Einstein. Dear-E decides who goes where.
- Flow-control extras β "WJU" = "We Just Update": Wait, Join, Update Contact.
- Journey vs Contact data β "Frozen Journey, Live Contact": Journey = a photo at the door; Contact = a live CCTV feed.
- Re-entry β "Never / Always / After": the three doors β locked, open, or open-once-you-leave.
- Versioning β "Running = Read-only": to change it, clone the version.
π Skeletons to memorize
1) Fire an API-event entry (REST) β the practical "how do advisors get added?" answer
POST https://YOUR_SUBDOMAIN.rest.marketingcloudapis.com/interaction/v1/events
Authorization: Bearer {access_token}
Content-Type: application/json
{
"ContactKey": "ADV-100245",
"EventDefinitionKey": "APIEvent-advisor-onboarding",
"Data": {
"AdvisorId": "ADV-100245",
"FirstName": "Maya",
"Email": "maya@firm.com",
"ComplianceCleared": true
}
}
π Line by line:
- POST .../interaction/v1/events β the Journey Builder REST endpoint that injects a contact into a journey.
- Authorization: Bearer {access_token} β OAuth2 token from your installed package (client credentials).
- ContactKey β the subscriber's unique key; must already exist or be creatable in the Contact model.
- EventDefinitionKey β copies from the journey's API Entry config; this is what binds the call to THAT journey.
- Data β the payload that becomes Journey Data (frozen snapshot) for this run; field names must match the entry-source DE/event schema.
- ComplianceCleared β financial-services gate value you can split on at entry.
2) Personalize an email with Journey Data vs Contact Data (AMPscript)
%%[
/* Journey Data = frozen snapshot from the entry payload */
SET @nameAtEntry = [AdvisorId] /* or {{Event.DEKey.Field}} in JB binding */
/* Contact Data = live lookup at send time */
SET @rows = LookupRows("Ent.Advisor_Master","AdvisorId", @nameAtEntry)
IF RowCount(@rows) > 0 THEN
SET @row = Row(@rows,1)
SET @tier = Field(@row,"ServiceTier") /* live value, may have changed since entry */
ENDIF
]%%
Welcome aboard, advisor %%=v(@nameAtEntry)=%% β current tier: %%=v(@tier)=%%
π Line by line:
- SET @nameAtEntry = [AdvisorId] β reads the attribute Journey Builder injected at entry (frozen).
- LookupRows("Ent.Advisor_Master",...) β a live read against the shared (Ent.) Advisor DE β this is Contact-data-style behavior.
- RowCount > 0 guard β never assume the lookup found a row; financial data must be defensive.
- Field(@row,"ServiceTier") β pulls the freshest tier; if the advisor was upgraded since entry, this shows the new value while @nameAtEntry stays as it was at the door.
- The output line proves the contrast in one message: frozen ID + live tier.
3) Bind a Decision Split on Journey Data (the JB expression you'd type)
Decision Split β Path "Compliant"
WHERE {{Event.APIEvent-advisor-onboarding.ComplianceCleared}} EQUALS true
Default path β "Hold for compliance review"
π Line by line:
- {{Event.<EventDefinitionKey>.<Field>}} β the binding syntax for Journey Data inside split criteria.
- EQUALS true β routes only cleared advisors down the welcome path.
- Default path β every split needs a catch-all; unmatched advisors are parked, not silently dropped (RCA-friendly).
π οΈ In practice (what you would actually click / do)
Build the advisor-onboarding journey (click-path):
- Journey Builder β New Journey β Build from scratch (Multi-Step).
- Drag the Entry Source. For batch: Data Extension, pick
Advisor_Onboarding_EntryDE, set Filter (e.g.ComplianceCleared = true), set Schedule (e.g. daily 6am) and re-entry mode. For real-time: drag API Event, define attributes, copy the EventDefinitionKey. - Set re-entry: click the entry source gear β No re-entry for one-time onboarding (an advisor should onboard once).
- Drag activities in order: Wait (1 day) β Email ("Welcome + first login") β Wait (2 days) β Decision Split on
ComplianceCleared/ profile-completed β Yes: Email ("Set up your book of business") β No: Update Contact (flagNeedsComplianceReview = true) + Email to ops. - Configure each Email: click the Email activity β select a Content Builder email β choose send-time personalization; set Sender Profile + Send Classification (commercial vs transactional β matters for compliance/CAN-SPAM footer).
- Add a Goal: click the flag at top β metric = "Advisor profile completed" with a target %. Add Exit Criteria β "unsubscribed OR ComplianceCleared = false" so non-compliant advisors leave immediately.
- Choose Journey vs Contact data: in journey Settings, decide if splits/personalization read the frozen entry snapshot or do live DE lookups. Onboarding usually wants live tier/status β use Contact Data or AMPscript
LookupRows. - Validate: click Validate (top bar) β JB checks for unconfigured activities, missing content, broken bindings.
- Test (Test Mode): Activate dropdown β Test β pick a test contact/DE β JB simulates the path, wait times collapse, no send to the real audience source β you watch which path the contact takes and inspect rendered emails.
- Activate β confirm version β journey goes Running.
Push a change to a LIVE journey (you CANNOT edit the running one):
- Open the journey β Edit β JB auto-creates Version 2 (Draft) β Version 1 keeps running untouched.
- Make edits in V2 (add a Wait, fix copy, retune a split).
- Validate β Test β Activate V2.
- On activation: V1 β "Finishing" (current members drain to the end), V2 β "Running" (all new entrants use it). When V1 empties it becomes "Stopped."
- To stop entirely: Stop the journey (ejects everyone) vs Pause (holds them in place β safer for a hot incident; resume later).
Test mode quick recall: "Test mode = dress rehearsal. Real path, fake send, instant waits."
π€ Rapid-fire
- Q: Entry source for advisors created in the CRM? β Salesforce Data Event (via Marketing Cloud Connect) β fires on record create/update on the MOD/CRM object. β¦and in practice: you select the SF object + criteria in the entry source, and Connect must be configured with that business unit.
- Q: Journey Data vs Contact Data β one-liner? β Journey Data is the frozen snapshot at entry; Contact Data is live, re-read each step. β¦and in practice: if a split must reflect a status that changes mid-journey (e.g. advisor revoked), use Contact Data / live lookup, not the entry snapshot.
- Q: Can you edit a running journey? β No. Create a new version, activate it; old version drains in "Finishing". β¦and in practice: I clone to V2, Validate, Test, then Activate β zero disruption to in-flight advisors.
- Q: Four split types? β Decision, Engagement, Random, Einstein (DEAR-E). β¦and in practice: Decision for attribute logic, Engagement for opened/clicked, Random for A/B, Einstein for AI send-time.
- Q: Goal vs Exit criteria? β Goal = success metric/target; Exit = condition that removes a contact mid-flow.
β¦and in practice: Exit on
unsubscribe OR non-compliantis mandatory in financial services for suppression. - Q: Stop vs Pause? β Stop ejects all members (irreversible for them); Pause freezes them in place to resume. β¦and in practice: during an INC I Pause to stop the bleed without losing journey state, investigate, then resume.
- Q: Re-entry modes? β No re-entry / Anytime / Only after exiting. β¦and in practice: onboarding = No re-entry; a recurring nurture = Anytime.
- Q: How do you inject one contact on demand? β Fire an API Event to
/interaction/v1/eventswith theEventDefinitionKey. - Q: Why might a contact not enter? β Doesn't meet entry filter, already in journey (re-entry rule), no matching ContactKey, or in suppression/exclusion list.
β οΈ Gotchas / RCA hooks
- "Email shows stale data." β You bound Journey Data (frozen) where you needed live. RCA: check whether personalization reads
{{Event...}}(frozen) vs an AMPscript liveLookupRows. Fix = switch to Contact Data / live lookup. - "My edit didn't take effect." β You edited a draft but never activated the new version, or V1 is still "Finishing" so old members see old content. RCA: check version status (Running vs Finishing vs Draft).
- "Contacts not entering." β Entry filter excludes them, re-entry = No re-entry and they were in before, missing/duplicate ContactKey, schedule not run yet, or stuck in a global suppression/exclusion list. RCA path: Journey Entry Source > history, check DE row count, check Contact Builder for the key, check exclusions.
- "Advisor got a non-compliant message." β No Exit Criteria for compliance status, or split read frozen data that was compliant at entry but later revoked. RCA: add live exit criteria + use Contact Data for the gate.
- "API event 400/entry rejected." β
EventDefinitionKeymismatch, payload field names don't match entry schema, or token scope missingjourneys/automations. RCA: compare payload keys to the entry-source attributes exactly. - "Wait never ends / sends bunch up." β Wait at journey end, timezone of Wait-By-Attribute, or activation during a wait window. RCA: inspect Wait config + journey activation time.
- "Can't tell who's where." β Use Journey Builder > journey > History / contact path and Journey Analytics to see per-activity counts; ties directly to SLA reporting on campaign failures.
- Distributed Marketing note: advisor-sent journeys originate from Distributed Marketing / Sales & Service Cloud quick-send; the journey still runs in MC but entry comes from the advisor's CRM action β know that boundary for integration RCA.
β‘οΈ Next: C07_Validation_Testing_Deployment.md
C07 β Campaign Validation, Testing, Preview & Deployment (PRACTICAL CORE)
π― Why Coforge cares: the JD literally lists "campaign validation, testing, preview & deployment" β a botched advisor send in financial services is a compliance event, so they need someone who can prove a send is correct before it leaves, not just describe it.
π§ One-screen mental model
BUILD VALIDATE (pre-send QA) DEPLOY / SEND
ββββββββββββββββ βββββββββββββββββββββββββββββββββ ββββββββββββββββββββββ
β Email + β β 1 PREVIEW & TEST (real DE row) β β Promote devβQAβprodβ
β AMPscript + β βββΊ β 2 Render test (Litmus) ββββΊβ via Package Manager β
β Dynamic Cont.β β 3 Links / UTM β β + folder/naming govβ
ββββββββββββββββ β 4 Audience row count β βββββββββββ¬βββββββββββ
β² β 5 Compliance: unsub/footer/SC β β
β β 6 VAWP / View As Web Page β βΌ
ββββββββ΄ββββββββ β 7 Proof / Test send β ββββββββββββββββββββββ
β Git versionedβ βββββββββββββββββ¬ββββββββββββββββ β Scheduled / triggered
β HTML/AMP/SSJSβ FAIL ββββββ PASS βββββββββββΊ β send to PROD audience
ββββββββββββββββ (RCA, fix, re-run) ββββββββββββββββββββββ
π Core in 60 seconds
- Preview & Test tab (inside the email in Content Builder) = your #1 weapon: pick a real subscriber / DE row, see AMPscript + dynamic content resolved with actual data, not raw code.
- Test Send (a.k.a. proof) goes to you / a test DE, runs the real send-time engine (so it catches AMPscript errors a preview can miss).
- Render testing = Litmus / Email on Acid: check Outlook (worst client) and dark mode.
- Audience verification = run the SQL / check DE row count before send; a wrong count = wrong audience.
- Compliance gates (finance): unsub link, physical address footer, correct sender/CAN-SPAM classification, suppression applied.
- VAWP = "View as Web Page" link must render (breaks if DE/email/sender is moved/overwritten after send).
- Deploy path: dev BU β QA BU β prod BU. Move assets with Package Manager (modern) / Deployment Manager (legacy AppExchange). Keep source of truth in Git.
π§© Mnemonics & memory hooks
- QA checklist = "PRLACVP" β say it as "PuRe LACK of VP" (no VP signs off if QA fails):
- Preview with real data β Render (Litmus/Outlook/dark) β Links & UTM β Audience count β Compliance (unsub/footer/classification) β VAWP β Proof/test send.
- Compliance four = "FUSS" β make a FUSS before any finance send: Footer (address) Β· Unsub link Β· Sender/classification Β· Suppression applied.
- Deploy promotion = "D-Q-P, Package, Pin" β Dev β QA β Prod, move via Package Manager, Pin it in Git. ("DQP" sounds like "dee-cue-pee, ship it clean.")
- Render killers = "OLD" β Outlook (Word engine) Β· Length/clipping (Gmail 102KB) Β· Dark mode. "OLD clients break new emails."
π Skeletons to memorize
1. Defensive AMPscript so Preview/Test never hard-fails on a bad row
%%[
VAR @firstName, @advisor
SET @firstName = AttributeValue("FirstName")
IF EMPTY(@firstName) THEN SET @firstName = "Valued Client" ENDIF
SET @advisor = Lookup("Advisors","AdvisorName","ClientID", AttributeValue("ClientID"))
IF EMPTY(@advisor) THEN SET @advisor = "your Gap Financial team" ENDIF
]%%
Hello %%=v(@firstName)=%%, your advisor %%=v(@advisor)=%% has an update.
π Line by line:
- VAR @firstName, @advisor β declare variables up front so the block is readable.
- SET @firstName = AttributeValue("FirstName") β pull the field from the current DE row being previewed.
- IF EMPTY(...) ... ENDIF β fallback default so an empty cell doesn't show a blank or error during QA.
- Lookup("Advisors",...) β fetch the advisor name from a related DE by ClientID; the realistic finance case.
- second IF EMPTY β fallback if the lookup misses, so no row breaks the proof send.
- %%=v(@firstName)=%% β output the resolved value; this is exactly what Preview shows per chosen row.
2. Audience row-count + suppression check SQL (run in Automation Studio / Query before send)
SELECT COUNT(*) AS SendCount
FROM Campaign_Q2_Advisors aud
WHERE aud.OptInStatus = 'Subscribed'
AND aud.SubscriberKey NOT IN (SELECT SubscriberKey FROM Global_Suppression)
AND aud.SubscriberKey NOT IN (SELECT SubscriberKey FROM Holdout_Control);
π Line by line:
- SELECT COUNT(*) AS SendCount β the single number you compare to the expected audience size.
- FROM Campaign_Q2_Advisors β your built send audience DE.
- OptInStatus = 'Subscribed' β only consentable rows (consent matters hard in financial services).
- NOT IN (... Global_Suppression) β strip anyone on the master suppression list.
- NOT IN (... Holdout_Control) β exclude the holdout/control group so the test stays valid.
- Eyeball the result vs the brief: if 50k expected and 12k returned, stop and RCA before sending.
3. Folder + naming governance pattern (so QA/Deploy is traceable)
Content Builder / Data Extensions naming:
[BU]_[Domain]_[Campaign]_[Type]_[YYYYMMDD]_[vN]
e.g. FS_Advisor_Q2Review_Email_20260620_v3
Folder tree:
π 01_Dev β π 02_QA β π 03_Prod β π 99_Archive
π Line by line:
- [BU] β business unit / brand (here FS = Financial Services) so cross-BU promotes stay clear.
- [Domain]_[Campaign] β who it's for and which campaign; searchable in 6 months.
- [Type] β Email / DE / Query / Journey, so asset type is obvious.
- [YYYYMMDD]_[vN] β date + version; the version is what you reconcile against Git.
- The Dev β QA β Prod β Archive folders give a visual promotion path and prevent sending a dev asset to prod.
π οΈ In practice (what you would actually click / do)
A. Preview & Test against a real row (the LTM-gap fix β say this out loud) 1. Email Studio / Content Builder β open the email β top tabs β Preview and Test. 2. Preview sub-tab β "Preview using" β choose Data Extension β pick your send DE β select a specific row (e.g. a row with a NULL advisor) β confirm AMPscript + dynamic content render correctly. 3. Cycle 3β5 rows: a populated row, an empty-field row, a suppression-edge row. 4. Switch the dynamic-content / decision rules preview to confirm each variant (e.g. "Premier" vs "Standard" client block) fires for the right segment.
B. Test / Proof send (catches send-engine-only errors)
1. Same screen β Test Send sub-tab.
2. Set From / Sender Profile and Send Classification (must be the correct commercial vs transactional one β finance auditors check this).
3. Choose a test data extension (so personalization runs on real-shaped data), add your inbox + QA distribution list.
4. Send β open in Gmail, Outlook desktop, iOS Mail, toggle dark mode.
5. If AMPscript throws here but previewed fine β it's a send-time function issue (e.g. Lookup on a DE the send context can't see) β fix and re-proof.
C. Render testing 1. Either forward the proof to a Litmus/Email on Acid seed address, or paste HTML into their app. 2. Prioritize Outlook (Windows) β it uses Word's rendering engine; check tables/VML buttons, then dark mode inversion of logos/text. 3. Check Gmail clipping (>102KB) β trim inline CSS/comments if clipped.
D. Link & UTM check
1. In Preview, click every link (or use Litmus link validation) β no http:// placeholders, no broken %%=RedirectTo()=%%.
2. Confirm UTM params on each CTA (source/medium/campaign) so reporting/attribution is right.
3. Verify the unsub %%unsub_center_url%% / profile-center link and the physical-address footer are present.
E. Audience verification 1. Automation Studio β SQL Query Activity (or Query Studio) β run the row-count + suppression SQL above β compare to the campaign brief. 2. In the DE record view, confirm row count and spot-check 5 rows for data accuracy. 3. Confirm global/CAN-SPAM suppression and holdout were applied (this is the data-accuracy pillar in the JD).
F. VAWP / "View as Web Page" 1. After proof, click the "View as a Web Page" link in the email β it must render fully. 2. Remember it breaks if you move/rename/overwrite the email, sender profile, or DE after send β so freeze assets post-send.
G. Deploy / promote (dev β QA β prod BU) 1. Build & QA in the Dev BU, get sign-off in QA BU. 2. Setup β Package Manager β Create Package β add assets (email, DEs, automations, journeys, content blocks) β Validate β Deploy to the target (prod) BU. 3. (Legacy alt: Deployment Manager AppExchange app for BU-to-BU asset copy.) 4. Re-point the deployed email to the prod DEs/sender profile, re-run a prod proof, then schedule/activate the send or journey. 5. Commit the final HTML / AMPscript / SSJS to Git (branch per release, tag the version that matches the asset name) β that's your rollback + audit trail.
H. SLA / critical-send readiness - Keep a one-page QA checklist (PRLACVP) attached to the deploy ticket; reviewer signs each line. - For critical sends, do a canary: send to a small internal seed segment first, watch deliverability/rendering, then release the full audience.
π€ Rapid-fire
-
Q: Preview vs Test Send β difference? A: Preview renders against a chosen DE row in the UI; Test Send actually runs the send engine to a test DE/inbox. β¦and in practice: I always do both β preview catches layout/data, the proof catches send-time AMPscript (
Lookup/HTTPGet) failures. -
Q: An advisor's name shows blank in preview β what now? A: The DE field is NULL or the lookup missed. β¦and in practice: add an
IF EMPTY()fallback in AMPscript, re-preview that exact row, then re-proof. -
Q: How do you confirm you're sending to the right people? A: Run a COUNT(*) SQL with opt-in + suppression + holdout filters and compare to the brief; spot-check rows. β¦and in practice: I never trust the build alone β wrong count = stop and RCA before send.
-
Q: Which email client do you test hardest and why? A: Outlook (Windows) β Word rendering engine breaks modern CSS; plus dark mode. β¦and in practice: I seed Litmus, fix with table layout/VML buttons, re-check.
-
Q: What is VAWP and why does it break? A: "View as Web Page"; breaks when the email/DE/sender profile is moved or overwritten after send. β¦and in practice: I freeze and archive send assets and never overwrite a sent DE.
-
Q: How do you promote a campaign from dev to prod? A: Package Manager creates a validated package of assets and deploys to the target BU; re-point to prod data, re-proof, schedule. β¦and in practice: final code goes to Git with a version tag matching the asset name.
-
Q: Compliance items you check before any finance send? A: FUSS β Footer address, Unsub link, Sender/classification, Suppression applied. β¦and in practice: these are non-negotiable sign-off lines on the deploy ticket.
-
Q: A critical send is due in 1 hour β how do you de-risk it? A: Run the PRLACVP checklist, then a canary to an internal seed before full release. β¦and in practice: if the canary renders/deliverers clean, I release; if not, I hold and RCA β SLA respects correctness.
β οΈ Gotchas / RCA hooks
- "It previewed fine but errored on send." β Preview β send context. RCA: re-run as Test Send; check
Lookup/LookupRowstarget DEs are reachable in the send BU; check publication/shared-DE scope. - Wrong audience count. β RCA: re-open the SQL/filter, check JOIN/
NOT INlogic and that suppression + holdout actually applied; verify the automation ran on fresh data (stale import = wrong count). - Links broken / wrong UTM. β RCA: search HTML for hard-coded
http://, unresolved%%=RedirectTo()=%%, missing?utm_; re-validate in Litmus link checker. - VAWP shows "temporarily unavailable." β RCA: the email, sender profile, or DE was moved/overwritten/deleted after send. Fix: restore/avoid post-send edits; archive sent assets read-only.
- Outlook layout collapses / dark-mode logo disappears. β RCA: relying on modern CSS/transparent PNGs. Fix: table layout, bulletproof buttons, dark-mode-safe logo background.
- Deployed to prod but still points at dev DEs. β RCA: post-deploy re-pointing missed. Fix: after Package Manager deploy, re-bind email to prod DEs/sender and re-proof in prod before scheduling.
- No rollback when a send goes wrong. β RCA: code lived only in SFMC UI. Fix: Git-version HTML/AMPscript/SSJS with release tags so you can restore the last good version fast (SLA recovery).
β‘οΈ Next: C08_Distributed_Marketing.md
C08 β Distributed Marketing & Advisor Communications (NEW β JD-critical)
π― Why Coforge cares: the JD explicitly names "Distributed Marketing / advisor communications" and "MOD (CRM)" β this is how a bank advisor sends an approved, compliant SFMC email to their own client from inside Sales/Service Cloud, with brand + compliance locked down centrally. Nail this and you own the headline differentiator.
π§ One-screen mental model
CENTRAL (You = Marketing Cloud admin) LOCAL (Advisor in CRM)
ββββββββββββββββββββββββββββββββββββββββ ββββββββββββββββββββββββββββββββ
β Email Studio: build approved email β β Sales/Service Cloud record β
β Journey Builder: wrap in a Journey β β (Contact / Lead / Campaign) β
β Content Builder: brand + legal lock β β β
βββββββββββββββββ¬βββββββββββββββββββββββ β βΈ Quick Send (1 message) β
β make Journey AVAILABLE β βΈ Add to Journey (series) β
β to Distributed Marketing β βΈ personalize + APPROVE β
βΌ βββββββββββββββββ¬βββββββββββββββ
ββββββββββββββββββββββββ β advisor clicks SEND
β DM Managed Package ββββ Marketing Cloud Connect ββββΆβ
β (installed in CRM) β (the account-level link) β
ββββββββββββ¬ββββββββββββ βΌ
β writes sender into ββββββββββββββββββββββββββββββββ
βΌ Entry/Event DE β Journey fires in Marketing β
sendFromName / sendFromEmail βββββββββββΆβ Cloud β email sends as ADVISOR β
βββββββββββββββββ¬βββββββββββββββ
β opens/clicks/sends
βΌ
Tracking flows BACK to CRM
(Campaign Member / Individual Email Result)
- Central builds & controls. Local picks, personalizes, approves, sends. Tracking returns.
π Core in 60 seconds
- What DM is: lets non-marketers (advisors, agents, franchisees) in Sales/Service Cloud send pre-approved SFMC campaigns to their own Contacts/Leads β central keeps brand + compliance.
- Two send modes: Quick Send = one single-message journey, ad-hoc. Add to Journey / Campaign Send = put many members into a multi-step journey (welcome/drip).
- Plumbing (3 pieces): DM Managed Package (installed in CRM) + Marketing Cloud Connect (the account link) + Journey Builder (every DM send is really a Journey).
- Sender identity: the email sends as the advisor via
sendFromName/sendFromEmailfields in the Entry (Event) Data Extension; Sender Profiles can control this org-wide. - Approval gate: advisor must review β personalize β approve campaign members before the send fires. That's the human compliance checkpoint.
- Permissions: Admin = link journeys to campaigns + org defaults; Standard = personalize + approve + send. Granted via permission set licenses / custom permissions in CRM.
- Tracking: opens/clicks/sends flow back to CRM (Campaign Member tracking / Individual Email Results) through the MC Connect API user.
- FinServ fit: advisor-to-client comms at scale, centrally compliant β exactly what a bank/insurer wants (advisor adds the human touch, legal can't be broken).
π§© Mnemonics & memory hooks
- The 3 plumbing pieces β "PCJ" β Package (managed), Connect (Marketing Cloud Connect), Journey (Builder). Hook: "Peanut-butter & Jelly Connects two clouds."
- What an advisor does β "P-A-S-S" β Pick journey β Add members / personalize β Submit for approval β Send. Hook: an advisor needs a PASS to talk to clients.
- DM value prop β "Central Brain, Local Hands" β strategy/compliance central, the personal relationship local. Hook: one brain, many hands.
- Sender fields β "FROM = Name + Email" β
sendFromName+sendFromEmailin the Entry DE. Hook: the advisor's face on a corporate letter. - Quick Send vs Journey β "1 vs Many" β Quick Send = 1 single-message journey; Add-to-Journey = many steps. Hook: Quick = one quick tap.
π Skeletons to memorize
Entry / Event Data Extension (the sender + recipient fields DM needs):
Entry Data Extension columns (minimum)
ContactKey -> who the email goes to (advisor's client)
EmailAddress -> recipient email
sendFromName -> "Priya Sharma, Wealth Advisor" (shows as From name)
sendFromEmail -> priya.sharma@bank.com (shows as From address)
FirstName / ... -> personalization fields for AMPscript
π Line by line:
- ContactKey β the subscriber identity; DM routes the message to this advisor's specific client.
- EmailAddress β the recipient's email; the Journey's sendable DE keys off this.
- sendFromName β what the client sees as the sender's display name β this is how it sends "as the advisor," not "as the bank."
- sendFromEmail β the reply/from address; pair with a verified Sender Profile so it's deliverable + on-brand.
- FirstName etc. β feed your AMPscript personalization so each advisor's note still feels 1:1.
AMPscript greeting that keeps the advisor's personal voice (FinServ-safe):
%%[
VAR @first, @advisor
SET @first = AttributeValue("FirstName")
SET @advisor = AttributeValue("sendFromName")
IF EMPTY(@first) THEN SET @first = "there" ENDIF
]%%
Dear %%=v(@first)=%%, a quick note from %%=v(@advisor)=%%.
π Line by line:
- VAR β declare variables up front (your GAP habit β keeps templates readable).
- SET @first = AttributeValue("FirstName") β pull the client's first name from the Entry DE.
- SET @advisor = AttributeValue("sendFromName") β reuse the DM sender field so the body matches the From name.
- IF EMPTY(... ) THEN ... "there" β defensive default so a blank name never prints "Dear ," (a deliverability/compliance embarrassment).
- The greeting line renders one personalized note per advisor β central template, local voice.
π οΈ In practice (what you would actually click / do)
A) Central admin β make a campaign available to advisors (one-time + per-campaign):
1. Install the DM managed package into Sales/Service Cloud: log out of MC β paste the managed package install URL β choose "Install for Admins/specific profiles."
2. Confirm Marketing Cloud Connect is configured (the MC Connect API user links the CRM org β MC account). Without this, DM has no pipe.
3. In Marketing Cloud β Journey Builder, build the journey using an Entry Source = Data Extension whose schema includes ContactKey, EmailAddress, sendFromName, sendFromEmail.
4. Mark the journey for DM: in the journey settings choose the Quick Send re-entry mode β Re-entry at any time (resend allowed) or Re-entry only after exiting. Activate the journey.
5. In CRM (Distributed Marketing app) β link the active MC journey to a Salesforce Campaign (Admin permission). This is what surfaces it to advisors.
6. Lock the brand: email built in Content Builder with locked regions / legal footer so advisors edit only the allowed blocks.
B) Advisor β Quick Send (single message, e.g. a market-update or birthday note):
1. Open a Contact/Lead in Sales Cloud β click the Quick Send action (DM component on the page layout).
2. Pick the approved single-message journey β personalize the allowed fields β Send. The email goes out from the advisor via sendFromName/Email.
C) Advisor β bulk into a Journey (welcome/drip): 1. Open the linked Salesforce Campaign β DM component shows Campaign Members. 2. Run the "Campaign Send" workflow β review members β approve β members enter the multi-step MC journey.
D) Validate / test / deploy (the part you fumbled before β be specific):
- Preview & seed: in Journey Builder use the email Preview with a test contact row; send a test send to a seed list before the journey goes live.
- Render test: Content Builder "Validate" / Litmus-style preview for inbox rendering + link check.
- Personalization test: put a fake advisor row in the Entry DE with sendFromName/Email filled β confirm the From + greeting resolve.
- Tracking check: after a test, open the CRM Contact / Campaign β confirm Individual Email Result / Campaign Member activity wrote back.
- Deploy: activate journey in MC, link to Campaign in CRM, confirm the Quick Send button appears on the advisor's page layout for the right profile.
π€ Rapid-fire
- Q: In one line, what is Distributed Marketing? A: Lets CRM users send pre-approved, brand-controlled SFMC emails/journeys to their own contacts. β¦and in practice: I link an active MC journey to a Salesforce Campaign so it shows up as a Quick Send button on the advisor's record.
- Q: Quick Send vs Add-to-Journey? A: Quick Send = one single-message journey, ad-hoc; Add-to-Journey/Campaign Send = many members into a multi-step journey. β¦and in practice: Quick Send for a one-off market note, Campaign Send for a welcome series.
- Q: What three components make DM work? A: DM managed package + Marketing Cloud Connect + Journey Builder (mnemonic PCJ).
- Q: How does the email send "as the advisor"? A:
sendFromName/sendFromEmailin the Entry (Event) DE; org-wide control via Sender Profiles. β¦and in practice: I populate those columns from the running user so each send carries the advisor's name. - Q: Where's the compliance gate? A: The advisor must approve campaign members before send, and central locks the template/legal regions. Nothing un-approved or off-brand goes out.
- Q: Does DM need Marketing Cloud Connect? A: Yes β it's the account-level link (via the MC Connect API user) between CRM and Marketing Cloud.
- Q: How is a DM send tracked? A: Opens/clicks/sends flow back to CRM as Individual Email Results / Campaign Member tracking via the API user. β¦and in practice: I verify the writeback on the Contact's activity after a test.
- Q: Why do financial-services firms love DM? A: Advisor-to-client personalization at scale with central brand + compliance β the advisor adds the human touch, legal can't be broken.
- Q: Admin vs Standard permission? A: Admin links journeysβcampaigns + sets org defaults; Standard personalizes, approves, and sends.
β οΈ Gotchas / RCA hooks
- "Quick Send button missing for an advisor." β RCA: DM permission set license / custom permission not assigned, or the DM action not on that page layout / profile. Fix in CRM Setup.
- Email sent as the brand, not the advisor. β RCA:
sendFromName/sendFromEmailempty in the Entry DE, or Sender Profile overriding. Check the DE row + journey config. - Journey not appearing in the DM app. β RCA: journey not Activated, or not linked to a Salesforce Campaign (Admin step skipped).
- No tracking writeback to CRM. β RCA: Marketing Cloud Connect API user broken / token expired, or Campaign Member tracking not enabled in MC Connect settings.
- Sender email bounces / lands in spam. β RCA:
sendFromEmaildomain not authenticated (SAP / SPF-DKIM). FinServ: never let advisors free-type unverified from-addresses β constrain via Sender Profiles. - Compliance leak (advisor edited a locked legal block). β RCA: Content Builder locked regions not set; re-lock and restrict editable blocks; reinforce the approval step.
- Wrong client list / data accuracy. β RCA: Entry DE keyed on stale
ContactKey; tie DM to a governed, freshly-synced segment, not an ad-hoc upload. (Ties to JD "data accuracy & segmentation.")
β‘οΈ Next: C09_APIs_and_Integrations.md
C09 β SFMC APIs & Integrations
π― Why Coforge cares: the JD wants someone who can fire journeys/upsert data via SFMC APIs, run Marketing Cloud Connect with the MOD/CRM system, and do RCA on integration failures (401 vs 403, expired tokens) under SLA β for advisor/financial-services comms.
π§ One-screen mental model
βββββββββββββββββββββββββββββββ
Installed β Installed Package β
Package ββββΆ β ClientID + ClientSecret β
(Setup) β + Auth/REST/SOAP base URIs β
ββββββββββββββββ¬ββββββββββββββββ
β POST /v2/token
β grant_type=client_credentials
βΌ
βββββββββββββββββββββββββββββββ
β ...auth.marketingcloudapis β
β returns: β
β access_token (~20 min) β
β rest_instance_url β
β soap_instance_url β
βββββββββ¬βββββββββββββββ¬ββββββββ
β Bearer token β
ββββββββββββββΌββββ ββββββΌββββββββββββββ
β REST β β SOAP β
β ...rest.mc... β β ...soap.mc... β
β journeys/eventsβ β DE CRUD / admin β
β transactional β β subscriber β
β assets/dataev. β β WSProxy β
ββββββββββββββββββ ββββββββββββββββββββ
CRM/MOD ββMarketing Cloud ConnectβββΆ Synchronized DEs
(Sales/Service Cloud) + Salesforce Data Events
π Core in 60 seconds
- Two APIs, one token. Auth once at
/v2/token, use the SAMEaccess_token(Bearer) for BOTH REST and SOAP. - REST = modern/JSON/fast β journeys, events, transactional messaging, assets, contacts, data events (rowset upsert).
- SOAP = legacy/XML/powerful β Data Extension CRUD, subscriber, admin, retrieves, anything WSProxy. AMPscript's
WSProxy/RetrieveSalesforceObjectsride SOAP under the hood. - OAuth 2.0 client_credentials (server-to-server): no user login, no refresh token. Token is short-lived (~20 min) β read
expires_infrom the response, refresh proactively, don't hardcode the number. (Legacy v1/requestTokenwas ~1 hour β don't confuse the two.) account_id= MID. Pass it in the token request to act on a specific Business Unit.- Base URLs come FROM the token response (
rest_instance_url,soap_instance_url) β never hardcode the subdomain. - MCC links CRM (MOD) β SFMC: Synchronized DEs pull CRM objects; Salesforce Data Events trigger journeys from CRM record changes.
- Fire a journey:
POST /interaction/v1/eventswithContactKey+EventDefinitionKey.
π§© Mnemonics & memory hooks
- REST vs SOAP β "REST takes a JET, SOAP washes the DASH"
- JET = Journeys, Events/assets, Transactional β REST.
- DASH = Data extensions, Admin, Subscriber, (WSProxy) Handling β SOAP.
- OAuth flow β "P-T-T-C": Package β Token β Twenty (min) β Call. "Pack a Token that lasts Twenty, then Call."
- Token response fields β "A.R.S.": Access_token, Rest_instance_url, Soap_instance_url. (Cover your ARS β grab all three.)
- Error codes β "401 = who? / 403 = no!"
- 401 Unauthorized = bad/expired token (identity unknown). 403 Forbidden = valid token, wrong scope/MID (known but blocked).
- Fire-journey payload β "CED": ContactKey, EventDefinitionKey, Data.
π Skeletons to memorize
1) Get the token (server-to-server)
POST https://SUBDOMAIN.auth.marketingcloudapis.com/v2/token
Content-Type: application/json
{
"grant_type": "client_credentials",
"client_id": "xxxxxxxxxxxxxxxx",
"client_secret": "yyyyyyyyyyyyyyyy",
"account_id": "7280000"
}
π Line by line:
- POST .../v2/token β the OAuth2 auth endpoint; subdomain comes from your Installed Package's Auth Base URI.
- Content-Type: application/json β payload is JSON (not form-encoded).
- grant_type: client_credentials β server-to-server flow; no human login, no refresh token.
- client_id / client_secret β the credentials generated by the Installed Package (treat secret like a password).
- account_id β the MID (Business Unit) you want to act in; omit to use the package's default BU.
Response gives you access_token, rest_instance_url, soap_instance_url, and expires_in (short-lived, ~20 min β read it, don't hardcode).
2) Fire a journey entry event (REST)
POST https://SUBDOMAIN.rest.marketingcloudapis.com/interaction/v1/events
Authorization: Bearer ACCESS_TOKEN
Content-Type: application/json
{
"ContactKey": "advisor_00482",
"EventDefinitionKey": "APIEvent-quarterly-statement",
"Data": {
"FirstName": "Priya",
"PortfolioId": "P-99213",
"StatementUrl": "https://secure.bank/stmt/P-99213"
}
}
π Line by line:
- POST .../interaction/v1/events β the endpoint that injects a contact into a journey.
- Authorization: Bearer ACCESS_TOKEN β the token from step 1; required on every REST call.
- ContactKey β the subscriber identifier (matches your DE/Contact key, e.g. advisor or client ID).
- EventDefinitionKey β copy from the journey's API Entry event; this is which journey to fire. Wrong/typo'd key β HTTP 400.
- Data {} β the event payload; fields must match the journey's Entry Source DE attributes for personalization (FirstName, PortfolioIdβ¦).
- Success = 201 with an eventInstanceId; inactive/missing contact or bad key = 400.
3) Upsert rows into a DE (REST data events / rowset)
POST https://SUBDOMAIN.rest.marketingcloudapis.com/hub/v1/dataevents/key:AdvisorMaster/rowset
Authorization: Bearer ACCESS_TOKEN
Content-Type: application/json
[
{ "keys": { "AdvisorId": "A-1001" },
"values": { "Email": "p@bank.com", "Tier": "Platinum", "OptStatus": "Subscribed" } }
]
π Line by line:
- .../hub/v1/dataevents/key:AdvisorMaster/rowset β upsert into the DE whose external key is AdvisorMaster (use key: for external key).
- Body is an array β you can upsert many rows in one call (batches well; great for sync jobs).
- keys {} β the DE's primary key(s); matched row is updated, unmatched row is inserted (true upsert).
- values {} β the non-key fields to write.
- Returns 2xx per accepted rowset; primary key MUST exist on the DE or it errors.
π οΈ In practice (what you would actually click / do)
A) Create the Installed Package (one-time, where credentials come from)
1. Setup (top-right gear/avatar) β Platform Tools β Apps β Installed Packages β New.
2. Name it (e.g. MOD-Integration), Save β Add Component β API Integration β Server-to-Server.
3. Tick scopes you need: Journeys (Read/Execute), Data Extensions (Read/Write), Email (Send), Automations, etc. Set the default Business Unit (MID).
4. Save β it generates Client ID, Client Secret, Auth/REST/SOAP Base URIs. Copy them into a vault (never in email/code).
B) Postman flow (the hands-on demo to describe in interview)
1. Get token: new request β POST {{authUri}}/v2/token, Body β raw JSON with grant_type/client_id/client_secret/account_id. Send β copy access_token, rest_instance_url.
- Pro move: in the Tests tab set pm.environment.set("token", pm.response.json().access_token) so it auto-saves; reuse as {{token}}.
2. Fire a journey: POST {{restUri}}/interaction/v1/events, Authorization β Bearer Token β {{token}}, body = the CED payload. Expect 201 + eventInstanceId.
3. Upsert DE rows: POST {{restUri}}/hub/v1/dataevents/key:AdvisorMaster/rowset, same Bearer header, array body. Verify in Email Studio β Subscribers β Data Extensions β AdvisorMaster β Records.
C) Wire the journey so the event works
1. Journey Builder β Create β Multi-step, Entry Source = API Event (or Salesforce Data event for CRM-driven).
2. Click the entry β set the Entry Source DE (the schema your Data{} maps to) β copy the generated EventDefinitionKey β paste into your POST.
3. Activate the journey (an API event journey must be Running or events 400/queue silently).
D) Marketing Cloud Connect (CRM/MOD β SFMC) 1. Installed in the CRM org as a managed package; connect SFMC via a dedicated integration user. 2. Synchronized Data Sources (Contact Builder β Data Sources) pull CRM objects (Contact, Lead, custom Advisor obj) into Synchronized DEs. 3. Salesforce Data events in Journey Builder let a CRM record change (e.g. "Advisor status = Active") enter a journey β no custom code. 4. Send-from-CRM: marketers send Email Studio emails to CRM Reports/Campaigns; sends/opens/clicks flow back to CRM activity.
E) RCA when an integration breaks (the support-model answer) - Reproduce the failing call in Postman with a fresh token first β rules out expiry instantly. - Read the HTTP code (401/403/400/429/5xx), check the integration user's scopes + MID, then check the payload/key mismatch.
π€ Rapid-fire
- Q: REST or SOAP to update a Data Extension? A: SOAP (or REST data events/rowset for upsert) β SOAP owns DE/subscriber/admin CRUD.
β¦and in practice: for a bulk sync I'd
POST /hub/v1/dataevents/key:DE/rowsetwith an array; for legacy/AMPscript I'd useWSProxyagainst SOAP. - Q: How long is an access token valid? A: short-lived β ~20 minutes (read
expires_in, don't hardcode); client_credentials has no refresh token β request a new one. (Legacy v1 /requestToken was ~1 hour.) β¦and in practice: I store the token + expiry timestamp and re-auth when <2 min remain. - Q: Which grant type for a backend integration? A:
client_credentials(server-to-server), no user interaction. - Q: Endpoint to drop a contact into a journey? A:
POST /interaction/v1/eventswith ContactKey + EventDefinitionKey. β¦and in practice: EventDefinitionKey is copied from the journey's API Entry event; journey must be Running. - Q: Where do REST/SOAP base URLs come from? A: the token response (
rest_instance_url,soap_instance_url) β tied to your tenant subdomain; don't hardcode. - Q: 401 vs 403? A: 401 = missing/expired/invalid token; 403 = valid token but lacks scope or wrong MID.
β¦and in practice: 401 β re-auth; 403 β edit the Installed Package scopes / fix
account_id. - Q: How does CRM data drive a journey without code? A: Marketing Cloud Connect β Salesforce Data event entry source on a Synchronized DE.
- Q: Send to 100 contacts in one journey call? A: use the Batch event (
/interaction/v1/events/batch) β up to 100 contacts per request. - Q: What's the MID and where do I pass it? A: the Business Unit ID; pass as
account_idin the token request to scope the token to that BU.
β οΈ Gotchas / RCA hooks
- Expired token (401): symptom = worked earlier, dead now (token aged out after ~20 min). Fix: re-fetch token; in code re-auth on any 401 and retry once.
- 403 Forbidden: token is fine but the Installed Package scope is missing (e.g. no "Journeys Execute") or wrong MID. RCA: open the package, compare granted scopes vs the call; check
account_id. - 400 on fire-event: wrong/typo'd EventDefinitionKey, journey not activated, or ContactKey inactive/missing. RCA: confirm journey is Running and the key matches the API entry event exactly.
- Hardcoded subdomain: breaks after a tenant migration. Always read
rest_instance_url/soap_instance_urlfrom the token response. - DE upsert silently "wrong":
keys{}didn't match the DE primary key β it inserts dupes instead of updating. RCA: verify PK definition in Contact Builder. - 429 Too Many Requests: you're hammering the API β implement backoff/retry; batch rowsets instead of per-row calls.
- Secret leaked / rotation: rotate Client Secret in the Installed Package immediately (critical in financial services); update the vault, not the code.
- MCC sync lag/failure: Synchronized DE not refreshing β check the integration user, sync schedule, and field-level security on the CRM object; this is a classic MODβSFMC INC ticket β start RCA at the integration user + sync logs.
- Compliance hook (FS): never log full tokens/secrets or PII payloads in ticket notes; suppress/respect OptStatus before any send fired via API.
β‘οΈ Next: C10_Support_Model_RCA_SLA.md
C10 β Support Model: INC, RCA, SLA & Troubleshooting (NEW β JD-critical)
π― Why Coforge cares: half the JD is run-the-platform β handle INC tickets for SFMC and MOD (CRM), do RCA, troubleshoot campaign/data/integration failures, hit SLA, coordinate critical issues. A Technical Lead is the person who calmly drives a Sev-1 send failure to closure. Theory won't save you here β you must say exactly how you'd triage.
π§ One-screen mental model
TICKET IN (INC / Sev) THE RCA LOOP (R-I-R-F-V-P) TICKET OUT
ββββββββββββββββββββββ βββββββββββββββββββββββββββββββββββββββββ ββββββββββββββββ
β User / monitor / β β 1 REPRODUCE can I see it myself? β β Fix verified β
β alert raises INC βββββΆβ 2 ISOLATE which LAYER broke? ββββΆβ + RCA doc β
β Assign severity β β 3 ROOT CAUSE the real "why" (5 whys) β β + prevention β
β Ack within SLA β β 4 FIX smallest safe change β β + comms sent β
β COMMUNICATE β β 5 VERIFY re-test, no regression β β SLA met β
β
ββββββββββββββββββββββ β 6 PREVENT monitor / guard / KB β ββββββββββββββββ
β² βββββββββββββββββββββββββββββββββββββββββ
β status updates every SLA interval (the part people forget)
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
THE 5 LAYERS you isolate across (memorize the order = signal flow):
DATA βββΆ CONTENT βββΆ RENDER βββΆ DELIVERABILITY βββΆ INTEGRATION (API/MCC/MOD)
"is the row right? β is the AMPscript right? β does it render? β did it reach? β did systems talk?"
π Core in 60 seconds
- INC vs other tickets: INCident = something broke (restore service). Compare: Service Request = "please do X" (new DE, access), Problem = the underlying root cause behind repeat INCs, Change = a planned modification. You'll live in INC + Problem + Change.
- Severity vs Priority: Severity = business impact (who/how much is hurt). Priority = order you work (impact Γ urgency). Sev-1 β always P1, but usually is.
- Sev ladder (FinServ flavour): Sev-1 = live send broken / wrong-data-to-clients / compliance breach / total outage. Sev-2 = major feature down, workaround exists. Sev-3 = minor / single-user. Sev-4 = cosmetic / question.
- SLA has two clocks: Response SLA (time to acknowledge) and Resolution SLA (time to fix). Missing comms cadence breaches SLA even if you're working the fix.
- The RCA loop = R-I-R-F-V-P: Reproduce β Isolate layer β Root cause β Fix β Verify β Prevent. Skipping Prevent = the same INC comes back next week.
- The 5 layers (signal flow): DATA β CONTENT β RENDER β DELIVERABILITY β INTEGRATION. Always isolate which layer before guessing a cause.
- MOD (CRM) tickets: the other half β data not syncing CRMβSFMC, advisor send (Distributed Marketing) failing, Marketing Cloud Connect login/sync errors. You triage across both systems and own the hand-off.
- Agile support model: daily stand-up (queue + aging tickets + Sev-1s), shared queue/backlog, on-call rota for after-hours Sev-1, swarming on majors, sprint to burn down Problems.
- Major Incident: a Sev-1 that needs coordination β you become Incident Commander: open a bridge, assign roles, drive comms, run the post-incident review (blameless RCA).
π§© Mnemonics & memory hooks
- RCA framework β "RIRFVP" β say "REPAIR-VP" β Reproduce, Isolate, Root-cause, Fix, Verify, Prevent. Hook: you're the VP of Repair β you don't just patch, you prevent.
- The 5 layers β "Don't Cook Raw Dodgy Ingredients" β Data, Content, Render, Deliverability, Integration. Hook: trace the signal kitchen-to-plate.
- Severity triage β "WHO-WHAT-WHEN-WORKAROUND" β Who is hit (1 vs all), What broke (send vs cosmetic), When (live send vs draft), Workaround? (yes β down a notch). Hook: 4 W's set the Sev.
- Ticket types β "I-S-P-C" β Incident, Service request, Problem, Change. Hook: "I Solve Problems & Changes."
- Sev-1 first moves β "ACT-C" β Assess scope, Contain (pause/stop the bleed), Tell stakeholders, Commander assigned. Hook: in a crisis, you ACT-Calmly.
- Comms cadence β "Heartbeat rule" β a Sev-1 with no update is a dead patient; send a heartbeat every interval even if it's "still investigating." Hook: silence breaches SLA.
- 5 Whys β "Ask why till it stops being a person's fault" β keep asking why until the answer is a system/process gap, not "Bob forgot." Hook: blame the process, not Bob.
π Skeletons to memorize
RCA write-up template (the artifact that closes a Sev-1):
INC-##### | Sev: 1 | System: SFMC (+ MOD) | Owner: A.Panda
SUMMARY : Mortgage-rate journey sent blank %%FirstName%% to 12,430 clients.
IMPACT : 12,430 advisor-branded emails, FinServ brand risk, 3 complaints.
TIMELINE : 09:02 send β 09:08 alert β 09:11 ack β 09:19 paused β 09:46 fixed.
ROOT CAUSE : SQL import to sendable DE ran AFTER the schedule fired (race) β
FirstName column null for new rows. (5-Whys: schedule order not enforced.)
RESOLUTION : Re-sequenced automation (import β wait β send); resent w/ AMPscript default.
DETECTION : Catch-block email alert on automation error fired in 6 min.
PREVENTION : (1) AMPscript IIF default on FirstName (2) verification step + row-count gate
(3) monitoring alert on null-key % (4) KB article linked.
SLA : Response 9m (β€15 β
) Resolution 44m (β€4h β
).
π Line by line:
- INC-#### / Sev / System / Owner β the header an interviewer wants first: what, how bad, where, who drove it.
- SUMMARY β one plain sentence a manager can read; lead with the user-visible symptom.
- IMPACT β quantify (count + business/compliance angle) β in FinServ "brand risk / complaints" is the language that matters.
- TIMELINE β timestamps prove SLA + show fast detectionβcontainment; this is your credibility.
- ROOT CAUSE β the real why via 5-Whys, ending at a process gap (schedule order), not a person.
- RESOLUTION β the smallest safe fix that restored service (re-sequence + resend).
- DETECTION β how you knew β proves monitoring exists (or exposes the gap to fix).
- PREVENTION β multiple guards so it can't recur: code default + verification + monitoring + KB.
- SLA β explicit response & resolution numbers vs target β this is what "SLA adherence" looks like on paper.
AMPscript defensive default (kills the #1 personalization INC):
%%[ VAR @fname SET @fname = AttributeValue("FirstName")
IF EMPTY(@fname) THEN SET @fname = "Valued Client" ENDIF ]%%
Dear %%=v(@fname)=%%,
π Line by line:
- VAR @fname / AttributeValue("FirstName") β pull the field into a variable so you can test it before printing.
- IF EMPTY(@fname) ... "Valued Client" β the guard: never let a blank/null field render an empty greeting to a client.
- %%=v(@fname)=%% β print the safe value; a missing-data row degrades gracefully instead of becoming a Sev-1.
Automation error alert (so a failure pages YOU, not the client):
SSJS Script Activity (last step) OR automation "Error" notification:
try { ...verification query / row count... }
catch(e) {
/* send alert email to support DL with automation name + error */
}
Automation Studio βΈ automation βΈ Settings βΈ "Notify on Error" β support@bank.com
π Line by line:
- try { verification } β run a sanity check (e.g., row count > 0, null-key % = 0) as a guarded step.
- catch(e) { send alert } β on failure, you get emailed with the automation name + error text β detection in minutes.
- Notify on Error β the no-code safety net: the built-in automation notification mails the support DL on any step failure.
π οΈ In practice (what you would actually click / do)
π΄ Triage a Sev-1 "campaign failed to send" under SLA β the exact runbook: 1. Acknowledge first (stop the clock): reply on the INC "Owned by A.Panda, investigating, next update in 15 min." Comms before cleverness. 2. Contain the bleed: Journey Builder βΈ open journey βΈ Pause (choose all running versions; decide whether to extend Wait durations) β or Automation Studio βΈ Pause/Stop the running automation. For a User-Initiated send: Email Studio βΈ Sent βΈ stop further sends. Don't fix yet β stop more bad emails first. 3. Find the failure: Automation Studio βΈ the automation βΈ Activities / Run History β red step + error text. For journeys: Journey Builder βΈ History / Journey Analytics β activity with high error/skip; search a single Subscriber Key in Contact History to see the exact failing step + message. 4. Isolate the layer (D-C-R-D-I): Did the import fail (Automation Studio error) = DATA? Did AMPscript throw = CONTENT? Renders but wrong = RENDER? Sent but bouncing = DELIVERABILITY? Marketing Cloud Connect / API / MOD sync error = INTEGRATION? 5. Confirm with data: Email Studio βΈ Subscribers or Data Extension βΈ Records β query the sendable DE; Tracking β Sends/Bounces/Errors; Setup βΈ Sender Authentication / SAP for deliverability. 6. Fix smallest-safe: re-sequence the automation, add AMPscript default, fix the SQL filter, re-validate the DE. Resend only the affected segment (build a DE of impacted SubscriberKeys, send to that). 7. Verify: send to a seed/test DE first; Preview & Test βΈ Preview with a real subscriber; row-count gate = 0 nulls; then release. 8. Close + RCA: fill the RCA template, link the KB article, add a monitoring alert so it self-detects next time.
Where the buttons live (memorize the click-paths): - Pause a journey: Journey Builder βΈ open journey βΈ ... menu / Pause βΈ choose current vs all versions βΈ optionally extend Wait-by-Duration. - Automation run history / errors: Automation Studio βΈ Overview βΈ open automation βΈ Activities tab / Run History βΈ click the red step. - Per-contact journey path: Journey Builder βΈ journey βΈ Contacts / History βΈ search SubscriberKey βΈ read step statuses. - Send / bounce / error tracking: Email Studio βΈ Tracking βΈ (Overview / Bounces / Not Sent). - Deliverability / auth: Setup βΈ Sender Authentication Package, and Email Studio βΈ Admin βΈ Reputation (or 250ok/Validity if licensed). - MCC / MOD sync errors: Setup βΈ Marketing Cloud Connect βΈ check API user + connection; in CRM check the Distributed Marketing managed package logs / Entry DE writes.
Set up so failures page you (prevention, the Tech-Lead move): - Automation Studio βΈ automation βΈ Settings βΈ Notify on Error/Skip/Complete β support DL. - Add a verification Script/Query step (row count, null %, dup check) as the last step before send; fail loud. - Journey Builder βΈ Validate before activate; Email βΈ Preview & Test with seed subscribers every deploy. - Keep a runbook + KB per recurring INC; review aging tickets at daily stand-up.
π€ Rapid-fire
- Q: Difference between an Incident and a Problem? β INC = restore service now; Problem = find/fix the root cause so INCs stop recurring. β¦and in practice: I open a Problem record when the same INC appears 3Γ β e.g. repeated null-personalization β and fix the process in a Change.
- Q: Severity vs Priority? β Severity = business impact; Priority = work order (impact Γ urgency). β¦and in practice: a cosmetic typo on a live FinServ disclosure email is low severity, high priority because compliance is urgent.
- Q: What's your RCA framework? β Reproduce β Isolate layer β Root cause (5-Whys) β Fix β Verify β Prevent. β¦and in practice: I always isolate across DATAβCONTENTβRENDERβDELIVERABILITYβINTEGRATION before touching anything.
- Q: First 3 things on a Sev-1 send failure? β Acknowledge/comms, contain (pause journey/automation), assess scope. β¦and in practice: I pause the journey for all running versions in Journey Builder before I even start diagnosing.
- Q: Personalization came out blank β why? β null/missing field, wrong attribute name, AttributeValue vs Lookup, or send fired before import. β¦and in practice: I check the sendable DE row, add an
IIF/IF EMPTYdefault, and re-sequence import-before-send. - Q: How do you find which contacts failed and where? β Journey Analytics for the failing activity, then search the SubscriberKey in Contact History. β¦and in practice: that pinpoints the exact step + error message per contact.
- Q: A MOD/CRM ticket says advisor emails aren't sending β where do you look? β Marketing Cloud Connect API user, the Distributed Marketing Entry DE writes, and the Journey behind the DM send. β¦and in practice: I confirm
sendFromEmailis a verified sender and the journey is available to DM. - Q: How do you prove you met SLA? β Timeline timestamps: ack time vs response SLA, resolved time vs resolution SLA, plus the comms log. β¦and in practice: I put the SLA line in the RCA doc with both numbers vs target.
- Q: What makes a good prevention step? β Layered: code guard + verification step + monitoring alert + KB. β¦and in practice: one fix isn't enough β I add a null-% monitor and an AMPscript default so it can't silently recur.
- Q: What's a blameless post-incident review? β Focus on system/process gaps, not the person; 5-Whys ends at a process fix. β¦and in practice: "schedule order wasn't enforced," never "Bob ran it early."
β οΈ Gotchas / RCA hooks
- Race condition: send fires before import finishes β blank personalization to live clients. RCA hook: re-sequence automation import β wait/verify β send; add row-count gate; AMPscript default as last line of defense.
- Pausing a journey silently extends Wait activities β contacts resume late or "stuck." RCA hook: on resume, check/extend Wait-by-Duration deliberately; avoid Waits < 15 min; final-step Waits can drop to ~1 min.
- "Contacts stuck in journey" β often a Wait still in progress, an unmet Decision Split, or a failed activity. RCA hook: search SubscriberKey in Contact History; if the final Wait hasn't completed it's just "in progress," not stuck.
- Deliverability dropped overnight β IP/domain reputation, SPF/DKIM/DMARC broke, spam-trap hit, or no suppression. RCA hook: check SAP/authentication, bounce category, recent list source; FinServ = enforce suppression + consent before resend.
- Data "not updating / segmentation wrong" β SQL query targeting stale DE, filter logic, or MCC sync lag CRMβSFMC. RCA hook: run the query manually, check the automation that populates the DE, verify the MCC sync ran; never trust a segment you didn't row-count.
- API/integration failure (REST/SOAP/MCC/MOD) β expired token, throttling/429, package permissions, or API user locked. RCA hook: check the API user, re-auth, inspect response code; 401=auth, 429=rate-limit, 500=SFMC side.
- SLA breached while you were "busy fixing" β you owe comms, not just a fix. RCA hook: set a recurring heartbeat update; the clock counts silence as a breach.
- Closing the INC without Prevent β it returns next cycle as a repeat. RCA hook: never close a Sev-1 without a monitoring alert + KB entry + (if recurring) a Problem record.
- Fixing on production with no test β you turn one INC into two. RCA hook: always seed-send to a test DE and Preview a real subscriber before the corrected resend.
β‘οΈ Next: C11_Deliverability_and_Compliance.md
C11 β Deliverability & Compliance
π― Why Coforge cares: advisor/financial-services emails are useless if they land in spam or break consent law β the JD wants someone who runs journeys, validates deployments, and resolves "campaign/data/integration failures" with proper RCA. Auth + consent IS the failure surface.
π§ One-screen mental model
YOUR SEND (SFMC) RECEIVER (Gmail/Yahoo) checks
---------------- ----------------------------
From: advisor@news.bankco.com
| 1) SPF -> "Is this IP allowed
| envelope (Return-Path/MAIL FROM) -----> to send for this domain?"
| bounce.sfmc-domain.com (checks Return-Path domain)
|
| DKIM signature (header) -----> 2) DKIM -> "Is the signature
| d=news.bankco.com valid? content untampered?"
|
v 3) DMARC -> "Does SPF or DKIM
Header From: news.bankco.com domain ALIGN with header From?
If fail -> p=none/quarantine/reject"
ALIGNMENT = the domains must MATCH the visible From
---------------------------------------------------------------------------
Pass all 3 + good reputation (low spam rate, clean list) => INBOX
Auth ok but bad reputation/content/traps => SPAM folder
Auth fail / blocklisted IP => BOUNCE / reject
π Core in 60 seconds
- SPF = which IPs may send for the domain (checks the envelope Return-Path). DNS TXT record.
- DKIM = cryptographic signature proving the mail wasn't tampered + came from the domain. Public key in DNS.
- DMARC = the policy that ties SPF/DKIM to the visible From via alignment, and tells receivers what to do on fail (
p=nonemonitor βp=quarantineβp=reject). Also enables reporting. - Alignment is the whole game: SPF/DKIM can pass for some random domain and DMARC still fails β the authenticated domain must match the From: domain the user sees.
- SAP (Sender Authentication Package) = the SFMC add-on that gives you a branded sending domain + dedicated IP + branded CloudPages/links/reply and lets you set SPF/DKIM/DMARC properly. FinServ should always be on SAP.
- Dedicated IP must be warmed = ramp volume slowly so the IP builds reputation (don't blast 1M on day 1).
- Hard bounce = permanent (bad address/domain) β suppress immediately. Soft bounce = temporary (mailbox full, server down) β retry, suppress after repeated fails.
- Gmail/Yahoo 2024 rules (bulk = 5,000+/day to Gmail): SPF + DKIM + DMARC (min
p=none), spam rate < 0.3% (aim < 0.1%), one-click List-Unsubscribe, honor opt-outs in 2 days. Enforced FebβApr 2024. - Laws: CAN-SPAM (US, opt-OUT), GDPR (EU, opt-IN + rights), DPDP (India, consent-first, 22-language notices, Consent Managers, under-18 = child).
π§© Mnemonics & memory hooks
- SPF / DKIM / DMARC = "Sender Permitted From / Don't Key-tamper / Decide Mismatch Action, Report Compliance."
- SPF = who's allowed (the guest list). DKIM = tamper seal (wax seal on the envelope). DMARC = the bouncer who checks the seal AND the name on the door (alignment) and decides reject/quarantine.
- Alignment = "Does the seal match the storefront sign?" SPF/DKIM can be valid for a back-alley domain; DMARC only passes if it matches the From the customer reads.
- Warming = "Idle the engine before flooring it." Cold IP + big blast = engine seize (blocklist).
- Gmail/Yahoo 2024 = "A.S.U. β All Senders Unsubscribe": Auth (SPF+DKIM+DMARC), Spam-rate < 0.3%, Unsubscribe one-click in 2 days.
- Laws = "US Opts-OUT, EU Opts-IN, India CONSENTS." CAN-SPAM=out, GDPR=in, DPDP=consent-first.
- FinServ compliance = "CASS": Consent (proof), Archival (retain sends), Suppression (honor & hold), Sensitive data (never PII like account/SSN in the email body).
- Bounce = "Hard = History (gone forever, suppress now). Soft = Snooze (retry, then suppress)."
π Skeletons to memorize
DNS records the auth standards live in (this is what you verify, not write in SFMC):
SPF (TXT @) v=spf1 include:cust-spf.exacttarget.com -all
DKIM (TXT s1._domainkey) v=DKIM1; k=rsa; p=MIGfMA0...<public key>...
DMARC (TXT _dmarc) v=DMARC1; p=quarantine; rua=mailto:dmarc@bankco.com; pct=100; aspf=s; adkim=s
π Line by line:
- v=spf1 include:... -all β declares SPF; include trusts SFMC's sending hosts; -all = hard-fail anything else (use ~all softfail while testing).
- s1._domainkey ... p=MIG... β the DKIM public key under a selector (s1); receivers fetch it to verify the signature SFMC adds with the private key.
- _dmarc ... p=quarantine β DMARC policy: p = action on fail (none/quarantine/reject), rua = where aggregate reports go, pct = % of mail the policy applies to, aspf=s/adkim=s = strict alignment (domains must match exactly, not just the org domain).
One-click unsubscribe headers the receiver looks for (SFMC adds these on commercial sends with SAP/correct config):
List-Unsubscribe: <https://click.bankco.com/unsub?id=%%subscriberid%%>, <mailto:unsub@bankco.com>
List-Unsubscribe-Post: List-Unsubscribe=One-Click
π Line by line:
- List-Unsubscribe: β gives a URL and a mailto so clients show a native "Unsubscribe" button; the URL carries the subscriber id so you can resolve who opted out.
- List-Unsubscribe-Post: ...One-Click β the 2024-required line that lets Gmail/Yahoo POST the opt-out without the user visiting a landing page; you must process it within 2 days.
AMPscript guard so sensitive accounts/PII never render in a FinServ email:
%%[
SET @acct = AttributeValue("AccountNumber")
SET @masked = Concat("****", Substring(@acct, Subtract(Length(@acct),4), 4))
]%%
Your account ending %%=v(@masked)=%% has a new statement.
π Line by line:
- SET @acct = AttributeValue(...) β pulls the raw account number from the sendable DE.
- Concat("****", Substring(...)) β keeps only the last 4 digits, masking the rest β never email a full account/SSN.
- %%=v(@masked)=%% β outputs the masked value; the full number stays in the DE, out of the email body and any forwarded copy.
π οΈ In practice (what you would actually click / do)
Set up / verify authentication (SAP):
- Setup β (gear) β Company Settings / Sender Authentication Package to confirm SAP is provisioned (branded domain, dedicated IP, branded links/CloudPages).
- Email Studio β Admin β Send Management β Sender Profiles β confirm the From name/address uses the authenticated domain (e.g. news.bankco.com), not the default *.exacttarget.com.
- Verify DNS externally: run the domain through MXToolbox (spf:, dkim:, dmarc: lookups) or dmarcian, and send a test to mail-tester.com for a 10/10 auth score before any FinServ campaign.
Diagnose "delivered but landing in spam" (the practical RCA they'll ask):
1. Send a seed/test to your own Gmail + Yahoo + Outlook (Email Studio β Preview & Test β send test, or a seed list). Open the message β Show original in Gmail to read SPF=PASS DKIM=PASS DMARC=PASS. Any FAIL β auth/alignment problem.
2. Google Postmaster Tools (postmaster.google.com, domain pre-verified via DNS): check Spam Rate (must be < 0.1%, hard line 0.3%), Domain/IP Reputation (want High/Medium), Authentication dashboard, and Feedback Loop. Yahoo β Sender Hub / CFL.
3. Check the IP/domain against blocklists (MXToolbox blacklist check, Spamhaus, SNDS for the IP).
4. Reputation/content fixes: if auth passes but reputation is poor β it's a list/content problem. In SFMC pull Tracking for the send (Email Studio β Tracking, or Reports) β high complaints/low engagement β tighten segmentation, run sunset suppression, check spammy subject/links and image-to-text ratio, ensure visible unsubscribe.
5. Confirm one-click unsub is present: view headers for List-Unsubscribe + List-Unsubscribe-Post. Missing β fix Sender Profile / commercial vs transactional classification.
Bounce handling & list hygiene:
- Email Studio β Tracking β Bounces, or build an Automation that queries _Bounce data view by BounceCategory (Hard / Soft / Block).
- Hard bounces β add to a suppression DE / All Subscribers status = Held; SFMC auto-holds after repeated hard bounces.
- Sunset policy = an Automation/SQL job that suppresses addresses with no opens/clicks in N days (e.g. 180) β query _Open/_Click data views, write non-engagers to a suppression DE, exclude it on every send (Send Definition β Exclusion).
Consent / suppression for FinServ: - Maintain a global suppression list (Email Studio β Subscribers β Suppression Lists or a master DE referenced as Exclusion) for opt-outs, complaints, and DNC. - Capture consent timestamp/source in the DE; for Distributed Marketing, advisors send from approved templates so consent + branding stay centrally controlled.
π€ Rapid-fire
- Q: What does SPF actually check? A: The envelope/Return-Path domain against the sending IP β not the visible From. β¦and in practice: in Gmail "Show original," SPF shows the
mailfrom/Return-Path domain, which under SAP is your branded bounce domain. - Q: SPF and DKIM pass but mail still fails DMARC β why? A: Alignment β the authenticated domain doesn't match the visible From domain. β¦and in practice: fix the Sender Profile to send from the SAP-branded domain so DKIM
d=aligns with From. - Q: Difference between p=none, quarantine, reject? A: none = monitor only (still inbox), quarantine = spam folder, reject = blocked outright. β¦and in practice: start
p=none, readruareports for weeks, then tighten. - Q: Hard vs soft bounce action? A: Hard = suppress immediately (permanent); soft = retry, suppress after repeated fails. β¦and in practice: query
_Bouncedata view byBounceCategoryin an Automation and write Hard to the suppression DE. - Q: Gmail/Yahoo 2024 must-haves? A: SPF+DKIM+DMARC, spam rate < 0.3%, one-click unsubscribe honored in 2 days; bulk = 5,000+/day to Gmail. β¦and in practice: verify spam rate in Postmaster Tools and the
List-Unsubscribe-Postheader in a seed test. - Q: What's an IP warm-up? A: Gradually ramping volume on a new dedicated IP so it earns reputation. β¦and in practice: send to your most-engaged segments first, increase daily volume on a schedule.
- Q: CAN-SPAM vs GDPR vs DPDP in one line each? A: US opt-OUT + honor unsub; EU opt-IN + data rights; India consent-first, multi-language notice, Consent Managers.
- Q: What's a spam trap? A: An address that only exists to catch senders with poor hygiene (pristine traps never opted in; recycled traps are abandoned addresses). β¦and in practice: a sunset policy removing long-term non-engagers is your main defense.
- Q: How do you prove a FinServ email is compliant? A: CASS β Consent record, Archival of the send, Suppression honored, Sensitive data masked.
β οΈ Gotchas / RCA hooks
- "It went to spam but auth passes" β it's reputation/content/list, not auth. RCA: Postmaster spam-rate + reputation, then segmentation/sunset, not DNS.
- Alignment trap: copying SPF/DKIM but still sending from the default
*.exacttarget.comFrom β DMARC fails. Always send from the SAP branded domain. - Cold dedicated IP blasted at full volume β instant blocklist + spam folder. Warm it; ramp by engagement tier.
- Soft bounces ignored β repeated retries to dead mailboxes quietly tank reputation. Automate suppression after N soft fails.
- Missing/late unsubscribe β opt-outs not honored within 2 days = Gmail/Yahoo penalty + legal exposure. RCA: check
List-Unsubscribe-Postheader + that the suppression job runs on schedule. - Sensitive data leak: full account number/SSN in the body β compliance incident even if delivered. Mask with AMPscript; never email PII.
- Spam traps from old purchased lists β never buy lists; FinServ must use consented, sunset-maintained lists only.
- DMARC
p=rejectset too early β legit mail rejected; treat as a P1 incident. RCA: readruareports first, fix alignment, then escalate the policy gradually.
β‘οΈ Next: C12_FinServ_and_Lead_Behaviors.md
C12 β Financial-Services Domain & Technical-Lead Behaviors
π― Why Coforge cares: this is a Technical-Lead seat in Financial Services β they need someone who runs advisor/client campaigns under compliance, consent & suppression, leads RCA & major incidents to SLA, and makes solution/trade-off calls for a team β not just an AMPscript coder.
π§ One-screen mental model
FINANCIAL-SERVICES SFMC (advisor β client, regulated)
βββββββββββββββββββββββββββββββββββββββββββββββββββββ
CENTRAL MARKETING (you/lead) DISTRIBUTED MARKETING
builds compliant templates ββββββββΊ advisor sends from
+ locked content + approvals CRM (Quick Send)
β
βΌ
DATA ββΊ [Consent/Preference] ββΊ [Suppression] ββΊ SEND ββΊ Client
(PII) opt-in/opt-down global block β
β β β βΌ
βΌ βΌ βΌ [Tracking +
encrypt / Publication Lists Suppression ARCHIVE/AUDIT]
field-level + Profile Center List + Excl. (who got what,
security (subscriber choice) Script (logic) when, version)
βββββββββββββββββ LEAD WRAPS THE WHOLE THING βββββββββββββββββ
β DesignβΈEstimateβΈReviewβΈMentorβΈCommunicateβΈRCAβΈPlan-for-Peak β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
π Core in 60 seconds
- FS = consent is king. No send without provable opt-in. Every comm must be suppressible, auditable, archivable.
- Advisor model = Distributed Marketing (DM). Central team owns compliant, locked templates; advisors personalize + send from Sales/Service Cloud via Quick Send / campaigns; approval workflow can gate the send.
- Two layers of "don't send": Preference (subscriber's choice β Publication Lists / Profile Center) vs Suppression (your internal hard block β Suppression List + Exclusion Script). Both filter; suppression always wins.
- PII handling: minimize PII in DEs, use Field-Level Encryption (and Tokenized Sending for SMS/MobileConnect, where a token replaces PII in the message), keep Einstein off regulated data, restrict via Roles/Business Units, never log PII in scripts/error tables.
- Audit/archival: keep send logs, template versions, approval trail, consent timestamps β FS regulators (FINRA/SEC-style) expect "prove who approved & who received what."
- Lead β doer. You own solution design, estimates, code standards, mentoring, stakeholder comms, RCA leadership, peak/capacity planning, Agile ceremonies.
- SLA mindset: P1/P2 incidents on SFMC and MOD (CRM) β triage β mitigate β RCA β preventive action.
π§© Mnemonics & memory hooks
- FS data rules = "CASPA" β Consent, Archive, Suppress, PII-protect, Approve. "In finance, you CASPA before you cast."
- Lead behaviors = "DERM-SCAP" β Design, Estimate, Review (code), Mentor β Stakeholder-comm, Capacity/peak, Agile, Postmortem(RCA). "A good lead has thick DERM and a SCAP-el for incidents."
- Don't-send layers = "PuSE" β Publication list (preference) β Suppression list β Exclusion script. "PuSE the brakes before every send." (left-to-right = subscriber choice β hard block β runtime logic)
- Incident order = "DRIP" β Detect, Restore (mitigate first), Investigate (RCA), Prevent. "Stop the DRIP before you find the leak."
- Approval flow = "SEAL" β Submit, Edit-lock, Approve, Launch. "In FS, every send carries a SEAL."
π Skeletons to memorize
1. Exclusion Script (runtime "don't send" with logic β the FS suppression workhorse)
%%[
/* runs per-subscriber at send time; true = EXCLUDE this person */
VAR @consent, @hardBounce
SET @consent = AttributeValue("EmailConsent")
SET @hardBounce = AttributeValue("HardBounceFlag")
IF @consent != "Y" OR @hardBounce == "true" THEN
RaiseError("Excluded: no consent / bounced", false)
ENDIF
]%%
π Line by line:
- VAR/SET @consent β pull the subscriber's consent flag from the sendable DE/profile at send time.
- @hardBounce β pull a deliverability flag so you never re-mail a dead address (FS reputation matters).
- IF ... RaiseError(msg, false) β if not opted-in or bounced, raise error; the false means "skip just this subscriber," not the whole send.
- Net effect: only provably-consented, deliverable contacts get the email β defensible in an audit.
2. AMPscript regulated-disclosure + advisor personalization block
%%[
VAR @advName, @advNMLS, @client
SET @advName = AttributeValue("AdvisorName")
SET @advNMLS = AttributeValue("AdvisorLicenseID")
SET @client = AttributeValue("FirstName")
]%%
Dear %%=v(@client)=%%, your advisor %%=v(@advName)=%% (Lic# %%=v(@advNMLS)=%%)...
<!-- Required FS disclosure stays hard-coded, NOT advisor-editable -->
π Line by line: - Pull advisor identity + license/NMLS ID β regulated comms must name the licensed sender. - Greet the client by first name only (minimize PII in body). - The disclosure line is template-locked so an advisor in Distributed Marketing can't strip mandatory legal text.
3. SQL: build a daily suppression DE (consent + cooling-off + DNC)
SELECT s.SubscriberKey, s.EmailAddress
FROM Master_Contacts s
WHERE s.EmailConsent <> 'Y'
OR s.DoNotContact = 'Y'
OR s.LastContactDate > DATEADD(day, -7, GETDATE()) -- frequency cap
π Line by line:
- Pull anyone not opted-in β must be suppressed.
- DoNotContact = 'Y' β honors DNC / regulator request.
- LastContactDate > -7 days β enforces a frequency cap / cooling-off so clients aren't over-mailed.
- Output DE is attached as a Suppression List on the send β centrally enforced, audit-friendly.
π οΈ In practice (what you would actually click / do)
Set up advisor sends (Distributed Marketing): - In Marketing Cloud Setup βΈ Distributed Marketing, install the managed package into Sales/Service Cloud; map the sending BU and DM-enabled DEs. - Build the email in Content Builder, then in DM mark regions as locked vs editable so advisors edit only approved zones. - Advisor side: opens a Contact/Lead/Campaign record βΈ Quick Send (single) or a DM Campaign (bulk/segment) βΈ personalizes editable fields βΈ Preview (bulk preview shows first 100) βΈ Submit for approval βΈ Send/Schedule. - Turn on manual approval in DM so a compliance reviewer must approve before launch.
Enforce consent & suppression on a normal Email Studio send: - Email Studio βΈ Subscribers βΈ Suppression Lists βΈ create list / import the daily suppression DE. - In Guided Send βΈ Step "Who", attach the Suppression List; in Step "Options/Delivery" paste an Exclusion Script for runtime logic. - Subscriber preferences: Email Studio βΈ Subscribers βΈ Publication Lists + a CloudPage Profile/Subscription Center so clients self-manage opt-downs.
Protect PII / lock down access:
- Setup βΈ Users βΈ Roles β least-privilege; advisors get send-only, not data export.
- Setup βΈ Business Units β segregate regulated data; sensitive DEs live in a restricted BU.
- Use Field-Level Encryption for PII at rest (and Tokenized Sending for SMS/MobileConnect, where a token stands in for PII); never write PII into _Bounces/error DEs or RaiseError text.
Audit & archival (the FS differentiator):
- Keep Tracking + Data Views (_Sent, _Open, _Click, _Bounce) exported nightly via Automation Studio to an archive DE / SFTP.
- Version templates in Content Builder (or external repo) and retain the DM approval trail β answer "who approved, who received, which version, when."
Lead-the-work moves (say these out loud in interview): - "I'd run a discovery β solution-design doc β effort estimate (T-shirt/story points) before the team codes." - "I enforce code review against a standards checklist (AMPscript guard-rails, no PII in logs, naming, error handling)." - "For peak (e.g., statement season / rate-change blast), I do capacity planning: pre-warm sends, stagger throttling, lock change-freeze windows." - "In Agile ceremonies I groom the backlog, size stories, run stand-ups, and own the demo + retro actions."
Reframed GAP STAR stories (FS / Tech-Lead lens):
| Your GAP story | FS Tech-Lead reframe |
|---|---|
| DE Lookup WSProxy tool | "Built reusable SSJS/WSProxy data-lookup so the team validated client/advisor data accuracy fast β I designed it as shared tooling and mentored juniors to use it." |
| Dynamic barcodes / countdowns (MovableInk) | "Real-time personalization, but in FS I'd gate it β no live-personalized regulated figures without approval; show design trade-off awareness." |
| A/B testing framework | "Led a standardized A/B + validation framework = my code-standards/quality contribution; in FS, A/B only on non-regulated copy, never on disclosures." |
| VAWP / Peak escalation | "Led the major-incident bridge: detected, mitigated send failure, ran RCA, drove preventive action + capacity plan for next peak β exactly the SLA/RCA lead behavior." |
3 questions to ask the interviewer: 1. "How is Distributed Marketing / advisor sending set up today β central templates with locked content, and where does compliance approval sit in the flow?" 2. "What does the incident model look like for SFMC + MOD β SLA tiers, who leads RCA, and how mature is the preventive-action loop?" 3. "What are the biggest data-accuracy / consent pain points the team hits during peak (statements, rate changes), and how do you currently plan capacity?"
π€ Rapid-fire
- Q: Preference vs suppression? A: Preference = subscriber's choice (Publication List/Profile Center); suppression = your hard block. Suppression always wins. β¦and in practice: attach a Suppression List in Guided Send "Who," manage preferences via a CloudPage subscription center.
- Q: How do advisors send compliant emails themselves? A: Distributed Marketing β central locked templates, advisor personalizes editable zones, optional manual approval, then Quick Send/campaign. β¦and in practice: record βΈ Quick Send βΈ edit βΈ preview βΈ submit for approval βΈ send.
- Q: Suppression list vs exclusion script β when each? A: List = static/known keys (DNC, bounces). Script = runtime logic on profile attributes. β¦and in practice: combine β daily SQL builds the list, exclusion script catches edge logic at send time.
- Q: How do you keep PII safe? A: Least-privilege Roles, restricted BUs, field-level encryption (Tokenized Sending for SMS), no PII in logs/error text.
- Q: What's your incident order? A: DRIP β Detect, Restore (mitigate), Investigate (RCA), Prevent. Mitigate before you diagnose.
- Q: As a lead, how do you estimate? A: Discovery β break into stories β T-shirt/story-point sizing with buffer for testing/validation; surface risks early.
- Q: How do you run code review on AMPscript? A: Standards checklist β error handling, no PII in logs,
RaiseError(...,false)for per-sub skip, naming, idempotent automations, peak-safe throttling. - Q: How do you prove a regulated send was compliant? A: Consent timestamp + suppression applied + approval trail + template version + Data View send logs archived to SFTP.
β οΈ Gotchas / RCA hooks
RaiseErrorwithoutfalsekills the whole send, not one subscriber β in FS that's a missed regulated comm. RCA: check the exclusion/error script's second arg; alwaysfalsefor per-subscriber skip.- Suppression not applied / wrong DE attached β opted-out client gets mailed = compliance breach. RCA: verify the Suppression List on the send job + that the nightly SQL automation actually ran (Automation Studio activity log).
- PII leaked into
_BouncesorRaiseErrortext β audit finding. RCA: scrub scripts; log SubscriberKey only, never email/SSN/account numbers. - Advisor edited locked content (DM mis-configured) β unapproved legal text goes out. RCA: confirm locked regions + manual-approval toggle in DM setup.
- Frequency cap missed during peak β over-mailing, spam complaints, sender-reputation drop. RCA: check cooling-off SQL window + send throttling; add to capacity plan.
- Approval bypassed (scheduled send skipped review) β note: scheduling is allowed only when manual approval isn't required; if compliance needs review, don't enable schedule-without-approval. RCA: audit DM approval settings.
- MOD (CRM) β SFMC sync lag β stale consent flag, you mail someone who just opted out. RCA: check integration/sync job timing; suppress on the freshest source of truth, add reconciliation step.
β‘οΈ Next: C13_Memory_Vault.md
C13 β Memory Vault (everything to recall, in one place)
π― Why Coforge cares: this is your pre-interview cram sheet β one screen that reloads the whole SFMC stack (campaigns, journeys, DEs, SQL, AMPscript, APIs, deliverability, RCA, SLAs) so you answer fast and hands-on, not theory-only.
π§ One-screen mental model
THE WHOLE COURSE ON ONE PAGE
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
PEOPLE Contact (Contact Key) ββ same key βββΆ Subscriber (Subscriber Key)
All Contacts β All Subscribers
β
DATA Data Extensions (6 types) ββ SQL / imports βββΆ Automation Studio
β (sendable + linked to _SubscriberKey)
βΌ
PERSONALIZE AMPscript / Dynamic Content ββ Lookup() into other DEs βββΆ rendered email
β
SEND Email Studio ββ Send Classification (sender+delivery) βββΆ ISP
Journey Builder ββ Entry β Wait/Decision β Activities βββΆ Goal
Distributed Mktg ββ advisor picks journey β personalize β approve β send
β
PROTECT SAP: SPF + DKIM (Salesforce sets) ; DMARC (you add) βββΆ inbox not spam
β
MEASURE Data Views (_Sent _Open _Click _Bounce _Sub _Job) β Analytics / SQL
β
INTEGRATE REST/SOAP APIs ββ OAuth2 v2/token (~20 min) βββΆ MOD/CRM
β
SUPPORT INC ticket β Triage β RCA loop β Fix β SLA met β Postmortem
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
π Core in 60 seconds
- Studios DO, Builders DEFINE. Email/Mobile/Web/Automation act; Contact/Journey/Content/Analytics set up.
- One human = one Contact Key = same Subscriber Key. All Contacts β All Subscribers. Key is sacred β never the email, use the MOD id.
- DEs hold data; SQL/imports shape it; Automation Studio runs it on a schedule. Sendable DE = "Is Sendable" + field linked to
_SubscriberKey. - AMPscript pulls fields at send time:
Lookup= 1 value,LookupRows= set,LookupOrderedRows= sorted set (β€2,000). - Send Classification = Sender (face) + Delivery (truck). Transactional sends ignore unsubscribe (OTP/statements must arrive).
- Journey = Entry β Wait/Decision β Activities β Goal. Version-locked once activated; re-publish for changes.
- Distributed Marketing = central brain, local hands: advisor picks journey, personalizes, submits for approval, sends.
- Deliverability = SAP (SPF+DKIM by Salesforce) + DMARC (you). DKIM aligns to the visible From domain.
- APIs: REST for speed/JSON (
/data,/messaging,/interaction), SOAP for full object CRUD + Retrieve. OAuth2v2/token, token is short-lived (~20 min β readexpires_in). - Metrics from Data Views:
_Sent _Open _Click _Bounce _Subscribers _Job. Support = INC β triage β RCA loop β SLA.
π§© Mnemonics & memory hooks
Every mnemonic from C01βC12, in one list:
- Studios vs Builders β "Build it, then Studio-use it." Builders are nouns, Studios are verbs.
- The Studios β "Every Morning Web Admins Automate" (E-M-W-A): Email, Mobile, Web, Automation. An admin every morning automates the channels.
- Contact vs Subscriber β "Same key, two hats." One person, one key β put on the email hat and it's the Subscriber Key.
- Data Views β "SOCBS" (or "SOCUB-J" with Job): Sent, Open, Click, (Unsub), Bounce, Subscribers, Job. "Send Often, Check Bounces, Suppress."
- DE types β "Stan Filled Random Shared Sync'd Salesforce" (Standard/Filtered/Random/Shared/Synchronized/Salesforce). Six drawers in the data cabinet.
- Make a DE sendable β "TICK + LINK": TICK "Is Sendable", then LINK the field to
_SubscriberKey. "Tick the box, link the soul." - Field config β "P.N.R.D." ("pin-ride"): Primary key? Nullable? Required? Default/Data-type/length. PNRD every column before you save.
- All Subscribers statuses β "A-HUB": Active, Held, Unsubscribed, Bounced. Every contact parks in the A-HUB.
- SQL update types β "OUA = Obliterate, Upsert, Add": Overwrite, Update (upsert), Append.
- Join key β "Same person, same SEND": SubscriberKey + JobID. Who + which send.
- AMPscript lookups β "One, many, many-sorted":
Lookup/LookupRows/LookupOrderedRows. - Rows loop β "C-R-F = Count, Row, Field":
RowCountβRow(@rs,i)βField(@row,"Col"). Count the Rows, Fetch each Field. - AMPscript block β "V-S-I-O = VAR, SET, IF, Output." Very Smart If Output.
- Safe output β "V for visible, E for empty-check": wrap in
v(), guard withEmpty()/IIF(). - The wall β "two grand and you're grounded": ordered lookups cap at 2,000 rows.
- Send Classification β "S-D-C = Sender, Delivery, Compliance." Who / How / Legal.
- Sender vs Delivery β "Sender = the FACE, Delivery = the TRUCK." Face = From/Reply-to; Truck = IP, domain, footer.
- Send modes β "U-T-T = User, Triggered, Transactional." You Type, Trigger Trips, Trans Talks.
- Commercial vs Transactional β "Transactional = no unsubscribe."
- Content Builder β "TSB = Templates have Slots, Slots hold Blocks." Russian-doll: T β S β B.
- QA checklist β "PRLACVP" = "PuRe LACK of VP" (no VP signs off if QA fails): Preview, Render, Links, Audience, Classification, Volume, Personalization.
- Compliance four β "FUSS" (make a FUSS before any finance send): Footer (address), Unsub link, Sender/classification, Suppression applied.
- Deploy promotion β "D-Q-P, Package, Pin": Dev β QA β Prod via Package Manager, Pin in Git.
- Render killers β "OLD": Outlook (Word engine), Length/clipping (Gmail 102 KB), Dark mode. OLD clients break new emails.
- Distributed Mktg plumbing β "PCJ": Package (managed), Connect (Marketing Cloud Connect), Journey (Builder). PB&J connects two clouds.
- What an advisor does β "P-A-S-S": Pick journey β Add/personalize β Submit for approval β Send. An advisor needs a PASS to talk to clients.
- DM value prop β "Central Brain, Local Hands."
- DM sender β "FROM = Name + Email":
sendFromName+sendFromEmailin the Entry DE. - Quick Send vs Add-to-Journey β "1 vs Many."
- REST vs SOAP β "REST is Fast/JSON, SOAP is Full/XML." REST to do, SOAP to define.
- OAuth β "Client gives ID+Secret, gets a short-lived Bearer." Token β 20 min (v2/token). (Legacy v1 /requestToken was ~1 hour β don't confuse them.)
- Deliverability stack β "SPF Says who, DKIM Signs, DMARC Decides."
- RCA loop β "REPAIR-VP" (RIRFVP): Reproduce, Isolate layer, Root-cause (5-Whys), Fix, Verify, Prevent. Hook: you're the VP of Repair β you prevent, not just patch.
- Ticket priority β "P1 = Page now": P1 down/compliance, P2 major, P3 minor, P4 cosmetic. Lower number = louder pager.
π Skeletons to memorize
1) AMPscript lookup + safe default (the FinServ workhorse):
%%[
VAR @first, @advisor
SET @first = AttributeValue("FirstName")
IF Empty(@first) THEN SET @first = "Valued Client" ENDIF
SET @advisor = Lookup("Advisors","AdvisorName","ContactKey", _subscriberkey)
IF Empty(@advisor) THEN SET @advisor = "your Gap Financial team" ENDIF
]%%
Dear %%=v(@first)=%%, your advisor %%=v(@advisor)=%% has an update.
π Line by line:
- VAR @first, @advisor β declare variables up top (V of V-S-I-O).
- SET @first = AttributeValue("FirstName") β read the sendable-DE column for this subscriber; returns "" if missing (no error).
- IF Empty(@first) THEN ... ENDIF β fallback so you never render "Dear ,".
- Lookup("Advisors","AdvisorName","ContactKey", _subscriberkey) β cross-DE join: get AdvisorName from the Advisors DE where ContactKey = the built-in _subscriberkey.
- %%=v(@first)=%% β v() outputs the variable into the rendered HTML.
2) Dedup SQL β keep the freshest row per subscriber:
SELECT SubscriberKey, EmailAddress, ModifiedDate
FROM (
SELECT SubscriberKey, EmailAddress, ModifiedDate,
ROW_NUMBER() OVER (PARTITION BY SubscriberKey ORDER BY ModifiedDate DESC) AS rn
FROM Master_Contacts
) x
WHERE rn = 1
π Line by line:
- ROW_NUMBER() OVER (PARTITION BY SubscriberKey ORDER BY ModifiedDate DESC) β number rows within each subscriber, newest first.
- AS rn β name that number.
- WHERE rn = 1 β keep only the single freshest row per subscriber = deduped audience.
3) Suppression join β exclude opt-outs before a finance send:
SELECT a.SubscriberKey, a.EmailAddress, a.FirstName
FROM Audience a
LEFT JOIN Suppression s ON a.SubscriberKey = s.SubscriberKey
WHERE s.SubscriberKey IS NULL
AND a.OptInStatus = 'Subscribed'
π Line by line:
- LEFT JOIN Suppression s β attach any suppression match to each audience row.
- WHERE s.SubscriberKey IS NULL β keep only rows with NO suppression match (anti-join = exclude suppressed).
- AND a.OptInStatus = 'Subscribed' β belt-and-braces: only consented contacts.
4) OAuth token request (REST):
curl -X POST https://YOURSUBDOMAIN.auth.marketingcloudapis.com/v2/token \
-H "Content-Type: application/json" \
-d '{"grant_type":"client_credentials","client_id":"XXX","client_secret":"YYY","account_id":"MID"}'
π Line by line:
- POST .../v2/token β the tenant-specific OAuth2 endpoint (subdomain comes from your Installed Package).
- grant_type":"client_credentials" β server-to-server flow (no user login).
- client_id / client_secret β the credentials from the Installed Package's API Integration component.
- account_id":"MID" β optional Business Unit MID to scope the token to a child BU.
- Response gives access_token (use as Authorization: Bearer ...) and expires_in (short-lived, ~20 min β read it, don't hardcode).
π οΈ In practice (what you would actually click / do)
- Build a sendable DE: Email Studio β Subscribers β Data Extensions β Create β Standard β name it β in the create wizard tick Is Sendable, set Send Relationship = your key field β Subscriber Key, email field β Email Address β set Retention for compliance β Save.
- Write + run SQL: Automation Studio β Activities β SQL Query β write the dedup/suppression query β set Target DE + update type (Overwrite/Update/Append) β Save β drag into an Automation β schedule or trigger via File Drop β Run Once to test β check the target DE row count.
- Personalize + preview: Content Builder β open the email β drop AMPscript in an HTML block β Preview & Test β pick a specific subscriber/DE row β confirm
@advisorresolves, no empty greeting β send a test send to your seed list. - Build a journey: Journey Builder β Create New Journey β Entry Source = the sendable DE (set evaluation/refresh) β drag Wait, Decision Split (e.g., Opened?), Email activities β set Goal β Validate β Activate (locks the version).
- Distributed Marketing send: advisor opens DM in Sales/Service Cloud β Use a Journey / Quick Send β picks the marketer-approved journey β personalizes the message β Submit for approval β on approval it sends from
sendFromName/sendFromEmail. - Set up an API integration: Setup β Installed Packages β New β add an API Integration (OAuth2) component β copy Client Id/Secret + the auth/rest base URIs β POST to
v2/tokenβ call/data/v1/...or/interaction/v1/...with the Bearer token. - Deploy promotion: build in Dev BU β QA validates with the PRLACVP/FUSS checklist β move assets via Package Manager (or Deployment Manager) DevβQAβProd β tag/pin the version in Git.
- RCA on a failed send: Automation Studio β check the Automation's Activity / error log β reproduce with one row in Preview β trace whether it's data (DE), logic (AMPscript/SQL), or integration (API/Connect) β fix β re-run β write the postmortem.
π€ Rapid-fire
Q1. Contact Key vs Subscriber Key? β Same string for one human; Contact Key is the account-wide id, Subscriber Key is the email-channel id.
Q2. How do you make a DE sendable? β Tick "Is Sendable" and link a field to All Subscribers _SubscriberKey. β¦and in practice: I do it in the DE create wizard's Send Relationship step in Email Studio.
Q3. Lookup vs LookupRows vs LookupOrderedRows? β One value / a set / a sorted set (β€2,000 rows).
Q4. How do you dedup an audience? β ROW_NUMBER() OVER (PARTITION BY key ORDER BY date DESC) then WHERE rn = 1. β¦and in practice: I run it as a SQL Query activity into a clean target DE in Automation Studio.
Q5. Three SQL update types? β Overwrite (truncate+insert), Update (upsert on PK), Append (insert only).
Q6. Commercial vs transactional send? β Transactional (OTP, statements) ignores unsubscribe and must be delivered; commercial honors opt-out.
Q7. What locks when you activate a journey? β The version is locked; to change logic you create/publish a new version. β¦and in practice: I pause/stop, copy to a new version, edit, validate, re-activate.
Q8. REST vs SOAP in SFMC? β REST = fast JSON for sends/data/journeys; SOAP = full object CRUD + Retrieve with paging. β¦and in practice: I use REST /data/v1 for DE rows, SOAP Retrieve for bulk object reads.
Q9. How long does an OAuth token last and how do you get one? β short-lived, ~20 min (read expires_in; no refresh token β just re-request); POST client_id/secret to the tenant v2/token endpoint, then send Authorization: Bearer.
Q10. SAP vs DMARC β who sets what? β Salesforce SAP configures SPF + DKIM for your sending domain; you add the DMARC TXT record. DKIM aligns to the visible From domain.
Q11. Where do email metrics live? β Data Views (_Sent, _Open, _Click, _Bounce, _Subscribers, _Job) joined on SubscriberKey + JobID. β¦and in practice: I SQL the Data Views into a reporting DE feeding Analytics Builder.
β οΈ Gotchas / RCA hooks
- Empty personalization / "Dear ," in production β missing column or failed Lookup. RCA: Preview the exact row, check the source DE field and the Lookup key match; add
Empty()fallbacks. - Send excludes people you expected β wrong send relationship, unmatched Subscriber Key, or over-broad suppression. RCA: count rows in the sendable DE vs the suppression anti-join.
- Journey won't pick up new contacts β entry-source evaluation/refresh not set, or contacts already went through. RCA: check entry DE refresh schedule + re-entry rules.
- DMARC fails even though SPF "passes" β SPF passes the SAP bounce domain, not the From domain. RCA: rely on DKIM alignment to the From domain; confirm the DMARC TXT and DKIM CNAME records.
- 401 from the API β token expired (~20 min) or wrong BU MID. RCA: re-request token, scope to correct
account_id, confirm the Installed Package scopes. - Automation failed overnight β file didn't drop, SQL target locked, or a query timed out. RCA: open the Automation error log, reproduce the SQL on a small set, check the import file path/SFTP.
- Duplicate sends β un-deduped audience or journey re-entry. RCA: add the
ROW_NUMBERdedup and tighten re-entry to "no re-entry."
β‘οΈ Next: C14_Practical_Drills_and_Mock.md
C14 β Practical Drills & Mock (the LTM-gap fix)
π― Why Coforge cares: the role is a hands-on Technical Lead β build/validate/deploy campaigns, fire journeys, fix INC tickets, run RCA under SLA. They will ask "show me HOW," not "what is it." This module turns your theory into click-paths.
π§ One-screen mental model
EVERY PRACTICAL ANSWER = 3 LAYERS
βββββββββββββββββββββββββββββββββββββββββββββββββ
(a) β THEORY β "what it is" (1 sentence, no more)β
βββββββββββββββββββββββββββββββββββββββββββββββββ€
(b) β PRACTICAL β "here is exactly what I click / β β they want THIS
β write / run" (the click-path) β
βββββββββββββββββββββββββββββββββββββββββββββββββ€
(c) β GOOD vs WEAKβ "I also verify X / suppress Y" β β seniority signal
βββββββββββββββββββββββββββββββββββββββββββββββββ
|
v
THE TELL: stop after 1 theory line, then say
"...and the way I'd actually do that is β go to X > click Y > ..."
π Core in 60 seconds
- The fix for "too theoretical" = after one definition sentence, pivot with "...and the way I'd actually do it is β" then narrate clicks.
- Always name the exact place: Studio > screen > button. Vague = weak.
- Always end practical answers with a verify step (Preview, Validate, test send, Tracking, query row count).
- For financial services, every send answer must mention suppression + compliance + approval.
- Mock yourself on a timer (90s/answer). The LTM gap was pacing + concreteness, not knowledge.
π§© Mnemonics & memory hooks
- The 3 layers = "T-P-G" β "Theory, then Prove it, then Good-vs-weak." Say the prove-it part out loud always.
- Every send = "BAT-VS-D" β Build β Audience β Test β Validate β Send β Deliverability check. "A BAT VS a Dragon."
- RCA = "5W + Fix + Prevent" β What broke, When, Where, Who-hit, Why, Fix, Prevent-recurrence. "Five W's, Fix, Forever."
- Debug blank personalization = "DARTS" β Data present? Attribute name spelled right? Relationship (sendable DE)? Typo/case? SubscriberKey match? "Throw DARTS at blank fields."
- Deliverability drop = "CRABS" β Content/spammy, Reputation/IP, Authentication (SPF/DKIM/DMARC), Bounces/list hygiene, Suppression/complaints. "CRABS crawl into your inbox placement."
π Skeletons to memorize
1. Dedup query (keep newest row per SubscriberKey)
SELECT SubscriberKey, EmailAddress, AdvisorID, ModifiedDate
FROM Lead_Staging
QUALIFY ROW_NUMBER() OVER (
PARTITION BY SubscriberKey
ORDER BY ModifiedDate DESC
) = 1
π Line by line:
- SELECT ... β the columns you want in the clean target DE.
- FROM Lead_Staging β the raw/duplicated source DE.
- QUALIFY ROW_NUMBER() OVER (...) β SFMC SQL supports QUALIFY; it filters on a window function without a sub-query.
- PARTITION BY SubscriberKey β restart the count for each unique person.
- ORDER BY ModifiedDate DESC β newest record gets number 1.
- = 1 β keep only the freshest row per person; drop the dupes.
- (Fallback if QUALIFY is blocked in your stack: wrap it as a sub-query and WHERE rn = 1.)
2. Fire a journey via API (entry event)
POST https://YOURSUBDOMAIN.rest.marketingcloudapis.com/interaction/v1/events
Authorization: Bearer <OAuth access_token>
Content-Type: application/json; charset=UTF-8
{
"ContactKey": "ADV-10293",
"EventDefinitionKey": "APIEvent-advisor-onboard",
"Data": { "AdvisorID": "10293", "Tier": "Platinum" }
}
π Line by line:
- POST /interaction/v1/events β the Journey Builder "fire entry event" REST endpoint.
- Authorization: Bearer β token from /v2/token (Server-to-Server installed package).
- Content-Type ... charset=UTF-8 β required when payload has non-ASCII (names/accents).
- ContactKey β the subscriber being injected; must match the journey's contact model.
- EventDefinitionKey β copied from the journey's API Event entry source config (NOT the journey name).
- Data{} β must match the journey's entry-source data schema attributes exactly, or the contact won't enter.
- Success = HTTP 201 with an eventInstanceId; 400 = bad key or inactive contact.
3. AMPscript "never blank" personalization guard
%%[ VAR @fname
SET @fname = AttributeValue("FirstName")
IF Empty(@fname) THEN SET @fname = "Valued Client" ENDIF
]%%
Dear %%=v(@fname)=%%,
π Line by line:
- VAR @fname β declare the variable first (undeclared = silent blank).
- AttributeValue("FirstName") β pulls from the sendable DE / subscriber attribute by exact name.
- IF Empty(@fname) β catches NULL and empty string.
- SET ... "Valued Client" β compliant fallback; never ship "Dear ,".
- %%=v(@fname)=%% β v() outputs the variable in the email body.
π οΈ In practice (what you would actually click / do)
This is the section that fixes your interview. For each, say the click-path out loud.
A. Build + send a campaign (the full BAT-VS-D)
- Build: Email Studio > Content Builder > Create > Email > pick template > drop AMPscript/dynamic blocks.
- Audience: target a sendable Data Extension (has SubscriberKey relationship). For FS, apply a suppression/exclusion DE (opt-outs, do-not-contact, compliance holds).
- Test: Preview & Test tab > load a test subscriber row > check personalization renders > Send Test to seed list.
- Validate: check links, subject/preheader, AMPscript errors, and Validate during send setup.
- Send / schedule: Send flow > select DE + suppression > schedule or send. For repeatable: build in Automation Studio as a Send Email activity.
- Deliverability check: after send, Tracking tab > Sent/Delivered/Bounce/Open/Click; investigate any bounce spike.
B. Write + run a dedup query
- Automation Studio > Activities > SQL Query > paste the QUALIFY skeleton.
- Target DE = clean DE; Update or Overwrite action.
- Run Once to validate, then check target DE row count vs source β confirm dupes dropped.
- Drop the Query activity into an Automation so it runs on schedule before the send.
C. Debug blank personalization (throw DARTS)
- Reproduce in Content Builder > Preview & Test with the failing subscriber.
- Data: query the sendable DE β is the value actually populated for that SubscriberKey?
- Attribute: is the AMPscript field name spelled/cased exactly as the DE column?
- Relationship: is it a sendable DE with the right subscriber relationship?
- Typo:
%%FirstName%%vs%%=v(@FirstName)=%%β declared variable? - SubscriberKey: does send context's key match the data row's key? Add an
Empty()fallback so it never ships blank again.
D. Fire a journey via API
- Journey Builder > journey > entry source = API Event > copy the Event Definition Key.
- Make sure an installed package (Server-to-Server) gives Journeys API scope; get token from
/v2/token. - POST the payload (skeleton #2). Confirm 201, then in the journey watch the entry count tick up / check the contact in Journey History.
E. Set up an A/B test
- Content Builder send / Email Studio > A/B Test > choose variable: Subject Line, Content, From Name, or Send Time.
- Set test % split (e.g., 10%/10%), pick winner metric (Open or Click), set wait duration, then auto-send winner to remaining 80%.
- Validate both treatments preview correctly; confirm same suppression applies to both.
F. Create a sendable DE + send relationship
- Email Studio > Subscribers > Data Extensions > Create (or from a template).
- Tick Is Sendable; map the DE field that holds the address, and set Sendable Relationship: DE field β Subscriber Key (Subscribers on Subscriber Key).
- Add a Primary Key (usually SubscriberKey) and an EmailAddress field. Now it appears as a send target.
G. Troubleshoot a failed automation
- Automation Studio > Activities/automation > open the run history / Activity > read the error message.
- Common: SQL syntax/timeout, file-drop file not arrived, DE field length, locked DE.
- Fix the activity, Run Once to confirm green, then re-enable schedule. Log RCA on the INC ticket.
H. RCA a deliverability drop (CRABS)
- Pull Tracking + reputation: Open Rate / Bounce / Complaint trend.
- Content (spam words/image-heavy), Reputation (IP/domain), Auth (SPF/DKIM/DMARC failing), Bounces (bad list hygiene), Suppression/complaints rising.
- Use Email Studio > Bounce Mail Management + Deliverability tools; check sender authentication (SAP). Document 5W+Fix+Prevent.
I. Build an advisor Distributed Marketing send
- Distributed Marketing (managed package in the CRM, e.g., Financial Services Cloud) β needs Journey Builder + an FSC/Sales/Service license.
- Marketer builds + approves a campaign in SFMC; surfaces it as a DM campaign on the CRM record (e.g., a Financial Account / Client).
- Advisor opens the client record > Quick Send (one email, personalized) or adds the client to a Journey > advisor personalizes within brand guardrails > sends.
- The advisor never logs into SFMC; data + branding stay centrally controlled (compliance win).
π€ Rapid-fire
-
Q: How do you make sure a personalization token never renders blank? A: Declare a VAR, pull with AttributeValue, wrap in
IF Empty() THEN fallback. β¦and in practice: I reproduce it in Content Builder Preview & Test with the failing SubscriberKey before shipping the fix. -
Q: Dedup a DE? A:
ROW_NUMBER() OVER (PARTITION BY key ORDER BY date DESC) = 1. β¦and in practice: SQL Query activity > target a clean DE > Run Once > compare row counts. -
Q: How does an external system push someone into a journey? A: POST to
/interaction/v1/eventswith ContactKey + EventDefinitionKey. β¦and in practice: I copy the Event Definition Key off the API Event entry source and confirm a 201 + rising entry count. -
Q: A/B test what and how? A: Subject, content, from-name or send-time; split %, winner metric, wait, auto-send winner. β¦and in practice: Email Studio A/B Test wizard, 10/10 split, winner by open rate.
-
Q: What makes a DE sendable? A: Is-Sendable flag + a send relationship mapping its key to Subscriber Key. β¦and in practice: Data Extensions > Create > tick Is Sendable > map field β Subscriber Key.
-
Q: Automation failed overnight β first move? A: Open run history, read the activity error, fix, Run Once, re-enable, log RCA. β¦and in practice: I check the failing step's error text first β usually SQL timeout or a file-drop that didn't land.
-
Q: Open rate dropped 40% β RCA? A: CRABS β Content, Reputation, Auth, Bounces, Suppression/complaints. β¦and in practice: Tracking trend + Bounce Mail Management + verify SPF/DKIM/DMARC, then write 5W+Fix+Prevent.
-
Q: How do advisors send without SFMC access? A: Distributed Marketing β marketer approves, advisor Quick Sends or adds to a Journey from the CRM record. β¦and in practice: managed package on the FSC client record; advisor personalizes inside brand guardrails, never logs into SFMC.
β οΈ Gotchas / RCA hooks
- Blank fields: undeclared variable or a non-sendable DE β always Preview with the real failing row, never a happy-path one.
- Journey API 400, not 201: wrong EventDefinitionKey (people use the journey name) or contact inactive / data schema mismatch β re-copy the key, match the entry-source attributes exactly.
- Dedup keeps the wrong row:
ORDER BYdirection wrong, or NULL dates sort last β coalesce/handle NULLs, confirm DESC = newest. - A/B winner never sends: wait window too short or remaining-audience setting off β check winner criteria + holdout config.
- Automation "succeeded" but no emails: SQL ran but matched 0 rows, or wrong target DE β always check row counts, not just the green check.
- Deliverability drop blamed on content but it's auth: check SPF/DKIM/DMARC + IP reputation before rewriting copy.
- FS compliance trap: forgot the suppression/exclusion DE β opt-outs or do-not-contact get mailed. Every send answer: "...applied against the suppression DE."
- Interview pacing trap (the real LTM gap): you over-explain theory and run out of time. Cap theory at one sentence; spend the rest on the click-path. Practice on a 90s timer.
β±οΈ Timed practical mock (set a 20-min timer β 90s/answer)
Read the Q, speak the answer aloud, then peek at the model. Score yourself with the rubric.
- Walk me through building and sending a campaign end to end. β BAT-VS-D: Content Builder build > sendable DE + suppression > Preview & Test seed > Validate > schedule/Automation > Tracking check.
- Write me a query that removes duplicate subscribers. β
ROW_NUMBER() PARTITION BY SubscriberKey ORDER BY ModifiedDate DESC = 1; run as SQL Query activity, compare row counts. - A token is rendering blank in production β debug it live. β DARTS; reproduce in Preview with the failing key; add
IF Empty() THEN fallback. - An external app needs to drop advisors into an onboarding journey. β POST
/interaction/v1/events, ContactKey + EventDefinitionKey + Data schema; confirm 201 + entry count. - Set up an A/B subject-line test. β A/B wizard, 10/10 split, winner = open rate, wait window, auto-send winner to 80%.
- Create a sendable DE for a new advisor list. β Data Extensions > Create > Is Sendable > map address field + Subscriber Key relationship.
- A nightly automation failed β what do you do? β Open run history, read the failing activity's error, fix, Run Once green, re-enable, log RCA on the INC.
- Open rates dropped sharply this week β run the RCA. β CRABS; Tracking trend + Bounce Mail Management + check SPF/DKIM/DMARC; write 5W+Fix+Prevent.
- How do you let financial advisors send branded emails without SFMC logins? β Distributed Marketing on the FSC record; marketer approves, advisor Quick Send or add-to-Journey within guardrails.
- A send went out with a wrong personalization β what's your INC + RCA response? β Acknowledge under SLA, identify scope (which SubscriberKeys), root cause (data/attribute/relationship), corrective send if needed, document Fix + Prevent (add Empty() guard + Preview-with-failing-row step).
- How do you validate a campaign before deployment? β Preview & Test with real rows, Send Test to seed, Validate in send flow, confirm suppression + links + AMPscript, dual approval for FS.
- Show me how you'd schedule a recurring data load + send. β Automation Studio: File Drop/SFTP import > SQL dedup Query > Send Email activity, scheduled; monitor run history.
π Scoring rubric (per answer, out of 3):
| Score | What it sounds like |
|---|---|
| 0 | Definition only / "it depends" β no clicks |
| 1 | Right concept, vague on where/how |
| 2 | Names the exact Studio + screen + steps |
| 3 | Steps + a verify step + a compliance/suppression mention |
- Target: average 2.5+. Anything scoring β€1 = you slipped back into theory β redo it leading with "...and the way I'd actually do it is β".
β‘οΈ Next: (final β the morning of the interview, re-read C13 Memory Vault, then breathe. You've got this, Akash! π)
β Marked for Review
Sections you flagged with the β Mark button in the bar above (or the M key) while studying. Click any item to jump straight back to it. This list is saved in your browser and updates automatically.