SOLVED

Using multiple contains values in Velocity

Go to solution
Highlighted

Using multiple contains values in Velocity

This is my first time using Velocity so apologies if it's an obvious answer. We need to populate based on multiple contains values in a single field, and have a default for anything that doesn't match but I'm not sure how best to write this out using Velocity. How would I write out this script?

If Job Function contains "programmer" "engineer"

Show: "Hello techie person"

elseIf Job Function contains "marketer" "sales"
Show: "Hello marketing person"

elseIf Job Function doesn't contain any of those values

Show: "Hello general person"

1 ACCEPTED SOLUTION

Accepted Solutions
Highlighted
Level 10 - Community Moderator

Re: Using multiple contains values in Velocity

#set( $imagePath = "http://lp.accessintel.com/rs/881-ZTT-725/images/" )         

#set( $outputByjobFunction = [           

{   

  "pattern" : "(?i).*\b(programmer|engineer)\b.*",    

  "color" : "#800080",   

  "greeting" : "techie person",  

  "images" : [

    "sm-black_i_50.gif", 

    "sm-black_f_50.gif", 

    "sm-black_t_50.gif" 

  ]

},   

{   

  "pattern" : "(?i).*\b(marketer|sales)\b.*",    

  "color" : "#B1309D",   

  "greeting" : "marketing person", 

  "images" : [

    "sm-rnd_fb_grey.png", 

    "sm-rnd_i_grey.png"   

  ]

},   

{   

  "pattern" : ".*",    

  "color" : "#99cc00",   

  "greeting" : "general person", 

  "images" : [

    "sm-square_li_100.gif", 

    "sm-square_g_100.gif", 

    "sm-square_fb_100.gif",  

    "sm-square_t_100.gif"  

  ]

}   

] )          

#foreach( $outputSet in $outputByjobFunction )          

#if( $lead.jobFunction.matches($outputSet.pattern) )         

    #set( $matchedOutputSet = $outputSet )  

    #break         

#end          

#end   

<span style="color: ${matchedOutputSet.color};">${matchedOutputSet.greeting}</span>   

  <table width="60%" border="0" cellspacing="0" cellpadding="6"> 

  <tbody> 

    <tr>

    #foreach( $image in $matchedOutputSet.images ) 

      <td align="center"><img src="${imagePath}${image}" width="30"></td> 

    #end

    </tr> 

  </tbody> 

</table>

I keep wondering if it would be faster to set up individual email script tokens with the tables of each images (the team keeps complicating this with more formatting needs, size changes, adding text, links, etc)

It's almost never better to repeat yourself, though at the same time you have to stop people from constantly changing the spec on you...

View solution in original post

14 REPLIES 14
Highlighted
Level 10 - Community Moderator

Re: Using multiple contains values in Velocity

Have you searched past threads on Velocity topics? There was one just the other day with a similar aim (the function is matches(), not contains ()).

Highlighted

Re: Using multiple contains values in Velocity

Hi Sanford,

Are you referring to this discussion? Velocity Script - value range

It's helpful in showing how to set up a consolidated list of matches but I'm a little confused about how I can use this to:

1. Target on incomplete values (so the lead's Job Function could be "programmer of nightmares" and they'd be included when I specify "programmer"

2. How to target multiple incomplete values in the same string

3. Use html as the shown content
4. How to test the default value

I'm not sure if this helps as an example, but here's what I'm attempting to do, and probably wrote out very badly

#set( $textByjobFunction = {     

"programmer" "engineer" : "<span style="color: #800080;">Hello techie person</span>", 

"marketer" "sales" : "<span style="font-size: 16px; color: #B1309D;">Hello marketing person</span>",    

"*" : "<span style="font-size: 16px; color: #99cc00;">Hello general person</span>"    

} )    

#foreach( $jobFunctionValue in $textByjobFunction.keySet() )    

## If we find a regex match for jobFunction we're done    

#if($lead.jobFunction.matches("(?i)${jobFunctionValue}") )    

    #set( $text = $htmlByjobFunction[$jobFunctionValue] )    

    #break   

#end    

#end  

$text

Highlighted
Level 10 - Community Moderator

Re: Using multiple contains values in Velocity

Well, that isn't valid VTL to begin with so it will always throw an error, even before you get to any business logic.

You also don't want to repeat yourself; the only thing different about those SPANs is the color so it should be factored out.

Something more like this:

#set( $outputByjobFunction = [       

{

  "pattern" : "(?i).*\b(programmer|engineer)\b.*",

  "color" : "#800080",

  "greeting" : "techie person"

},

{

  "pattern" : "(?i).*\b(marketer|sales)\b.*",

  "color" : "#B1309D",

  "greeting" : "marketing person"

},

{

  "pattern" : ".*",

  "color" : "#99cc00",

  "greeting" : "general person"

}

] )      

#foreach( $outputSet in $outputByjobFunction )      

#if( $lead.jobFunction.matches($outputSet.pattern) )     

    #set( $matchedOutputSet = $outputSet )      

    #break     

#end      

#end

<span style="color: ${matchedOutputSet.color};">${matchedOutputSet.greeting}</span>

I did just write this on a plane so it may not be perfect, but it is the right pattern to follow.

Highlighted

Re: Using multiple contains values in Velocity

Ahhh got it! I'm running into issues with previewing, though. When I preview the email and view by person, I'm selecting leads I specifically set up for testing (so I know they don't exist in any other partitions), and of the 4 unique leads I set up, 2 (one in each pattern matches) show their dynamic content and the other 2 show the generic content.

So this makes perfect sense, but how would I add a block of html for each variable? The team would want to add images, and they won't be consistent across each pattern. Is this the best way to write it out?

#set( $outputByjobFunction = [         

  "pattern" : "(?i).*\b(programmer|engineer)\b.*",  

  "color" : "#800080", 

  "greeting" : "techie person",

  "image1" : "sm-black_i_50.gif",

  "image2" : "sm-black_f_50.gif",

  "image3" : "sm-black_t_50.gif"

}, 

  "pattern" : "(?i).*\b(marketer|sales)\b.*",  

  "color" : "#B1309D", 

  "greeting" : "marketing person",

  "image1" : "sm-rnd_fb_grey.png",

  "image2" : "sm-rnd_i_grey.png" 

}, 

  "pattern" : ".*",  

  "color" : "#99cc00", 

  "greeting" : "general person",

  "image1" : "sm-square_li_100.gif",

  "image2" : "sm-square_g_100.gif",

  "image3" : "sm-square_fb_100.gif",

  "image4" : "sm-square_t_100.gif"

] )        

#foreach( $outputSet in $outputByjobFunction )        

#if( $lead.jobFunction.matches($outputSet.pattern) )       

    #set( $matchedOutputSet = $outputSet )

    #set( $imagePath = "http://lp.accessintel.com/rs/881-ZTT-725/images/" )       

    #break       

#end        

#end 

<span style="color: ${matchedOutputSet.color};">${matchedOutputSet.greeting}</span> 

<table width="60%" border="0" cellspacing="0" cellpadding="6">

  <tbody>

    <tr>

      <td align="center"><img src="${imagePath}${matchedOutputSet.image1}" width="30"></td>

      <td align="center"><img src="${imagePath}${matchedOutputSet.image2}" width="30"></td>

      <td align="center"><img src="${imagePath}${matchedOutputSet.image3}" width="30"></td>

      <td align="center"><img src="${imagePath}${matchedOutputSet.image4}" width="30"></td>

    </tr>

  </tbody>

</table>

Highlighted
Level 10 - Community Moderator

Re: Using multiple contains values in Velocity

Ahhh got it! I'm running into issues with previewing, though. When I preview the email and view by person, I'm selecting leads I specifically set up for testing (so I know they don't exist in any other partitions), and of the 4 unique leads I set up, 2 (one in each pattern matches) show their dynamic content and the other 2 show the generic content.

Don't test with Preview-by-Leads, test with a static list and Preview-by-List (lesson from the master!). 

If you still have confusion about why someone isn't qualifying you can always output $lead.jobFunction directly for debugging.

So this makes perfect sense, but how would I add a block of html for each variable? The team would want to add images, and they won't be consistent across each pattern. Is this the best way to write it out?

#foreach( $outputSet in $outputByjobFunction )  #if( $lead.jobFunction.matches($outputSet.pattern) )   #set( $matchedOutputSet = $outputSet )   #set( $imagePath = "http://lp.accessintel.com/rs/881-ZTT-725/images/" )   #break  #end  #end 

The $imagePath is the same for every lead here, so there's no need to set it over and over again. It's indeed a good idea to store it in a variable, just not reassigning the value unnecessarily.

<table width="60%" border="0" cellspacing="0" cellpadding="6">  <tbody>  <tr>  <td align="center"><img src="${imagePath}${matchedOutputSet.image1}" width="30"></td>  <td align="center"><img src="${imagePath}${matchedOutputSet.image2}" width="30"></td>  <td align="center"><img src="${imagePath}${matchedOutputSet.image3}" width="30"></td>  <td align="center"><img src="${imagePath}${matchedOutputSet.image4}" width="30"></td>  </tr>  </tbody> </table>

If I'm reading your requirements correctly, this won't work b/c you have different numbers of images for each lead. In this case you need to put the images in a collection (list) not individual vars and #foreach over it.. I'll post some sample code later tonight that will get you started.

Highlighted

Re: Using multiple contains values in Velocity

Thank you! I keep wondering if it would be faster to set up individual email script tokens with the tables of each images (the team keeps complicating this with more formatting needs, size changes, adding text, links, etc), but I'm still figuring out how to best write this all out so I really appreciate the guidance!

Highlighted
Level 10 - Community Moderator

Re: Using multiple contains values in Velocity

#set( $imagePath = "http://lp.accessintel.com/rs/881-ZTT-725/images/" )         

#set( $outputByjobFunction = [           

{   

  "pattern" : "(?i).*\b(programmer|engineer)\b.*",    

  "color" : "#800080",   

  "greeting" : "techie person",  

  "images" : [

    "sm-black_i_50.gif", 

    "sm-black_f_50.gif", 

    "sm-black_t_50.gif" 

  ]

},   

{   

  "pattern" : "(?i).*\b(marketer|sales)\b.*",    

  "color" : "#B1309D",   

  "greeting" : "marketing person", 

  "images" : [

    "sm-rnd_fb_grey.png", 

    "sm-rnd_i_grey.png"   

  ]

},   

{   

  "pattern" : ".*",    

  "color" : "#99cc00",   

  "greeting" : "general person", 

  "images" : [

    "sm-square_li_100.gif", 

    "sm-square_g_100.gif", 

    "sm-square_fb_100.gif",  

    "sm-square_t_100.gif"  

  ]

}   

] )          

#foreach( $outputSet in $outputByjobFunction )          

#if( $lead.jobFunction.matches($outputSet.pattern) )         

    #set( $matchedOutputSet = $outputSet )  

    #break         

#end          

#end   

<span style="color: ${matchedOutputSet.color};">${matchedOutputSet.greeting}</span>   

  <table width="60%" border="0" cellspacing="0" cellpadding="6"> 

  <tbody> 

    <tr>

    #foreach( $image in $matchedOutputSet.images ) 

      <td align="center"><img src="${imagePath}${image}" width="30"></td> 

    #end

    </tr> 

  </tbody> 

</table>

I keep wondering if it would be faster to set up individual email script tokens with the tables of each images (the team keeps complicating this with more formatting needs, size changes, adding text, links, etc)

It's almost never better to repeat yourself, though at the same time you have to stop people from constantly changing the spec on you...

View solution in original post

Highlighted

Re: Using multiple contains values in Velocity

This is amazing, thank you! I'm running into a new issue now, with the script above, everything works perfectly. However, when I alter the script to target specific Company Names, and create a static list of test leads that I know have company names that match the keywords, I get the following error in my email preview (viewing by List, not person, as you recommended 😞

Cannot get email content-

An error occurred when procesing the email Body!

Encountered "}" near

  "pattern" : "(?i)(.*)(^|,)\s*energysolutions|energysource|mhf services|energy solutions\s*(,|$)(.*)",      

  "speaker" : "goodbye",    

},     

{     

  "pattern" : "(?i)(.*)(^|,)\s*nuclear regulatory comm|nrc|usnrc\s*(,|$)(.*)", 

This is the velocity script token I'm using. I'm sure I'm missing something obvious:

#set( $outputByCompany = [             

{     

  "pattern" : "(?i).*\b(energysolutions|energysource|mhf services|energy solutions)\b.*",      

  "speaker" : "goodbye",    

},     

{     

  "pattern" : "(?i).*\b(nuclear regulatory comm|nrc|usnrc)\b.*",      

  "speaker" : "hello",   

},     

{     

  "pattern" : ".*",      

  "speaker" : "from ${lead.Company}",   

}     

] )            

#foreach( $outputSet in $outputByCompany )            

#if( ${lead.Company}.matches($outputSet.pattern) )           

    #set( $matchedOutputSet = $outputSet )    

    #break           

#end            

#end     

${matchedOutputSet.speaker} 

Highlighted
Level 10 - Community Moderator

Re: Using multiple contains values in Velocity

Trailing comma after the last object property.

{

  "prop" : "value",

  "prop1" : "value1",

}

must be

{

"prop" : "value",

"prop1" : "value1"

}

The error message gives you a clue for where to look.