DEV Community

Cover image for AMPscript Patterns: Lookups, Conditionals, and Safe Fallbacks
SapotaCorp
SapotaCorp

Posted on • Originally published at sapotacorp.vn

AMPscript Patterns: Lookups, Conditionals, and Safe Fallbacks

Personalization Strings cover the simple cases. AMPscript is what you reach for when the email needs to do more than inject a single value.

Three patterns we use on almost every production engagement:

  1. Looking up values from a non-sendable Data Extension
  2. Tiered conditional content based on subscriber state
  3. Formatting dates and numbers for display

The AMPscript block is wrapped in %%[ ... ]%%. Output of a variable comes from %%=v(@varName)=%%.

Pattern 1: Lookup across Data Extensions

The sendable DE usually doesn't hold every attribute the email needs. A common case: the email sends from each subscriber's assigned Sales Rep, but the rep's name, email, and phone live in a separate SalesRep_DE, not duplicated into the sendable.

Customer_DE (sendable):
  - CustomerID     <- Subscriber Key
  - EmailAddress
  - SalesRepID     <- just an ID

SalesRep_DE (non-sendable):
  - SalesRepID     <- Primary Key
  - RepName
  - RepEmail
  - RepPhone
Enter fullscreen mode Exit fullscreen mode

Fetch the rep data at send time with Lookup():

%%[
VAR @repID, @repName, @repEmail, @repPhone

SET @repID    = AttributeValue("SalesRepID")
SET @repName  = Lookup("SalesRep_DE", "RepName",  "SalesRepID", @repID)
SET @repEmail = Lookup("SalesRep_DE", "RepEmail", "SalesRepID", @repID)
SET @repPhone = Lookup("SalesRep_DE", "RepPhone", "SalesRepID", @repID)

/* Always handle the not-found case */
IF EMPTY(@repName) THEN
  SET @repName  = "Customer Care Team"
  SET @repEmail = "support@company.com"
  SET @repPhone = "1800 xxxx"
ENDIF
]%%

<p>Your account manager:</p>
<p><strong>%%=v(@repName)=%%</strong></p>
<p>%%=v(@repEmail)=%% | %%=v(@repPhone)=%%</p>
Enter fullscreen mode Exit fullscreen mode

Lookup syntax:

Lookup("TableName", "FieldToReturn", "FieldToMatch", ValueToMatch)
Enter fullscreen mode Exit fullscreen mode

The pair that gets swapped constantly is positions 2 and 3 - FieldToReturn and FieldToMatch. Order wrong = Lookup silently returns empty. No error, just blank output.

/* wrong - argument positions swapped */
SET @repName = Lookup("SalesRep_DE", "SalesRepID", "RepName", @repID)

/* right */
SET @repName = Lookup("SalesRep_DE", "RepName", "SalesRepID", @repID)
Enter fullscreen mode Exit fullscreen mode

Pattern 2: Tiered conditional content

Loyalty emails routinely say different things depending on the subscriber's current state:

%%[
VAR @points, @message, @pointsLeft

SET @points = AttributeValue("LoyaltyPoints")

IF @points >= 1000 THEN
  SET @message    = "You've reached GOLD tier!"
  SET @pointsLeft = 0
ELSEIF @points >= 500 THEN
  SET @message    = "You're at SILVER tier"
  SET @pointsLeft = Subtract(1000, @points)
ELSE
  SET @message    = "You're at STANDARD tier"
  SET @pointsLeft = Subtract(500, @points)
ENDIF
]%%

<p>%%=v(@message)=%%</p>
%%[IF @pointsLeft > 0 THEN]%%
  <p>Earn <strong>%%=v(@pointsLeft)=%%</strong> more points to reach the next tier!</p>
%%[ENDIF]%%
Enter fullscreen mode Exit fullscreen mode

Two scripting blocks here: the top one sets variables, the inline IF decides whether to render a paragraph at all.

When conditional content is structural (show or hide whole blocks of HTML), either AMPscript inline IF or a Dynamic Content Block works. Dynamic Content is nicer for non-developers to maintain; AMPscript is nicer when logic is complex or needs lookups.

Pattern 3: Formatting values for display

Raw data rarely matches how humans read it. 1500000 in a DE should display as 1,500,000 VND in the email. 2024-01-15 should display as 15/01/2024.

%%[
VAR @today, @amount, @formattedAmount

SET @today = Format(Now(), "dd/MM/yyyy")
SET @amount = AttributeValue("OrderAmount")
SET @formattedAmount = Format(@amount, "N0")
]%%

Order date: %%=v(@today)=%%
Amount: %%=v(@formattedAmount)=%% VND
Enter fullscreen mode Exit fullscreen mode

Format(value, "N0") = number with thousands separators, no decimals. Format(date, "dd/MM/yyyy") = day/month/year. Now() = current send time.

Other useful format strings:

  • "yyyy-MM-dd" for ISO dates
  • "hh:mm" for 12-hour time
  • "HH:mm" for 24-hour time
  • "C" for currency (locale-aware, use cautiously in international sends)

The three mistakes we still see

Mistake 1: No EMPTY() check after Lookup

Lookup returns empty when the match fails. Without an explicit fallback, the email just shows nothing where the data should be. Always:

SET @rep = Lookup("SalesRep_DE", "RepName", "SalesRepID", @repID)
IF EMPTY(@rep) THEN
  SET @rep = "Customer Care Team"
ENDIF
Enter fullscreen mode Exit fullscreen mode

Mistake 2: Unclosed AMPscript blocks

Forgetting to close %%[ breaks rendering on the whole email. Test in Preview & Test immediately after writing AMPscript - if the Preview shows error text, the syntax is wrong and the email won't send.

Mistake 3: AMPscript in the Subject Line

Same rule as Personalization Strings: Subject Line does not render AMPscript. Move the logic upstream, pre-compute a field in the DE, and use a plain Personalization String in the subject.

Takeaway

AMPscript earns its place in the project when the email needs cross-DE data, conditional logic, or formatted values. Three patterns cover 90% of the real-world use cases: Lookup with IF EMPTY fallback, IF/ELSEIF/ELSE for tiers, and Format() for numbers and dates. Preview & Test with multiple data profiles catches both logic bugs and syntax errors before they go to the full list.


Writing AMPscript for a production SFMC build? Our Salesforce team reviews and ships complex AMPscript on Marketing Cloud engagements. Get in touch ->

See our full platform services for the stack we cover.

Top comments (0)