I'm having an issue where instead of Marketo showing the default value when previewing an email, it shows ${drivername}. In the campaign I'm building, not all values set in velocity will exist in the JSON field. Some records may have a few while another has all.
How do I code my velocity so that if a value I'm setting is missing from the JSON field, it is overlooked and the echo script I set in a token doesn't output ${drivername}, but outputs the default value "there", such as {{my.drivername:DEFAULT=there}}?
##set defaults
#set( $utm_source = "mkto-email" )
#set( $utm_medium = "customer-engagement" )
#set( $utm_campaign = "TXreferralsprogram" )
#set( $messageHTML = "" )
##check JSON and set vars
#if( $lead.carpoolJSON.isEmpty() )
#set( $lead.carpoolJSON = '[]' )
#elseif( $lead.carpoolJSON )
#set( $refData = '#set( $refData = ' + ${lead.carpoolJSON} + ' )' )
#evaluate($refData)
#end
#foreach( $ref in $refData )
#set( $referralURL = $ref[0].driverReferralUrl )
#set( $driveruniqueUrl = $ref[0].driverUniqueUrl )
#set( $custommessage = $ref[0].customMessage )
#set( $drivername = $ref[0].driverName )
#set( $driverdashboardurl = $ref[0].driverDashboardUrl )
#set( $giftSelectionUrl = $ref[0].giftSelectionUrl )
#set( $passengername = $ref[0].passengerName )
#end
#if( $custommessage.isEmpty() )
#set( $custommessage = '[]' )
#elseif( $custommessage )
#set( $messageHTML = '<td align="center" vertical-align="middle" style="font-size:24px; font-style: italic; font-weight: 400; color: #184c6d; padding:15px;word-break:break-word;"><table cellpadding="15" cellspacing="0" border="0" role="presentation" style="background: #f8f8f8; max-width: 520px; width: 100%;"><tr><td>"${custommessage}" </br></br><span style="font-weight: 700; font-size: 18px;">${drivername}</span></br></br></td></tr></table></td>' )
#end
#set( $referralURL2 = $referralURL.replace("https://", "") )
#set( $driveruniqueUrl2 = $driveruniqueUrl.replace("https://", "") )
#set( $driverdashboardurl2 = $driverdashboardurl.replace("https://", "") )
#set( $giftSelectionUrl2 = $giftSelectionUrl.replace("https://", "") )
Solved! Go to Solution.
You haven't really detailed your data model, so I've had to infer it from your code (which is always risky).
Assuming all properties are present, your code may expect a JSON structure like this, an array with an inner array with inner object(s):
[
[
{
"driverReferralUrl" : "https://example1.com",
"driverUniqueUrl" : "https://example2.com",
"customMessage" : "Hello",
"driverName" : "Raj",
"driverDashboardUrl" : "https://example3.com",
"giftSelectionUrl" : "https://example4.com",
"passengerName" : "Sandy"
}
]
]
However, it loops over the outer array, without exiting, and reads the first object of the inner array. So in fact JSON like this (shortened for readability) will still be parsed:
[
[
{
"driverName" : "Raj",
"passengerName" : "Sandy"
},
{
"driverName" : "Raj 2",
"passengerName" : "Sandy 2"
}
],
[
{
"driverName" : "Raj 3",
"passengerName" : "Sandy 3"
},
{
"driverName" : "Raj 4",
"passengerName" : "Sandy 4"
}
]
]
Leaving you with with driverName "Raj 3" and passengerName "Sandy 3".
I don't know if this result is expected or desired. But any time you're repeatedly overwriting a global value in a loop, and seeking the same object multiple times, that's generally a sign that something is wrong, and certainly inefficient. If you only care about the 1st object in the 1st array, you should go right to it with $refData[0][0], don't iterate needlessly.
Also not sure what you really expect to happen if the JSON field is completely empty. Even though you're transforming it from an empty string into "[]" (which is a really good idea), because everything you have is inside a loop over the (empty) outer array, none of your output variables are set in that case.
More notes:
So I recommend this code over what you've got, but you have to think about the above business logic questions as well.
## UTM params
#set( $utm_source = "mkto-email" )
#set( $utm_medium = "customer-engagement" )
#set( $utm_campaign = "TXreferralsprogram" )
## JSON defaults for missing properties
#set( $defaults = {
"driverReferralUrl" : "",
"driverUniqueUrl" : "",
"customMessage" : "",
"driverName" : "there",
"driverDashboardUrl" : "",
"giftSelectionUrl" : "",
"passengerName" : "Your referred friend"
})
## ensure JSON is parsed as at least an empty List
#if( $lead.carpoolJSON.isEmpty() )
#set( $lead.carpoolJSON = '[]' )
#end
## hydrate JSON
#set( $refData = "${esc.h}set( ${esc.d}refData = ${lead.carpoolJSON} )" )
#evaluate($refData)
## start with defaults
#set( $focusedRef = $defaults.clone() )
#foreach( $ref in $refData )
#set( $void = $focusedRef.putAll($ref[0]) )
#set( $referralURL = $focusedRef.driverReferralUrl )
#set( $driveruniqueUrl = $focusedRef.driverUniqueUrl )
#set( $custommessage = $focusedRef.customMessage )
#set( $drivername = $focusedRef.driverName )
#set( $driverdashboardurl = $focusedRef.driverDashboardUrl )
#set( $giftSelectionUrl = $focusedRef.giftSelectionUrl )
#set( $passengername = $focusedRef.passengerName )
#end
#if( !$custommessage.isEmpty() )
#define( $messageHTML )
<td align="center" vertical-align="middle" style="font-size:24px; font-style: italic; font-weight: 400; color: #184c6d; padding:15px;word-break:break-word;"><table cellpadding="15" cellspacing="0" border="0" role="presentation" style="background: #f8f8f8; max-width: 520px; width: 100%;"><tr><td>"${custommessage}" </br></br><span style="font-weight: 700; font-size: 18px;">${drivername}</span></br></br></td></tr></table></td>
#end
#else
#define( $messageHTML )
[]
#end
#end
#set( $referralURLNoHost = $referralURL.replaceAll("^https://", "") )
#set( $driveruniqueUrlNoHost = $driveruniqueUrl.replaceAll("^https://", "") )
#set( $driverdashboardurlNoHost = $driverdashboardurl.replaceAll("^https://", "") )
#set( $giftSelectionUrlNoHost = $giftSelectionUrl.replaceAll("^https://", "") )
Please highlight your code (as Java, closest to VTL) using the syntax highlighter, then we'll continue.
Hey Sanford. Thanks. I edited my question and highlighted the code as Java.
Thanks, I'll answer when back at the office in ~1.5h, wanted it to be ready for me.
I believe I fixed it. I set my defaults at the top of the script. Seems to be working. There are some instances where the values will be passed into the JSON field with "". So that's why I did line 29-31. Thank you though Sanford. If you have the time to evaluate my coding, I'd appreciate that. I'm new to Velocity.
##set defaults
#set( $utm_source = "mkto-email" )
#set( $utm_medium = "customer-engagement" )
#set( $utm_campaign = "TXreferralsprogram" )
#set( $messageHTML = "" )
#set( $drivername = "there" )
#set( $passengername = "your referred friend" )
##check JSON and set vars
#if( $lead.carpoolJSON.isEmpty() )
#set( $lead.carpoolJSON = '[]' )
#elseif( $lead.carpoolJSON )
#set( $refData = '#set( $refData = ' + ${lead.carpoolJSON} + ' )' )
#evaluate($refData)
#end
#foreach( $ref in $refData )
#set( $referralURL = $ref[0].driverReferralUrl )
#set( $driveruniqueUrl = $ref[0].driverUniqueUrl )
#set( $custommessage = $ref[0].customMessage )
#set( $drivername = $ref[0].driverName )
#set( $driverdashboardurl = $ref[0].driverDashboardUrl )
#set( $giftSelectionUrl = $ref[0].giftSelectionUrl )
#set( $passengername = $ref[0].passengerName )
#end
#if( $custommessage.isEmpty() )
#set( $custommessage = '[]' )
#elseif( $custommessage )
#set( $messageHTML = '<td align="center" vertical-align="middle" style="font-size:24px; font-style: italic; font-weight: 400; color: #184c6d; padding:15px;word-break:break-word;"><table cellpadding="15" cellspacing="0" border="0" role="presentation" style="background: #f8f8f8; max-width: 520px; width: 100%;"><tr><td>"${custommessage}" </br></br><span style="font-weight: 700; font-size: 18px;">${drivername}</span></br></br></td></tr></table></td>' )
#end
#if( $passengername.isEmpty() )
#set( $passengername = 'Your referred friend' )
#end
#set( $referralURL2 = $referralURL.replace("https://", "") )
#set( $driveruniqueUrl2 = $driveruniqueUrl.replace("https://", "") )
#set( $driverdashboardurl2 = $driverdashboardurl.replace("https://", "") )
#set( $giftSelectionUrl2 = $giftSelectionUrl.replace("https://", "") )
You haven't really detailed your data model, so I've had to infer it from your code (which is always risky).
Assuming all properties are present, your code may expect a JSON structure like this, an array with an inner array with inner object(s):
[
[
{
"driverReferralUrl" : "https://example1.com",
"driverUniqueUrl" : "https://example2.com",
"customMessage" : "Hello",
"driverName" : "Raj",
"driverDashboardUrl" : "https://example3.com",
"giftSelectionUrl" : "https://example4.com",
"passengerName" : "Sandy"
}
]
]
However, it loops over the outer array, without exiting, and reads the first object of the inner array. So in fact JSON like this (shortened for readability) will still be parsed:
[
[
{
"driverName" : "Raj",
"passengerName" : "Sandy"
},
{
"driverName" : "Raj 2",
"passengerName" : "Sandy 2"
}
],
[
{
"driverName" : "Raj 3",
"passengerName" : "Sandy 3"
},
{
"driverName" : "Raj 4",
"passengerName" : "Sandy 4"
}
]
]
Leaving you with with driverName "Raj 3" and passengerName "Sandy 3".
I don't know if this result is expected or desired. But any time you're repeatedly overwriting a global value in a loop, and seeking the same object multiple times, that's generally a sign that something is wrong, and certainly inefficient. If you only care about the 1st object in the 1st array, you should go right to it with $refData[0][0], don't iterate needlessly.
Also not sure what you really expect to happen if the JSON field is completely empty. Even though you're transforming it from an empty string into "[]" (which is a really good idea), because everything you have is inside a loop over the (empty) outer array, none of your output variables are set in that case.
More notes:
So I recommend this code over what you've got, but you have to think about the above business logic questions as well.
## UTM params
#set( $utm_source = "mkto-email" )
#set( $utm_medium = "customer-engagement" )
#set( $utm_campaign = "TXreferralsprogram" )
## JSON defaults for missing properties
#set( $defaults = {
"driverReferralUrl" : "",
"driverUniqueUrl" : "",
"customMessage" : "",
"driverName" : "there",
"driverDashboardUrl" : "",
"giftSelectionUrl" : "",
"passengerName" : "Your referred friend"
})
## ensure JSON is parsed as at least an empty List
#if( $lead.carpoolJSON.isEmpty() )
#set( $lead.carpoolJSON = '[]' )
#end
## hydrate JSON
#set( $refData = "${esc.h}set( ${esc.d}refData = ${lead.carpoolJSON} )" )
#evaluate($refData)
## start with defaults
#set( $focusedRef = $defaults.clone() )
#foreach( $ref in $refData )
#set( $void = $focusedRef.putAll($ref[0]) )
#set( $referralURL = $focusedRef.driverReferralUrl )
#set( $driveruniqueUrl = $focusedRef.driverUniqueUrl )
#set( $custommessage = $focusedRef.customMessage )
#set( $drivername = $focusedRef.driverName )
#set( $driverdashboardurl = $focusedRef.driverDashboardUrl )
#set( $giftSelectionUrl = $focusedRef.giftSelectionUrl )
#set( $passengername = $focusedRef.passengerName )
#end
#if( !$custommessage.isEmpty() )
#define( $messageHTML )
<td align="center" vertical-align="middle" style="font-size:24px; font-style: italic; font-weight: 400; color: #184c6d; padding:15px;word-break:break-word;"><table cellpadding="15" cellspacing="0" border="0" role="presentation" style="background: #f8f8f8; max-width: 520px; width: 100%;"><tr><td>"${custommessage}" </br></br><span style="font-weight: 700; font-size: 18px;">${drivername}</span></br></br></td></tr></table></td>
#end
#else
#define( $messageHTML )
[]
#end
#end
#set( $referralURLNoHost = $referralURL.replaceAll("^https://", "") )
#set( $driveruniqueUrlNoHost = $driveruniqueUrl.replaceAll("^https://", "") )
#set( $driverdashboardurlNoHost = $driverdashboardurl.replaceAll("^https://", "") )
#set( $giftSelectionUrlNoHost = $giftSelectionUrl.replaceAll("^https://", "") )
Sanford, you are the greatest. I will take your advice and suggestions in consideration. I'm still learning Velocity, so this made me happy to see a very thorough reply.
Make sure you're following my blog posts, lots out there and more coming up.