Upping your Token Game: Getting Started with Velocity Script

Chris_Wilcox
Level 9
Level 9

I cannot express the number of times I’ve spoken with other Marketo users who are interested in getting started with using Velocity Script tokens, but they have no idea where to start. The truth is, it IS hard to get started, but only because there aren’t a ton of resources that help paint the broad picture for what Velocity is, how it works, and why it might make sense to use. Hopefully this piece can start to fill that gap.

 

Overview

  1. Introduction to Velocity
  2. When to Use Velocity Script Tokens
  3. Tools of the Trade & Best Practices
  4. Creating & Testing Tokens

Introduction to Velocity: What is Velocity Scripting?

Velocity is a coding language built on Java used for scripting content. With it, you can create powerful personalization in your email assets, resulting in more customized experiences for your prospects and customers.

 

As we get started here, I want to state upfront that Velocity can be… a bit of a rabbit hole. But we don’t need to go down it right now. Developers can use Velocity to do some truly incredible things, but in this intro we’re going to focus on some simpler applications of Velocity that marketers can take advantage of to improve their email marketing campaigns.

 

Velocity can access fields on your contact object, and it can also access Opportunity data and Custom Objects, which can all be used to create more advanced logic to power dynamic content in emails. If you’re not familiar with the opportunity object or custom objects, literally ignore this paragraph. Not everyone uses them and you don't need to know anything about them to start using Velocity!

 

In Short: Velocity is a coding language for dynamic content that is more detailed and robust than snippets or traditional dynamic content.

MOST IMPORTANTLY: It’s Not Scary!

 

When to Use Velocity Script Tokens

The biggest question I get asked is WHEN should I consider a script token instead of more traditional snippets or dynamic content.

 

A few easy examples are:

  • You need to reference multiple attributes on a contact record simultaneously. For example: You want to combine a Gender field + Last Name to create a single dynamic Hi [Mr./Ms./Mrs.] Lastname token.
  • Show/Hide content section based on user preferences or other attributes. For example: Show a particular piece of content to customers if they are located in specific region.

For more on scenarios where it might make sense to choose Velocity over other approaches, there's an excellent Master Class piece by @Beth_Massura on Tokens vs. Snippets vs. Dynamic Content in Marketo Community.

 

Personally, I’ve run into so many seemingly relatively simple personalization ideas where building a segmentation and then creating the different versions in a piece of dynamic content just isn’t scalable. You want to combine 3 or 4 attributes into a segmentation, and all of a sudden you'd need to make 80 segments to account for your combinations. In those types of cases, Velocity scripts can be significantly easier to maintain at scale compared to segmentations, snippets, and dynamic content.

 

Tools of the Trade & Best Practices

Where to work? Marketo Editor vs. Offline Editor

Personally, I prefer to work with an offline editor like Notepad++ for a few reasons. Specifically, I like maintain a history of my tokens as I make changes, and I don’t have to live in fear of becoming disconnected from the internet randomly and losing all of my work. Of course you can always use Marketo’s editor, but it’s just personal preference.

  • Marketo editor - Can be finicky, always online, possibility of disconnected from network and no changes saved. Easily access field names/references.
  • Offline Editor (Notepad++) - Able to work offline, keep offline history of past token values, no fear of disconnected network. Negative: need to access Marketo editor for field names.

Marketo Velocity Script EditorMarketo Velocity Script Editor

 

 

You can see in the editor, you have the left pane where you create/edit your code, and your right panel where you can access fields on opportunities, persons, and any custom objects you have connected to Marketo.

 

Personally I use Notepad++ with an updated highlighter that mimics the color coding of the Marketo editor (see the appendix at the bottom for how to set this up, makes my life a lot easier!)

 

Other Tips

 

Maintain an Offline Archive of Tokens

Keep in mind that Marketo does not maintain a history other than the date that a token was updated. I strongly encourage everyone to keep an offline archive of your tokens and try to maintain a history, that way you can always revert back to previous versions of your token if needed!

 

Document Changes to Tokens

With new versions of tokens, keep notes in the offline files documenting what changed in the logic with this new version of the logic. Or, use comments (more on that in a minute) to document changes right in the token logic itself.

 

Where you store tokens in Marketo matters!

Tokens can be stored in a Marketo Activities Folder or an individual Program. Tokens are accessible to all sub-folders and programs below the folder where the token is created, so make sure you’re creating tokens knowing where you intend to use it inside your programs.

02-Token-location.png

 

Tokens intended to be used globally should be placed in the highest level folder of your instance. Some tokens may be program specific, build them into that program.

 

If you modify a token in a child folder, an "override" version of that token is created locally within that child folder and below. This can make things messy and should be avoided where possible!

 

Be Aware of Field Types

One other thing really as an FYI that's a little more advanced – Marketo-only and CRM Fields all get converted to strings when they are used in Velocity. What that means in normal human speak is that if you want to have your script do something like comparing numbers (e.g. greater than, less than, etc.), you have to convert those fields BACK to numeric values in your velocity script before you do the comparison. Honestly, that's another explanation entirely, but something you should be aware of!

 

Creating Tokens

At its core, Velocity scripting is like a big IFTTT (If This Then That) problem. If a record matches a certain set of conditions, do this thing or show this information.

 

Primary Query Operators:

#if – Starts an "If" statement. Works just like excel to check if a record matches your criteria.

#elseif – Allows for multiple #if statements if the record does not qualify for your first set of criteria. 

#if recordtype equals "1", do this thing -> #elseif recordtype equals "2", do this other thing, etc.

#else as default choice for records that do not match any of your if statement criteria.

#end to close the script.  If you forget #end, your email will likely fail to approve or send.

 

Logic Rules:

Once you start your #if statement, you use a few rules operators to write the criteria for the logic rules you are trying to achieve.  Here are some basic rules operators that you can get started using:

 

AND: &&

OR: ||

Equals: $lead.fieldName.equals("value")

Does Not Equal: !$lead.fieldName.equals("value")

Contains: $lead.FieldName.contains("value")

Check if the Field Is Empty: $lead.FieldName.isEmpty()

Check if the Field is Not Empty: !$lead.FieldName.isEmpty()

  

SIDEBAR: Depending on your instance, if you want to use "contains" logic, it may make sense to make the value all lowercase so you don’t get tripped up by a rogue capital letter.  You can do that with: $variable.toLowerCase().contains("value")

 

By combining your query operators with your logic rules, you can write a statement that will have a single or multiple conditions to check for, and then you can define what you’d like to show when someone meets your criteria.  You can combine multiple operators using parenthesis just like advanced Smart List logic in Marketo, so you could say:

 

 

 

 

#if ($lead.fieldNameA.equals("1") && $lead.fieldNameB.equals("2"))

 

 

 

 

and the logic will look for BOTH conditions to be true.

 

If you want to use a True/False (Boolean) field in your logic, that should be coded as a "1" or a "0" for true or false.

 

Please understand that the logic rules of equals, and, or, contains, and isEmpty are only the some basic operators you can use in velocity. You can do extremely advanced searches in text, you can do sorting and ordered lists in your output, you can even build loops that run over and over for each condition that applied to that unique record. For this intro, I really wanted to simply highlight these simpler operators to get people introduced to Velocity.

 

Comments

Lastly, you can add comments or notes right inside your token code by starting a line with ## and Velocity will ignore that line. You’ll see the text turn gray and that won’t show anywhere in the output, but instead just lets you keep some notes right in context of your code so you remember what you did or what is supposed to happen in that section of code.  I like to comment out my logic as much as possible so others can interpret what I am creating without me having to explain it in person.

 

Keep in Mind

People will only qualify for the FIRST #if statement they match. If you need to have outputs for multiple reasons, those are all separate #if statements, not #elseif statements.

 

So ALL that said, this is how you structure your token:

#if statement

                Output for people who meet your if statement rules, can use token values here if you’d like.

#elseif for as many subsequent sets of criteria you have

                Output for next set of criteria

#else

                Default output for everyone who did not meet any of the if statements we created

#end

 

Identifying Field Names For Your Token

Probably the most confusing thing for people to figure out is how do you know what field names to use when you’re writing your logic?  When you create dynamic content or snippets, you’re using your segmentations to pick when to personalize, but here you have to reference the field names themselves.

 

Easiest way: Open the Marketo Token Editor, find the field in the right-side pane, and drag it into the editor. Boom. You have your field name.

Drag in your field to get the field name!Drag in your field to get the field name!

 

 

For your code, you should remove the backets {} around variable names as they are not necessary and clean up your code.

 

Examples

Honestly, I think seeing examples is the easiest way to learn Velocity, so let’s look at a couple.

In this example: We are creating a token to place in the Email From Name field that will show the contact’s Sales Rep Name for clients in Sales Groups 3 or 4 for the West region, and will show our brand name for everyone else.

 

The anatomy of a scriptThe anatomy of a script

You can see where we start our if statement, use our "||" and "&&" operators for our OR and AND rules, and then reference the Sales Owner First/Last name fields. Notice we have the final #else statement where we put the ‘default’ value for anyone who doesn’t qualify for our #if statement. Finally, our #end statement to close the script.

 

Creating & Testing Tokens

Putting your Code into Marketo

After you create your code, navigate to the folder where you want the token to be housed in Marketo, click on the My Tokens tab, and drag an "Email Script" token from the right panel into the pane.

Here's where you create Velocity tokensHere's where you create Velocity tokens

 

Name your token

Click "edit"

Paste your code

 

IMPORTANT: On the right "Integration" pane, you have to check the box next to any field used in your token code!  Otherwise, Marketo will not be able to access that field when running the script.

 

Make sure you check off all of the fields used in your script!Make sure you check off all of the fields used in your script!

 

Testing your Token:

To test your token, you have two options.

  1. Send an email to test leads that meet your conditions (i.e., create test records and update them so that they pass or fail your script rules)
  2. Add real leads into a static list, and preview your email by that list.

Preview your email using your test list.Preview your email using your test list.

 

Unfortunately due to the way test emails in Marketo are generated, you will want to avoid "Test Send" emails to test your velocity tokens. It does some weird things on the back sometimes don't always allow velocity to run correctly, so you'll want to stick with real email sends or previewing your email by your test list.

 

When you're creating or looking for leads in your database for your testing, make sure you're selecting leads that both should and should NOT meet your logic criteria, that way you can double check the logic is working as expected. In addition, make sure to test people where their values are blank for any or all of the fields you’re using in your code.

 

Troubleshooting tokens can be challenging at first, but as you learn Velocity and get more exposure, it will get easier to understand where your logic is failing!

 

Troubleshooting & Other Tips:

When the Marketo Editor first loads, it takes 3-5 seconds for the integration pane to load. Wait until this pane loads to begin editing / updating your token code in the window!

  • Editing too quickly can cause an issue on the backend of Marketo where all integrations get reset behind the scene. Basically, your token stops working.
  • Wait the 3-5 seconds for the right pane to load and begin working, you’ll never have the issue.

Sometimes the "Integrations" pane on the right side of the Marketo editor does not populate with any information ever. Try Hard Refreshing (CTRL+SHIFT+R) your Marketo window to resolve the issue.

 

Closing Out

Ok. That was a lot. A LOT a lot.

 

Here’s your checklist for making a new token:

  1. (Optional) Setup your offline editor, see appendix!
  2. Write out your logic requirements / rules
    • You can do this using psudo (fake) code, or just writing down your rules in sentences. This can help you better understand your desired outputs for when you go to write your code.
  3. Use the Marketo editor to pull the field names you will use in your logic.
  4. Write your logic conditions and if statements using your fields.
  5. Find where you want to create your token in Marketo, add a script token, and open the editor.
  6. Once the integration pane loads, paste your code into the editor window
  7. Check off the boxes next to the fields referenced in your code in the integration pane, save your token.
  8. Identify your test cases and find your test records in your database.
  9. Add your token to a test email and send an email for your test records, or preview by list.

 

Custom Object Considerations

This is pretty technical, but if you DO want to use fields inside custom objects, those fields aren't 100% of the time available to velocity scripting. Custom Object data available to velocity scripting varies based on the Custom Object type (e.g. Marketo vs SFDC vs MSD) and the Custom Object record association (e.g. Contact vs Account related). The following matrices identify what field values are and aren’t available:

Custom object field availabilityCustom object field availability

 

A complex CRM schema can create both positive and negative exceptions to the above with regard to SFDC and MSD. Every schema and CRM are implemented differently, check with you admins to investigate your implementations.  If this whole section is confusing, don't worry about it.  Bottom line is, the best way to really know if something on a custom object is accessible to use in Velocity is to open the editor and try dragging the field in.

 

 

Other Resources:

Honestly, the best resource for you to learn Velocity is the community. You can access any discussions tagged with Velocity here, or use the search to look for keywords closer to your exact scenario. There are countless threads discussing how to create certain tokens, specific logic, testing, etc. Besides that, the official velocity documentation was something I used a lot when I got started, but it’s not exactly thrilling reading (although, was this????), and obviously Google and Github can be resources to help answer a specific question you’re looking to answer. The TEKNKL Blog also has great info on Velocity!

 

BUT WAIT... THERE'S MORE

Can we look at one more quick example?

 

A really common thing I have seem firms use velocity for is showing/hiding a specific piece of content based on a user’s choices. Let’s say you have a lead collection form at your booth at a conference. In that form, you give the user 3 choices to select which topics they are interested in hearing from your organization about. Now, when you send your follow up you want to SHOW the content they selected on the form, and HIDE the things they didn’t select.

 

Doing this with snippets is insane, since you’d need to create a segmentation that accounts for every combination of those 3 choices (1; 1 and 2; 1 and 3; 1 and 2 and 3; etc…). With velocity, you simply write 3 quick tokens, one for each choice, which shows the HTML where that field is true, and shows nothing when it’s false. Pop those 3 tokens into the body of your email, and you’re done.

 

Using Velocity for dynamic content sectionsUsing Velocity for dynamic content sections

 

The Real Closing

 

I know that’s a crazy amount of information. Re-read, start playing, you can do it. It’s really NOT that hard, just takes some time to get your head around. Questions, post a question and tag me @Chris_Wilcox . Follow me, connect, I’m around. I’m sure @SanfordWhiteman will have plenty to say too about your velocity scripts 😁

 

See you in the community! ALRIGHT, I’M OUT

 

 

 

 

 

 

 

-----

Appendix: Notepad++ Setup

  • Install Notepad++
  • Download @Casey_Grimes's Syntax Highlighter from Github
  • Open Notepad++, Navigate to Language > Define your language
  • Click "Import" and select the highlighter xml file
  • Notepad++ will now color code files that end in .vm just like the Marketo editor does!

 

 

After downloading Syntax Highlighter, open Notepad++ and click Define Your LanguageAfter downloading Syntax Highlighter, open Notepad++ and click Define Your Language

 

 

Click Import, grab the xml highlighter file you downloadedClick Import, grab the xml highlighter file you downloaded

 

 

Yay! Pretty markup!Yay! Pretty markup!

 

 

31864
13
13 Comments
Jo_Pitts1
Level 10 - Community Advisor

As an alternative approach to @Chris_Wilcox 's product example above, I often create tokens long these lines:

#if($lead.products_of_interest.contains("A")) 
  #set( $storyHidden = false )
#else
  <!--
  #set( $storyHidden = true )
#end

Repeat this token as many times as you have potential products of interest.

 

and then another token that looks like this

#if($storyHidden)
  -->
#end

 

Drop your product of interest token before a series of Marketo Modules, and then drop in the second token at the end of the modules (something like this)

Product of interest token

A headline

An image

Some body text

End token

A different product of interest token

a headline

some body text

end token

 

This means you can use Marketo modules (Images, Body Content, CTAs etc).  You have to be a little careful around other comments in your code of course as they can break the heck out of this (HTML does not support nested comments), but it does give you a lot of flexibility.  

 

You may also have to be mindful of the overall size of your email with this approach as ALL the content is in the email, just commented out.  As with all things, there are pluses and minuses.

 

Cheers

Jo

 

Chris_Wilcox
Level 9

Great point Jo!  Love that solution, part of what makes Velocity so powerful is it's insane flexibility!

Jared_Kimball2
Level 3

Thanks @Chris_Wilcox I'm trying to figure out how to put a contacts custom object field data in an email. 

How do I do that?

 

For example, I want to put the cruise line name in an email that's stored on the opportunity object

Here is the script I've written:

##show the name of the cruise line
#if
${OpportunityList.get(0).cruiseLine}
#else
your cruiseline
#end

 

When I test it out all I get is "Email Default Text".

Thanks in advance,

Jared

SanfordWhiteman
Level 10 - Community Moderator

Hi Jared,

 

1st pointer... the OpportunityList is a list of Opportunities, not a single item. So it actually doesn't have "a" cruiseLine value, as there's one for every item in the list. (Even if there's only one Opportunity in the list at a certain point in time, one shouldn't think of the list as a single item, as it is always a collection that needs to be looped over.)

 

2nd... Velocity directives like #if are always followed by parentheses, so what you have above is a syntax error

 

To iterate over the list and output the cruiseLine for each one:

#if( !$OpportunityList.isEmpty() )
#foreach( $oppty in $OpportunityList )
#if( !$display.alt($oppty.cruiseLine,"").isEmpty() )
${oppty.cruiseLine}
#else
your cruiseline
#end
#end
#end

 

Note I also check if the list is empty, a crititcal measure when proofing emails.

 

 

Amanda_Thomas6
Level 9

Wow! This guide is awesome! Thanks Chris!

Marcia_Kerber
Level 3

Thank you for putting this together and sharing it!  A lot of great info here.

neelambakre
Level 3

I'm new to Velocity scripts, but this guide has made it much easier to understand.

Thank you for such a detailed and informative resource.

Chris_Wilcox
Level 9

@neelambakre Glad it was useful! Always around for support! 🙂 

Kristof
Level 4

Such a great guide that is so friendly to digest for people that are new to velocity scripting. Thanks @Chris_Wilcox, you are a great teacher!

Just two Qs please:
- what is actually meant by a "MSD" object type?

- in your 1st example you are saying: sales group 3 OR sales group 4 AND West - I don't see any "advanced logic brackets" there that would group ORs - like this: (3 OR 4) AND West - are these not needed there?

SanfordWhiteman
Level 10 - Community Moderator
  • Microsoft Dynamics
  • Think you’re right, hard to be sure in the screenshot but it looks like there’s a syntax error as the #if() is closed too early