background shape
background shape
Getting Started with AMPScript in Salesforce Marketing Cloud

Getting Started with AMPScript in 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)

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 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*/

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*/

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 */


Basic comparators

    IF @a == @b THEN
        SET @result = "Equal"
    ELSEIF @a > @b THEN
        SET @result = "Greater"
        SET @result = "Lesser"

NOT operator

Negate a condition using NOT operator.

    SET @isActive = "true"
    IF NOT @isActive == "false" THEN
        SET @status = "Active"
        SET @status = "Inactive"

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!"
        SET @greeting = Concat("Hello, ", @firstName, "!")

IndexOf() Function

Find the position of a substring within a string using INDEXOF.

    SET @email = ""
    SET @atPosition = IndexOf(@email, "@")
    IF @atPosition > 0 THEN
        SET @domain = Substring(@email, Add(@atPosition, 1), Length(@email))
        SET @domain = "Invalid email address"


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 = ""
    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)
        /* If there are no query parameters, add UTM parameters with ? */
        SET @finalLink = Concat(@link, "?", @utmParameters)

<a href="%%=RedirectTo(@finalLink)=%%">Click here</a>


  1. Define the Variables:
    • @link: The original URL.
    • @utmParameters: The UTM parameters you want to add.
    • @queryIndex: The position of the ? character in the URL.
  2. 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.
  3. 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 ?.
  4. Output the Final Link:
    • Use RedirectTo(@finalLink) to create the final clickable link with the correct UTM parameters.

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, "!")
        /* Prompt the user to fill out the form */
        SET @message = "Please fill out the form."
<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">

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.


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.


    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.


Name of the email



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().


Subscribers email address.



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

Common Functions


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.


SET @value = Lookup("DataExtensionName", "ColumnName", "LookupColumn1", "LookupValue1" [, "LookupColumn2", "LookupValue2", ...])


%%[ SET @value = Lookup("DataExtensionName", "ColumnName", "LookupColumn", "LookupValue") ]%%


Use to retrieve multiple rows based on criteria and loop through the results for further processing.


SET @rows = LookupRows("DataExtensionName", "LookupColumn1", "LookupValue1" [, "LookupColumn2", "LookupValue2", ...])


    /* 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
        Output(v("<p>No products found in the Electronics category.</p>"))

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().


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.


  • 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.


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.


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))
        /* No vouchers available, handle the fallback */
        RaiseError("No vouchers available at the moment. Please try again later.", true)


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.




SET parameterName = RequestParameter("parameterName")

Oh hi there đź‘‹
I have a FREE e-book for you.

Sign up now to get an in-depth analysis of Adobe and Salesforce Marketing Clouds!

We don’t spam! Read our privacy policy for more info.

Share With Others

MarTech consultant

Marcel Szimonisz

Marcel Szimonisz

I specialize in solving problems, automating processes, and driving innovation through major marketing automation platforms.

Buy me a coffee