How to AMPScript: Salesforce Marketing Cloud
To effectively leverage any advanced marketing automation platform, understanding its personalization language is essential. In Salesforce Marketing Cloud, AMPScript serves as the go-to language for email personalization and as a backend tool for cloud pages. This scripting language allows marketers to create dynamic, personalized content, making your campaigns more engaging and effective.
What is AMPScript?
AMPScript is a proprietary scripting language developed by Salesforce for Marketing Cloud. It allows marketers to personalize and manipulate email content dynamically. With AMPScript, you can pull data from data extensions, personalize emails, and create complex conditional logic within your messages.
Basic Syntax
Before diving into examples, let’s cover some fundamental syntax rules.
Case insensitive
I do not know if it’s a good thing, but AMPScript is case insensitive. A good practice is to use any programming language naming convention of your choice (camel case, snake case, Pascal case, etc.).
My personal best practice is to use:
- uppercase letters with conditions.loops and variable declaration and definition e.g. IF ELSEIF ENDIF FOR DO NEXT, SET, VAR, NOT etc.
- Pascal case for all AMPScript functions Lookup, LookupRows, ClaimRow, etc.
- camel case for any variables
- lowercase for personalization strings
%%[ /* Camel Case */ SET @firstName = "John" /* Variable using camel case */ /* Pascal Case */ SET @FirstName = "Jane" /* Variable using Pascal case */ /* Snake Case */ SET @first_name = "Alice" /* Variable using snake case */ /* Kebab Case (Not typically used in AMPScript, but shown for reference) */ /* SET @first-name = "Bob" */ /* This would not work in AMPScript, as dashes are not allowed in variable names */ /* Upper Snake Case (for constants) */ SET @FIRST_NAME = "Charlie" /* Variable using upper snake case */ /* Hungarian Notation */ SET @strFirstName = "Dave" /* Variable using Hungarian notation */ ]%%
Choose one and stick with it for the entirety of the script, or establish a project-wide naming convention.
%%[ SET @firstName = Lookup("Subscribers", "FirstName", "SubscriberKey", _subscriberkey) SET @fiRstNAme = LOOKUP("Subscribers", "FirstName", "SubscriberKey", _subscriberkey) /* you can bring some of the mocking meme style to the business world you can */ SET @firstname = LoOKuP("Subscribers", "FirstName", "SubscriberKey", _subscriberkey) ]%% %%=v(@FIRSTNAME)=%%
AMPScript block
AMPScript block, is used for more complex scripting needs. It’s enclosed within %%[
and ]%%
delimiters and is typically placed at the beginning of your email or in a designated section. This format allows you to execute multiple lines of AMPScript code, including setting variables, performing lookups, and creating conditional logic.
%%[ SET @firstName = Lookup("Subscribers", "FirstName", "SubscriberKey", _subscriberkey) SET @lastName = Lookup("Subscribers", "LastName", "SubscriberKey", _subscriberkey) SET @fullName = Concat(@firstName, " ", @lastName) ]%%
Inline AMPScript
Inline AMPScript is used for embedding AMPScript directly within the HTML content of your emails or cloud pages. It’s enclosed within %%=
and =%%
delimiters and is typically used for simple expressions and variable outputs. Inline AMPScript is ideal for quick, single-line statements or inserting dynamic content directly into the email body.
Certain functions (iif, indexof) or double quotes within inline AMPScript used within anchor tag (ahref) can break the email text version and thus prevent you from sending any email and giving you headaches.
Variables
Variables in AMPScript must start with (@), which is the only condition. This means you can begin your variable name with a number. However, avoid using characters like /, !, and @ after the initial @ symbol, as they are not allowed.
Initialize variables
This can be done, but it is not a requirement and won’t cause any harm if you skip the initialization entirely. The only scenario that comes to mind where initialization might be beneficial is when you are setting your variables within conditional blocks.
%%[ VAR @name,@surname,@ahoy ]%%
Define variables
Defining or setting variables is done with the keyword SET
and cannot be done otherwise in AMPscript.
%%[ SET @name = "John Doe" ]%%
Assign variables from data extension
You might say that assigning personalization variables from the data extension is as easy as simply using the assignment operator ‘=’. However, this can sometimes lead to personalization errors. Let’s take a look at the following example.
%%[ SET @firstname = firstname IF Empty(@firstname) THEN /*do something*/ ENDIF ]%%
When the firstname column is not defined in the data extension, the email will result in a personalization error because we are referencing a non-existent variable. A safe way to achieve email personalization without causing an error is to use the AttributeValue()
function. With this function, the same example will render without error.
%%[ SET @firstname = AttributeValue('firstname') IF Empty(@firstname) THEN /*do something*/ ENDIF ]%%
Arithmetic Operations
Perform arithmetic operations to manipulate numeric values.
%%[ SET @a = 10 SET @b = 5 SET @sum = Add(@a, @b) /* Addition */ SET @difference = Subtract(@a, @b) /* Subtraction */ SET @product = Multiply(@a, @b) /* Multiplication */ SET @quotient = Divide(@a, @b) /* Division */ ]%%
Comparators
Basic comparators
%%[ IF @a == @b THEN SET @result = "Equal" ELSEIF @a > @b THEN SET @result = "Greater" ELSE SET @result = "Lesser" ENDIF ]%%
NOT operator
Negate a condition using NOT
operator.
%%[ SET @isActive = "true" IF NOT @isActive == "false" THEN SET @status = "Active" ELSE SET @status = "Inactive" ENDIF ]%%
Empty() Function
Check if a value is empty using EMPTY
.
%%[ SET @firstName = Lookup("Subscribers", "FirstName", "SubscriberKey", _subscriberkey) IF Empty(@firstName) THEN SET @greeting = "Hello, valued subscriber!" ELSE SET @greeting = Concat("Hello, ", @firstName, "!") ENDIF ]%%
IndexOf() Function
Find the position of a substring within a string using INDEXOF
.
%%[ SET @email = "john.doe@example.com" SET @atPosition = IndexOf(@email, "@") IF @atPosition > 0 THEN SET @domain = Substring(@email, Add(@atPosition, 1), Length(@email)) ELSE SET @domain = "Invalid email address" ENDIF ]%%
Examples
Personalized Greeting
Personalizing email content is a powerful way to engage subscribers and enhance their experience. A common personalization technique is to greet subscribers by their first name. However, sometimes the first name may not be available in the data. In this example, we will use AMPScript to dynamically generate a personalized greeting. We will check if the subscriber’s first name is available and use it if present; otherwise, we will use a generic greeting. This ensures that each subscriber receives a tailored message, whether their name is known or not. Let’s explore the code to see how this can be achieved effectively.
%%[ SET @firstName = Lookup("Subscribers", "FirstName", "SubscriberKey", _subscriberkey) ]%% %%[ IF NOT EMPTY(@firstName) THEN ]%% Hello, %%=v(@firstName)=%%! %%[ ELSE ]%% Hello, valued subscriber! %%[ ENDIF ]%%
Adding query parameters to existing link dynamically
When working with email marketing campaigns, adding UTM parameters to your URLs is crucial for tracking the performance of your links. However, it can be challenging to dynamically add these parameters, especially when you are unsure if the original URL already contains query parameters. In this example, we will use AMPScript’s INDEXOF
function to check for existing query parameters in a URL and appropriately append UTM parameters. This ensures that your links are correctly formatted for tracking, regardless of their initial state. Let’s dive into the code to see how this can be done efficiently.
%%[ SET @link = "https://example.com/page" SET @utmParameters = "utm_source=newsletter&utm_medium=email&utm_campaign=spring_sale" SET @queryIndex = IndexOf(@link, "?") IF @queryIndex > 0 THEN /* If there is already a query parameter, add UTM parameters with & */ SET @finalLink = Concat(@link, "&", @utmParameters) ELSE /* If there are no query parameters, add UTM parameters with ? */ SET @finalLink = Concat(@link, "?", @utmParameters) ENDIF ]%% <a href="%%=RedirectTo(@finalLink)=%%">Click here</a>
Explanation:
- Define the Variables:
@link
: The original URL.@utmParameters
: The UTM parameters you want to add.@queryIndex
: The position of the?
character in the URL.
- Check for Existing Query Parameters:
- Use
IndexOf(@link, "?")
to find the position of the?
character. - If
@queryIndex
is greater than 0, it means the URL already has query parameters.
- Use
- Add UTM Parameters:
- If the URL has query parameters (
@queryIndex > 0
), concatenate the UTM parameters with&
. - If the URL does not have query parameters (
@queryIndex == 0
), concatenate the UTM parameters with?
.
- If the URL has query parameters (
- Output the Final Link:
- Use
RedirectTo(@finalLink)
to create the final clickable link with the correct UTM parameters.
- Use
Cloud page form submission using @@ExecCt
Handling form submissions on Cloud Pages in Salesforce Marketing Cloud is a common task for collecting and processing user data. While Server-Side JavaScript (SSJS) offers a way to get the request method, AMPScript can also be used effectively by utilizing the @@ExecCtx
variable to determine the execution context. This approach helps in distinguishing between form submissions (POST requests) and page loads (LOAD requests), ensuring proper handling of user inputs. Using this method is a good practice as it enhances security, improves data processing, and provides clear user feedback. Let’s explore an example to see how this can be done using AMPScript.
%%[ /* Check the execution context: LOAD or POST */ IF @@ExecCtx == "POST" THEN /* Retrieve form data */ SET @firstName = RequestParameter("firstName") SET @email = RequestParameter("email") /* Perform your processing here, such as storing data in a data extension */ IsertDE("FormSubmissions", "FirstName", @firstName, "Email", @email) /* Set a thank-you message */ SET @message = Concat("Thank you for your submission, ", @firstName, "!") ELSE /* Prompt the user to fill out the form */ SET @message = "Please fill out the form." ENDIF ]%% %%=v(@message)=%% <form action="%%=RequestParameter('PAGEURL')=%%" method="post"> <label for="firstName">First Name:</label> <input type="text" id="firstName" name="firstName" required> <label for="email">Email:</label> <input type="email" id="email" name="email" required> <input type="submit" value="Submit"> </form>
For loops
A FOR
loop in AMPScript allows you to execute a block of code repeatedly for a specified number of times. This is useful when you need to process or display multiple pieces of data. The basic structure of a FOR
loop involves initializing a counter, setting the loop’s starting and ending conditions, and defining the actions to be taken on each iteration.
Syntax
FOR @counter = start TO end DO /* Code to be executed in each iteration */ NEXT @counter
@counter
: The loop counter variable.start
: The initial value of the counter.end
: The final value of the counter.
Example
%%[ FOR @i = 1 TO 5 DO Output(Concat("Iteration: ", @i, "<br>")) NEXT @i ]%%
Peronalization strings
Personalization strings in Salesforce Marketing Cloud are placeholders that dynamically populate specific information about the subscriber, email, or context in which the message is being rendered. These strings allow marketers to tailor content to individual recipients.
emailname_
Name of the email
%%=emailname_=%%
_subscriberkey
The contact subscriber key is available when landing on a cloud page from an email communication. Links to the landing page must be created with the CloudPagesURL()
function in combination with RedirectTo()
.
emailaddr
Subscribers email address.
%%=v(@emailaddr)=%%
_IsTestSend
Evaluates to True if the email job is designated as a Test Send. I use this to add labels to multivariant proofs.
%%[ IF _isTestSend == false THEN ... // this code doesn’t run for test sends ENDIF ]%%
Common Functions
Lookup
Retrieve a value from a data extension. This function is used for quick lookups based on criteria when you only need to retrieve a single column value. To get the entire row, other lookup functions such as LookupRows
must be used.
Syntax
SET @value = Lookup("DataExtensionName", "ColumnName", "LookupColumn1", "LookupValue1" [, "LookupColumn2", "LookupValue2", ...])
Example
%%[ SET @value = Lookup("DataExtensionName", "ColumnName", "LookupColumn", "LookupValue") ]%%
Lookuprows
Use to retrieve multiple rows based on criteria and loop through the results for further processing.
Syntax
SET @rows = LookupRows("DataExtensionName", "LookupColumn1", "LookupValue1" [, "LookupColumn2", "LookupValue2", ...])
Example
%%[ /* Retrieve rows from the Products data extension where ProductCategory is "Electronics" */ SET @productRows = LookupRows("Products", "ProductCategory", "Electronics") /* Get the number of rows returned */ SET @rowCount = RowCount(@productRows) /* Initialize counter */ SET @counter = 1 /* Loop through each row */ IF @rowCount > 0 THEN FOR @i = 1 TO @rowCount DO /* Get the current row */ SET @row = Row(@productRows, @i) /* Retrieve column values from the current row */ SET @productID = Field(@row, "ProductID") SET @productName = Field(@row, "ProductName") SET @productPrice = Field(@row, "ProductPrice") /* Output the product details */ Output(Concat("<p>Product ID: ", @productID, "<br>")) Output(Concat("Product Name: ", @productName, "<br>")) Output(Concat("Product Price: $", @productPrice, "</p>")) NEXT @i ELSE Output(v("<p>No products found in the Electronics category.</p>")) ENDIF ]%%
Have you noticed something with the Output function? It can only output a value if it is returned from a nested function. If you reference a variable directly, nothing will be printed. To properly display a variable’s value with the Output function, you need to use functions like v() or Concat().
TreatAsContent
The TreatAsContent function in AMPScript is used to render a string as content, allowing the string to be processed as if it were part of the email or landing page content. This is useful when you need to dynamically generate or include content that should be treated as HTML or AMPscript.
Syntax
TreatAsContent(string)
- string – string to evaluate
When using the TreatAsContent
function in AMPScript, it’s important to note that any links defined within the content will not be tracked automatically. To enable link tracking, you need to prepend httpgetwrap|
before the protocol (e.g., httpgetwrap|https://
). Additionally, only the first 100 links defined with TreatAsContent
can be tracked. This function is typically used in dynamic content blocks or when rendering modules that contain HTML or links, allowing for more flexible and dynamic content management in your emails and landing pages.
Before this feature had to be enabled by support for your business unit but now it is enabled by default.
ClaimRow
The ClaimRow
function in AMPScript is used to claim or reserve a row in a data extension. This function is particularly useful in scenarios where you need to assign unique values, such as vouchers or promo codes, to users. By claiming a row, you ensure that the same voucher or promo code is not assigned to multiple users.
Syntax
ClaimRow("DataExtensionName", "ClaimColumn", "ClaimValue")
DataExtensionName
: The name of the data extension from which you want to claim a row.ClaimColumn
: The column used to mark the row as claimed.ClaimValue
: The value that signifies a row has been claimed (typically a unique identifier for the user).
Example: How to assign a voucher
This example demonstrates how to use ClaimRow
to assign a voucher to a user. If no voucher is available, it uses the RaiseError
function to handle the fallback scenario.
Data Extension Setup
Assume we have a data extension named Vouchers
with the following columns:
VoucherCode
(Primary Key)IsClaimed
(Boolean indicating if the voucher is claimed) default is set to false- EmailAddress (The email of the user who claimed the voucher)
Claim Coupon Code Example
%%[ /* Attempt to claim a voucher */ SET @voucherRow = ClaimRow("Vouchers", "IsClaimed", "EmailAddress", emailAddr) /* Check if a voucher was successfully claimed */ IF RowCount(@voucherRow) > 0 THEN /* Retrieve the voucher code */ SET @voucherCode = Field(@voucherRow, "VoucherCode") /* Output the voucher code */ Output(Concat("Your voucher code is: ", @voucherCode)) ELSE /* No vouchers available, handle the fallback */ RaiseError("No vouchers available at the moment. Please try again later.", true) ENDIF ]%%
RequestParameter
The RequestParameter
function in AMPScript is used to retrieve data submitted via form inputs as well as query parameters from the URL. This function is essential for handling user input and dynamically personalizing content based on parameters passed to the landing page.
Syntax
RequestParameter("parameterName")
Example
%%[ SET parameterName = RequestParameter("parameterName") ]%%