Streamline your script tokens with a #displayIfFilled Velocimacro

Printing fallback content when a Lead field is blank is a basic Velocity task. You can do it in a few lines of clunky code… but that's a few lines too many!

Seeking a one-liner, you might reach for Velocity's built-in $display.alt. But that won't fill the bill in Marketo-land. You see, $display.alt($field, $fallback) outputs the fallback if the field is null. But null isn't the same as the empty String that Marketo uses for unfilled Lead fields.

Therefore, the code

Dear ${display.alt($lead.FirstName,"Friend")},

will only ever output

Dear Joe,

or

Dear ,

It will never fall back to Dear Friend, because Marketo ensures $lead.FirstName is always a String of some kind, never null.[1]

So without any other tools at your disposal, you're left with a typically wordy #if block:

Of course, #displayIf can be overused; past a certain point of complexity, you should be using #if-#else on separate lines. But where a one-liner doesn't hurt readability, I say use it. #displayIf is critical to my sanity (if I have any left) as an avid Velocity coder.

Stay functional

There's another detail that you'd eventually learn on your own, but I'll spoil it to save you time.

When passing macro arguments in parentheses, you can include any chain of function calls but not syntactical expressions. For example, though Boolean operators and expressions are valid in other parts of Velocity, you can't do:

To be clear, this doesn't mean you can't use all manner of operators and expressions to construct Boolean values, you just can't use them directly inside the parentheses when calling a macro. This will work fine:

What's with $context.get("0")?

Ah, yes. I don't want to overwhelm you earlier with the details of null checking in Velocity.

$context.get("0") (up above in the first #displayIfFilled macro) gets the value of a reference that is guaranteed to not exist, i.e. guaranteed to be null, in any Velocity context.

Why is it guaranteed to not exist? Because neither Java nor Velocity variable names are allowed to begin with a number.

Why not compare to the literal null? Because — and this reality sneaks up in other important places in Velocity — there is no four-letter keyword null! The null-ability of injected data is honored, even favored, in Velocity, like by $display.alt as noted above. But it doesn't have a keyword to create new null values easily.

So you have to find a roundabout way of getting a reference to a null value. Elsewhere on the net, people say “just use a variable you didn't #set anywhere else, like $abcdefg, as that will naturally be null.” The flaw in this reasoning is nothing actually stops someone else (either a future coder or a current collaborator) from using $abcdefg for something else. So I prefer to use a reference that cannot exist even by coincidence.

Notes

[1] In the Marketo Lead/Person world, you aren't gonna run into literal null values, but rather empty strings. This is true despite non-filled fields being represented as [null] or NULL in parts of the Marketo UI. You can and will encounter null with Custom Objects, though. That's the stuff of another post.

[2] Yes, you could smush the VTL into one line. But if you think Dear #if($lead.FirstName.isEmpty())Friend#else${lead.FirstName}#end, is sufficiently readable, you're made of stronger stuff than me.