SOLVED

Velocity Dynamic Content Sorting

Go to solution
Jayant_Singh
Level 3

I have imported a list of records to custom objects which contains data based on user visits in the website. By using this list trying to create email in Marketo. From CO list, selecting only recent visit of the product. In the given list, have product name, image, URL and recent visit date.

 

Problem- I have created three velocity script and sorting the list based on recent visit date. But, in email output is display incorrect.

 

Jayant_Singh_0-1590074462697.png

 

Below three velocity script used for sorting the product name, image and URL.

 

 

 

Script-1

<html>
<body>
<table>
## start product image select
<tbody>
#set( $DEFAULT_Product = "No item in list." )
<tr>
#if( $pro_cList.isEmpty() )
#set( $outputItemimage = $DEFAULT_Product )
#else
#foreach( $pro_c in $sorter.sort($pro_cList, "date:desc") )
#if( !$display.alt($pro_cList["productImage"],"").isEmpty() )
#set( $outputItemimage = $pro_c["productImage"] )
#break
#end
#end
#set( $outputItemimage = $display.alt($outputItemimage, $DEFAULT_Product) )
#end
<td>
<img width="189" align="right" src="${outputItemimage}" border="0"/>
</td>
</tr>
</tbody>
</table>
</body>
</html>

 

 

 

 

 

Script-2

<html>
<body>
<table>
## start product name select
<tbody>
#set( $DEFAULT_Product = "No item in list." )
<tr>
#if( $pro_cList.isEmpty() )
#set( $outputName = $DEFAULT_Product )
#else
#foreach( $pro_c in $sorter.sort($pro_cList, "date:desc") )
#if( !$display.alt($pro_cList["productName"],"").isEmpty() )
#set( $outputName = $pro_c["productName"] )
#break
#end
#end
#set( $outputName = $display.alt($outputName, $DEFAULT_Product) )
#end
<td>
${outputName}
</td>
</tr>
</tbody>
</table>
</body>
</html>

 

 

 

 

 

Script-3

<html>
<body>
<table>
## start product URL select
<tbody>
#set( $DEFAULT_Product = "No item in list." )
<tr>
#if( $pro_cList.isEmpty() )
#set( $outputItemCTA = $DEFAULT_Product )
#else
#foreach( $pro_c in $sorter.sort($pro_cList, "date:desc") )
#if( !$display.alt($pro_cList["productCTA"],"").isEmpty() )
#set( $outputItemCTA = $pro_c["productCTA"] )
#break
#end
#end
#set( $outputItemCTA = $display.alt($outputItemCTA, $DEFAULT_Product) )
#end
<td>
<a href="${outputItemCTA}">Check out</a>
</td>
</tr>
</tbody>
</table>
</body>
</html>

 

 

 

Jayant
1 ACCEPTED SOLUTION
SanfordWhiteman
Level 10 - Community Moderator

This line:

#if( !$display.alt($pro_cList["productName"],"").isEmpty() )

 

Should be:

#if( !$display.alt($pro_c["productName"],"").isEmpty() )

 

Remember, when you're iterating over the items ($pro_c) in the list, you want to test the item, not the whole list.

View solution in original post

20 REPLIES 20
SanfordWhiteman
Level 10 - Community Moderator

Hi Jayant,

 

This seems like an overly wordy (and thus fragile) way to do this — it could easily be a single token with a #macro since the logic is the same other than the field name.

 

Beyond that, I'd need to see a dump of all of the data from the list. Chances are, for the fields that are outputting the default value, you don't have them checked off in the tree in Script Editor. 

Jayant_Singh
Level 3

Hi San,

Before creating macro, I want to fetch the data for each field correctly. So, I am not able to find checked off condition for the script. Can you please suggest more in this?

Jayant_Singh_0-1590158250005.png

 

 

Jayant
SanfordWhiteman
Level 10 - Community Moderator

Not sure I understand what you're saying here.  When I say "checked off" I mean in the tree (of Lead and Object fields) on the right-hand-side of Script Editor.

Jayant_Singh
Level 3

I have already selected that one but not sure why it is evaluating only default output this is the worry part and I am not starting macro unless I am sure that I can get output individually correct. 

Jayant
SanfordWhiteman
Level 10 - Community Moderator

Please show a screenshot of the Script Editor tree with the checkboxes checked for all the fields.

 

If you want to check to see if something has a non-null value (including an empty String, which is a value) just output that ${lead.field}.  If you've failed to check off the field, you'll see the literal VTL code, since that's what Velocity prints if the value is null.

Jayant_Singh
Level 3

Jayant_Singh_0-1590174159415.pngJayant_Singh_0-1590174480876.pngJayant_Singh_0-1590174238138.png

I am selecting CO list tree. am I missing anything?

 

Jayant
SanfordWhiteman
Level 10 - Community Moderator

I see 3 fields, sure, though what their Velocity property names are isn't clear.

 

Run this standard CO debugging code:

 

#set( $coList = $pro_cList )
#foreach( $record in $coList )
#foreach( $kv in $record.entrySet() )
${kv.getKey()} ${display.alt($kv.getValue().class,"")} ${display.alt($kv.getValue(),"null")}
#end
#end

 

Jayant_Singh
Level 3

In the given code,

1. kv and record will be replaced with any property?

2. This code need to add in velocity script in starting

 

Jayant
SanfordWhiteman
Level 10 - Community Moderator

Nope, nothing to replace. 

 

Just put this exact at the top of your token to get debug output.

Jayant_Singh
Level 3

I have added the code in three ways

1. Full code at top after debug no change in previous email design.

2. Both end statement at last after debug nothing display.

3. Putting both end statement before output the ${outputName} and got below design

Jayant_Singh_0-1590177290207.png

 

Jayant
SanfordWhiteman
Level 10 - Community Moderator

I'm not sure you're putting the code in the right place.

 

If you put that code in a Velocity token (in Script Editor) it'll give you a full debug dump of all the fields in the given list, with their names, values (or null) and datatypes.

Jayant_Singh
Level 3

This is the one script product name where I added the code at the top.

 

<html>
<body>
<table>
#set( $coList = $pro_cList )
#foreach( $record in $coList )
#foreach( $kv in $record.entrySet() )
{kv.getKey()} ${display.alt($kv.getValue().class,"")} ${display.alt($kv.getValue(),"null")}
#end
#end
## start product name select
<tbody>
#set( $DEFAULT_Product = "No item in list." )
<tr>
#if( $pro_cList.isEmpty() )
#set( $outputName = $DEFAULT_Product )
#else
#foreach( $pro_c in $sorter.sort($pro_cList, "date:desc") )
#if( !$display.alt($pro_cList["productName"],"").isEmpty() )
#set( $outputName = $pro_c["productName"] )
#break
#end
#end
#set( $outputName = $display.alt($outputName, $DEFAULT_Product) )
#end
<td>
${outputName}
</td>
</tr>
</tbody>
</table>
</body>
</html>

 

 is code placement is incorrect? 

Jayant
SanfordWhiteman
Level 10 - Community Moderator

It's very surprising to me that you're outputting the entire email from a single Velocity token. That's not usually — well, basically, it's never done.

 

Please reduce the "testing surface" so that you're only outputting the product list (using my debug code) from VTL. Don't mix in anything else, put everything else in the template.

Jayant_Singh
Level 3

I am using only the debug code and removed everything from VTL.

 

#set( $coList = $pro_cList )
#foreach( $record in $coList )
#foreach( $kv in $record.entrySet() )
{kv.getKey()} ${display.alt($kv.getValue().class,"")} ${display.alt($kv.getValue(),"null")}
#end
#end
${coList}

 

 In the template, I am using {{my.VTL}}  to debug it now. is it ok now or need to add code more?

Jayant
SanfordWhiteman
Level 10 - Community Moderator

That's seems like the right start.

 

So what's in the output?

Jayant_Singh
Level 3

 

{kv.getKey()} class java.lang.String 2020-03-23 08:20:02 {kv.getKey()} class java.lang.String 4 {kv.getKey()} class java.lang.String https://www.mdg.co.in/product/item4.html {kv.getKey()} class java.lang.String b1c1c49a-1545-3c38-a421-d3af748ac5c1 {kv.getKey()} class java.lang.String http://ta-sj29.marketo.com/rs/717-ICG-368/images/item4.png {kv.getKey()} class java.lang.String item3 {kv.getKey()} class java.lang.String 2020-04-24 08:20:02 {kv.getKey()} class java.lang.String 5 {kv.getKey()} class java.lang.String https://www.mdg.co.in/product/item6.html {kv.getKey()} class java.lang.String b1c1c49a-1545-3c38-a421-d3af748ac5c1 {kv.getKey()} class java.lang.String http://ta-sj29.marketo.com/rs/717-ICG-368/images/item6.png {kv.getKey()} class java.lang.String item4 {kv.getKey()} class java.lang.String 2020-05-20 08:20:02 {kv.getKey()} class java.lang.String 6 {kv.getKey()} class java.lang.String https://www.mdg.co.in/product/item5.html {kv.getKey()} class java.lang.String b1c1c49a-1545-3c38-a421-d3af748ac5c1 {kv.getKey()} class java.lang.String http://ta-sj29.marketo.com/rs/717-ICG-368/images/item5.png {kv.getKey()} class java.lang.String item5 [{date=2020-03-23 08:20:02, leadID=4, productCTA=https://www.mdg.co.in/product/item4.html, productID=b1c1c49a-1545-3c38-a421-d3af748ac5c1, productImage=http://ta-sj29.marketo.com/rs/717-ICG-368/images/item4.png, productName=item3}, {date=2020-04-24 08:20:02, leadID=5, productCTA=https://www.mdg.co.in/product/item6.html, productID=b1c1c49a-1545-3c38-a421-d3af748ac5c1, productImage=http://ta-sj29.marketo.com/rs/717-ICG-368/images/item6.png, productName=item4}, {date=2020-05-20 08:20:02, leadID=6, productCTA=https://www.mdg.co.in/product/item5.html, productID=b1c1c49a-1545-3c38-a421-d3af748ac5c1, productImage=http://ta-sj29.marketo.com/rs/717-ICG-368/images/item5.png, productName=item5}]

 

Jayant
SanfordWhiteman
Level 10 - Community Moderator

You have a typo.

 

{kv.getKey()} 

is supposed to be

${kv.getKey()} 

 

Also, can you please do this in the Text-only version of the email so the line breaks are preserved? 🙂 Kind of impossible to read otherwise.

Jayant_Singh
Level 3
date class java.lang.String 2020-03-20 08:20:02
leadID class java.lang.String 1
productCTA class java.lang.String https://www.mdg.co.in/product/item.html
productID class java.lang.String 059130d0-b9a5-4691-9f85-4f94afdadffe
productImage class java.lang.String http://ta-sj29.marketo.com/rs/717-ICG-368/images/item.png
productName class java.lang.String item
date class java.lang.String 2020-04-21 08:20:02
leadID class java.lang.String 2
productCTA class java.lang.String https://www.mdg.co.in/product/item2.html
productID class java.lang.String 059130d0-b9a5-4691-9f85-4f94afdadffe
productImage class java.lang.String http://ta-sj29.marketo.com/rs/717-ICG-368/images/item2.png
productName class java.lang.String item1
date class java.lang.String 2020-05-22 08:20:02
leadID class java.lang.String 3
productCTA class java.lang.String https://www.mdg.co.in/product/item3.html
productID class java.lang.String 059130d0-b9a5-4691-9f85-4f94afdadffe
productImage class java.lang.String http://ta-sj29.marketo.com/rs/717-ICG-368/images/item3.png
productName class java.lang.String item2
[{date=2020-03-20 08:20:02, leadID=1, productCTA=https://www.mdg.co.in/product/item.html, productID=059130d0-b9a5-4691-9f85-4f94afdadffe, productImage=http://ta-sj29.marketo.com/rs/717-ICG-368/images/item.png, productName=item}, {date=2020-04-21 08:20:02, leadID=2, productCTA=https://www.mdg.co.in/product/item2.html, productID=059130d0-b9a5-4691-9f85-4f94afdadffe, productImage=http://ta-sj29.marketo.com/rs/717-ICG-368/images/item2.png, productName=item1}, {date=2020-05-22 08:20:02, leadID=3, productCTA=https://www.mdg.co.in/product/item3.html, productID=059130d0-b9a5-4691-9f85-4f94afdadffe, productImage=http://ta-sj29.marketo.com/rs/717-ICG-368/images/item3.png, productName=item2}]
Jayant
Jayant_Singh
Level 3

Hi Sanford,

I was wondering  if you have gone through the debug code and please let me know the details.

Jayant
SanfordWhiteman
Level 10 - Community Moderator

This line:

#if( !$display.alt($pro_cList["productName"],"").isEmpty() )

 

Should be:

#if( !$display.alt($pro_c["productName"],"").isEmpty() )

 

Remember, when you're iterating over the items ($pro_c) in the list, you want to test the item, not the whole list.