Don't use Velocimacros for link output — but #define is fine

Velocimacros are functions that can be declared at the top of a template or context and reused as many times as you need. Really, the term “macro” doesn't do them justice, since with VTL you can use a wide swath of Java language features, and all that fun stuff can be used inside a #macro too.

While using macros in tiny scripts is probably a sign of overengineering, when I answer questions on the Marketo community I like to structure my code with the user-editable parts (i.e. site-specific strings) at the top, followed by a comment like ## No need to edit below this line! — the goal being to make new/non-developers a little less frightened.

So if at the end of a script you'll want to output a link (as is very common!) you might think about putting a macro at the top to call later:

#macro( outputLink $documentURL )
<a href="${documentURL}">Click to get your document!</a>
#end
## No need to edit below here!
... lots ...
... of ...
... other ...
... code ...
#set ( $url = "http://www.example.com/something" )
#outputLink( $url )

A newbie could then tweak the “Click to get…” text without having to touch the meat of the code.

Indeed, this works fine in Velocity in general. But a macro doesn't work here because of Marketo's unique Velocity implementation.

While Marketo is okay with calling a #macro for computation, when it comes to output, stuff breaks. There are tricky rules governing when an <A> tag output from Velocity will be rewritten to go via Marketo's tracking server. Marketo PM Justin Cooperman explained many of those rules here. (Unfortunately, though his remarks are certainly authoritative, these rules don't yet appear in any formal documentation.)

In addition to those rules, there appears to be a “previously unreleased” rule (you heard it here first) that links coming out of a Velocimacro will break. It's not that they won't be tracked (they are, actually!) but they don't interpret Velocity variables correctly. As in, the final URL the tracking server tries to send you to is literally

${documentLink}

and that's... not gonna work! (In more vanilla Velocity environment, you'd see the expected output <a href="http://www.example.com/my.pdf">Click to get your document!</a>.)

#define to the mostly-rescue

Luckily, though, Velocity defines can be used for this purpose and they do work with Marketo email links.

A #define is more like a traditional “macro” in that it only allows for the inline insertion of a block of prefab code. (It doesn't take any arguments or have a return value, so you'd never call it a function.)

Following the concept above, you'd use it like this:

#define( $formatLink )<a href="http://${url}">Click to get your document!</a>#end
## No need to edit below here!
... lots ...
... of ...
... other ...
... code ...
#set ( $url = "http://www.example.com/something" )
${formatLink}

So it mostly does the trick, if this is trick you want to do. Enjoy!