I am trying to pass json data input to email script token from Marketo API invoked Email notification using tokens so that layout data in table format in Email Message Body. I know we can use lead/contact object attributes in addition to other objects like Oppurunity or Account but I have not seen example where we use one custom token ({{my.jasonData}}) into Email Script token so that Velocity script can be used to create html content that can be renderded. Any ideas/suggesstion if this possible and how to do it(with example)
Solved! Go to Solution.
@SanfordWhiteman After your below reply (Send VTL, including #set(), as the {{my.token}} value.), We got the idea that we can pass VTL (velocity template language) from API as token content along with data. By referring to your blog post , we were able to pass json data (see texttemplate variable below) from API itself with VTL included to parse and layout that json data. Here is how final request looks like
curl -X POST \
https://<munchkinid>.mktorest.com/rest/v1/campaigns/1025/trigger.json \
-H 'Accept: */*' \
-H 'Authorization: Bearer <token>' \
-H 'Cache-Control: no-cache' \
-H 'Connection: keep-alive' \
-H 'Content-Type: application/json' \
-H 'Host: <munchkin-id>.mktorest.com' \
-H 'Postman-Token: <postman-token>' \
-H 'User-Agent: PostmanRuntime/7.15.0' \
-H 'accept-encoding: gzip, deflate' \
-H 'cache-control: no-cache' \
-H 'content-length: 1591' \
-d '{
"input": {
"leads": [
{
"id": 2
}
],
"tokens": [
{
"name": "{{my.texttemplate}}",
"value": "<table border=1><tr><th>Email Id</th><th>Full Name</th><th>Date Referred</th><th>Referral Program</th></tr> #set($jsonString = '\''[{\"Email\" : \"joe@example.com\",\"FullName\" : \"Joe Exton\",\"DateReferred\" : \"2016-08-01\",\"ReferralProgram\" : \"Season Pass Holders\"},{\"Email\" : \"jill@example2.com\",\"FullName\" : \"Jill Towson\",\"DateReferred\" : \"2016-08-03\",\"ReferralProgram\" : \"Gold Donors\"}]'\'') #set( $jsonData = '\''#set( $jsonData = '\''+$jsonString+'\'')'\'') #evaluate($jsonData) #foreach($jdata in $jsonData)<tr><td >${jdata.Email}</td><td >${jdata.FullName}</td><td >${jdata.DateReferred}</td><td >${jdata.ReferralProgram}</td></tr> #end </table>"
},
{
"name": "{{my.order-number}}",
"value": "3023532055"
},
{
"name": "{{my.shipment-on-way}}",
"value": "Your order has shipped and is on it'\''s way!"
},
{
"name": "{{my.order-status}}",
"value": "Partially Shipped"
},
{
"name": "{{my.track-shipment}}",
"value": "9012412122"
},
{
"name": "{{my.shipping-method}}",
"value": "Standard (2-Day Guaranteed)"
},
{
"name": "{{my.packing-slip}}",
"value": "7569737098"
},
{
"name": "{{my.ship-to-account-number}}",
"value": "98746892"
},
{
"name": "{{my.ship-to-account-name}}",
"value": "chicago childcare hospital"
},
{
"name": "{{my.delivery-address}}",
"value": "121 s tonne dr, arlington heights, IL from postman"
}
]
}
}'
You can’t read another Text {{my.token}} as plain text from a Velocity {{my.token}}.
But you can write inline Velocity in a Text {{my.token}} — it cannot have any dependencies, that is, it can’t reference any lead or object fields — that #sets a variable in the context, then read that variable from a Velocity {{my.token}} located after it in the email.
@SanfordWhiteman we tried your suggestion but it seems to be giving error. Below screenshots shows that
1. first screenshot gives you error overview when you insert Velocity script directly inside your Email Html
2. Second screenshot is showing text token value that contains velocity script as you suggested.
3. Third screenshot is showing how we insert the text token (containing velocity script) in Email html code.
4. Fourth screenshot shows when you save the changes and error shows up in Email preview screen about inject text token with velocity script.
Hope below is clear. Let me know if there is any confusion. Thanks for you help.
I didn’t say anything about running #evaluate directly in email content. The error is not surprising because Marketo sees the formal reference as a ${mktoVariable} (which is no coincidence).
You can include Velocity in a Text {{my.token}} but of course the Velocity needs to be error-free. I couldn’t say, without analyzing the entirety of your code and approach, why you’re getting that lexical error.
@SanfordWhiteman Contents of text token are shown in screenshot. It is just setting velocity variable with simple constant string value. When we inject that text token, we see the error. When we remove the text token, We do not see the error. Is that not sufficient to conclude that issue is velocity script in text token. I am happy to email you html code if you have where I need to send the code.
Hi @sssingh ,
Based on what I've read above, I feel that if you simply change your "evaluate" line to output the variable instead:
#set($greeting = "Dear Mr. Dan")
$greeting
Then you can do what you are setting out to do. This worked in my testing - I created a text token which contained the full code above, and then placed that text token in the email as {{my.Test Greeting}}. When previewing the email as a specific person, it showed the results of the Velocity code.
So to expand upon this, you could update that plain text token with the Velocity code you want to run, and that will modify the email. But as Sanford mentioned, you can't use any variables related to the person in this way, so you are either:
1. Sending everyone the same content - which defaults the purpose, right? Or:
2. Updating the token via API, sending an email, and then updating the token before sending another email - so the personalisation is done every time the email is sent to anyone.
Overall, this is a bit of a hack, but it seems like @SanfordWhiteman 's solution might work for you.
Based on what I've read above, I feel that if you simply change your "evaluate" line to output the variable instead:#set($greeting = "Dear Mr. Dan") $greeting
Correct. There’s no need for #evaluate. The code is already compiled as code the first time, not just as text.
#set($greeting = "Dear Mr. Dan")
$greeting
#set($greeting = "Dear " + {first-name})
$greeting
first-name will be Mr. Dan from api call and its another text token we created (accessible by using {{my.first-name}} in the HTML).
Is this possible ?
Your question isn’t exactly clear, but Velocity in a Text {{my.token}}, not just in an Email Script {{my.token}}, will be compiled.
Of course one would not usually deliberately put Velocity in a Text {{my.token}}, because (a) it’s confusing and (b) it doesn’t allow you to export lead/oppty/CO fields into the context... but it can be useful when you’re updating using the API, since only one of the {{my.token}} types can be updated that way.
Not sure if there’s any other way to phrase the above, Phil and I have said it a few times already...
@SanfordWhiteman @Phillip_Wild Thank you for your replies. We are following you what you are saying. We are trying to implement the second use case ( Updating the token via API, sending an email, and then updating the token before sending another email - so the personalization is done every time the email is sent to anyone. ) described by phil. We are testing this scenario but it does not seems to be working for us.
Here is what we are doing
1. create custom token pname as shown below that will be used in text token {{my.texttemplate}}
2. Here is how my {{my.texttemplate}} is defined.
3. Currently we are only able to use send sample functionality to send email. Here is sample of email received when testing using send sample functionality in Marketo
4. When sending through API (using postman) client, we are receiving below error. We have already validated the html and it comes out as valid. API call comes back with success but when we check receiver person activity log, we see below mysterious error.
5. Here is API request through PostMan
curl --location --request POST 'https://<muchkin-number>.mktorest.com/rest/v1/campaigns/1025/trigger.json' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <accesstoken>' \
--data-raw '{
"input":
{
"leads" : [
{
"id" : 5
}
],
"tokens" : [
{
"name" : "order-number",
"value": "3023532055"
},
{
"name" : "pname",
"value": "Mr.Prudhvi"
},
{
"name" : "shipment-on-way",
"value": "Your order has shipped and is on it'\''s way!"
},
{
"name" : "order-status",
"value": "Partially Shipped"
},
{
"name" : "track-shipment",
"value": "9012412122"
},
{
"name" : "shipping-method",
"value": "Standard (2-Day Guaranteed)"
},
{
"name" : "packing-slip",
"value": "7569737098"
},
{
"name" : "ship-to-account-number",
"value": "98746892"
},
{
"name" : "ship-to-account-name",
"value": "chicago childcare "
},
{
"name" : "delivery-address",
"value": "121 s tonne dr, arlington heights, IL from postman"
}
]
}
}'
I will be opening support ticket to troubleshoot API error to see if we can find the root cause. FYI we are using sandbox environment for testing where we have full flexibility for testing.
I can't speak to the API call - sorry, that doesn't look like an error I'm familiar with.
On the subject line part, you are using the nomenclature ${my.pname}. This is a mixture of a Velocity variable name, and a Marketo token name.
Velocity variable names start with a dollar sign, as you have, and can optionally have brackets - eg. ${variable}, or simply $variable. Marketo token names have the double brackets, and "my" as a prefix - eg. {{my.variable}} .
In what you have in the subject line, you have mixed both of these - Velocity variable name, but with "my." in the middle as per Marketo tokens. That is likely why it isn't rendering correctly. Hope this helps.
@Phillip_Wild Sorry I should have included the Email Draft screenshot in previous reply for context. Below is how email draft looks like . As you can see in subject line, we are not including the velocity variable but email template text token which contains velocity script that has another my token {{my.pname}}. Hope this makes sense. I have also fixed the screenshot for {{my.texttemplate}} in previous reply. It was not showing {{my.pname}} as token part of velocity script variable that we were printing. Third screenshot is from mobile phone where I received the email which lays it out as ${m.pname}. I am not sure why it is doing that.
Hi @sssingh ,
Hmm. When you put that {{my.texttemplate}} token in the email body instead of the email subject line, does it work then?
I remember something I've read in the past that you shouldn't use an email script token for only PART of a subject line - it should output the full subject line. That might not be possible given you have other dynamic variables in there. But if you can get it to work in the email body, at least we have a cause.
@Phillip_Wild it is text token instead of email script token as suggested by @SanfordWhiteman earlier to in post to try instead of email script token. Here is screenshot with this text token in the body of the email which were delivered to my email id
Hi @SS
Your Payload needs to be updated for tokens as below (as mentioned by @SanfordWhiteman), you can add remaining fields in similar way to the payload:
{
"input": {
"leads": [
{
"id": 5
}
],
"tokens": [
{
"name": "{{my.order-number}}",
"value": "3023532055"
},
{
"name": "{{my.pname}}",
"value": "Mr.Prudhvi"
},
{
"name": "{{my.shipment-on-way}}",
"value": "Your order has shipped and is on it's way!"
},
{
"name": "{{my.order-status}}",
"value": "Partially Shipped"
}
]
}
}
Above should work fine, as I tested below:
Tokens in the program:
Tokens in email:
Hope above helps your cause.
Thanks
@SanfordWhiteman I am trying to understand your first point where you say "Your Request Campaign payload is wrong; JSON property names are like {{my.token)}". I am not able to understand. Can you please be more specific in API request payload where we are doing that ?
- understood your second point. Based on one of your previous reply in this post, you mentioned you can use velocity script in text token. I think we misunderstood your answer there. I have to say though that without being able to pass any type of data to velocity script , its usage will be very limited. Especially if that data is not associated with any objects that are supported in email script. As you can see we are trying to layout html tabular structure in the email body with order items details. We are passing those order items through API invocation. Order item count will vary from one API call to another. we will have to put some sort of loop construct to iterate over those items to create table html. Any idea how to handle such scenario in your previous experience?
wrong; JSON property names are like {{my.token)}". I am not able to understand. Can you please be more specific in API request payload where we are doing that ?- understood your second point.
Right here:
{
"name" : "order-number",
"value": "3023532055"
}
The syntax is actually:
{
"name" : "{{my.order-number}}",
"value": "3023532055"
}
I think we misunderstood your answer there. I have to say though that without being able to pass any type of data to velocity script
But I never said you couldn’t “pass any type of data.“
I said you couldn’t reference Lead, Custom Object, or Opportunity fields in the code that’s inside the text token, for the obvious reason that there’s no place to check off the fields that should be injected into the Velocity context. The Text {{my.token}} itself can contain locally set variables.
(In fact it’s more complex than the above, you can reference fields if they’re checked off in an earlier token, but you can’t if your Text {{my.token}} is the first token in the email.)
Thank you for the example. That made it very clear. I was hoping that you can answer my second question around accepting data through API call which can be dynamic nature and laying that out in email using velocity script. We will be editing email template html directly. I know you said that Text {{my.token}} itself can only contain locally set variables but that does not help
us with passing that data to this token which was passed through API invocation request payload. Lets say I am passing following data from API call
API payload token value with json string
{
"name":"{{my.json-data-token}}"
"value":"{
{"itemId":"123", "qty":"10", "unit":"box", "sku":"sku787"},
{"itemId":"124", "qty":"1", "unit":"case", "sku":"sku788"},
{"itemId":"125", "qty":"11", "unit":"box", "sku":"sku789"},
{"itemId":"126", "qty":"5", "unit":"single", "sku":"sku790"},
{"itemId":"127", "qty":"6", "unit":"box", "sku":"sku791"}
}"
}
Email Template Body Html Segment that parses json data and create table segment in the email template body
<table>
## parse data from json-data-token as array of objects, parse function is madeup for demonstration
# set $json-data-token-list = $util.parseJson({{my.json-data-token}})
## iterate over json-data-token passed through API call
#foreach( $item in $json-data-token-list )
## construct the html for table row and output that into email content
#set( $table_row_html = "<tr><td>"+ $item.itemId +"</td><td>"+ $item.qty +"</td><td>"+ $item.unit +"</td><td>"+ $item.sku +"</td></tr>")
$($table_row_html)
#end
</table>
Let me know if something like this can work. Above is just pseudo code and real code example. I just want to know feasibility of it before going down this path.
There’s no method $util.parseJson, don’t know where you’re getting this from.
It still seems like you don’t understand the approach.
Once again: do not send raw JSON as the {{my.token}} value.
Send VTL, including #set(), as the {{my.token}} value.
Thus as far as Velocity knows, you’re passing a #set statement that creates a LinkedHashMap (with nested LinkedHashMaps). You‘re not passing a JSON string (it is never parsed as JSON, even if it some of it looks like JSON),
If this still doesn’t make sense, you should wait for me to blog about it at greater length.
@SanfordWhiteman After your below reply (Send VTL, including #set(), as the {{my.token}} value.), We got the idea that we can pass VTL (velocity template language) from API as token content along with data. By referring to your blog post , we were able to pass json data (see texttemplate variable below) from API itself with VTL included to parse and layout that json data. Here is how final request looks like
curl -X POST \
https://<munchkinid>.mktorest.com/rest/v1/campaigns/1025/trigger.json \
-H 'Accept: */*' \
-H 'Authorization: Bearer <token>' \
-H 'Cache-Control: no-cache' \
-H 'Connection: keep-alive' \
-H 'Content-Type: application/json' \
-H 'Host: <munchkin-id>.mktorest.com' \
-H 'Postman-Token: <postman-token>' \
-H 'User-Agent: PostmanRuntime/7.15.0' \
-H 'accept-encoding: gzip, deflate' \
-H 'cache-control: no-cache' \
-H 'content-length: 1591' \
-d '{
"input": {
"leads": [
{
"id": 2
}
],
"tokens": [
{
"name": "{{my.texttemplate}}",
"value": "<table border=1><tr><th>Email Id</th><th>Full Name</th><th>Date Referred</th><th>Referral Program</th></tr> #set($jsonString = '\''[{\"Email\" : \"joe@example.com\",\"FullName\" : \"Joe Exton\",\"DateReferred\" : \"2016-08-01\",\"ReferralProgram\" : \"Season Pass Holders\"},{\"Email\" : \"jill@example2.com\",\"FullName\" : \"Jill Towson\",\"DateReferred\" : \"2016-08-03\",\"ReferralProgram\" : \"Gold Donors\"}]'\'') #set( $jsonData = '\''#set( $jsonData = '\''+$jsonString+'\'')'\'') #evaluate($jsonData) #foreach($jdata in $jsonData)<tr><td >${jdata.Email}</td><td >${jdata.FullName}</td><td >${jdata.DateReferred}</td><td >${jdata.ReferralProgram}</td></tr> #end </table>"
},
{
"name": "{{my.order-number}}",
"value": "3023532055"
},
{
"name": "{{my.shipment-on-way}}",
"value": "Your order has shipped and is on it'\''s way!"
},
{
"name": "{{my.order-status}}",
"value": "Partially Shipped"
},
{
"name": "{{my.track-shipment}}",
"value": "9012412122"
},
{
"name": "{{my.shipping-method}}",
"value": "Standard (2-Day Guaranteed)"
},
{
"name": "{{my.packing-slip}}",
"value": "7569737098"
},
{
"name": "{{my.ship-to-account-number}}",
"value": "98746892"
},
{
"name": "{{my.ship-to-account-name}}",
"value": "chicago childcare hospital"
},
{
"name": "{{my.delivery-address}}",
"value": "121 s tonne dr, arlington heights, IL from postman"
}
]
}
}'