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:
- The standard way to #evaluate VTL uses escapes. Some eval methods work in Marketo's Velocity but not in a vanilla Velocity install. You should work with the more standard way (as you'll see in my code below). Keep aware that Velocity doesn't actually support all valid JSON. It's a (very happy) coincidence that VTL Map, List, String, and Number literals look almost exactly like JavaScript Object, Array, String, and Number literals, but there are still pitfalls. Look out for my upcoming blog post on "untreated" JSON -- that is, JSON that hasn't been generated with Velocity in mind.
- When working with URLs, remember that some sequences may appear (unencoded) in different parts of a URL. Countless code snippets out there (mostly in JS) are broken because they aren't based on the URL RFC -- even if you're "sure" your URLs look a certain way, parse them per the standard. If you want to strip off the protocol, you must anchor your search to the beginning of the URL, i.e. using a regex.
- Single quotes and double quotes behave differently in Velocity, variables inside single quotes are not substituted
- As for the default logic, what you have will work, but I don't like to rely on the accessing-null-property-is-a-noop behavior. Instead, set up a default data block and merge into those defaults. That is, set your default values (so no property is ever missing) and then putAll the live values on top of those.
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://", "") )