Forum Discussion
Can Liquid be passed in Custom Event Properties?
Hey Braze Community!
I’m trying to set up a Canvas campaign to deliver personalized notifications to users over a time period. The Canvas is triggered by a custom event with a payload like this
[
{
"external_id": "78647",
"app_id": "a5a9dfc3-0511-42d4-a2c6-1759645e30a8",
"name": "Purchase Milestone Reached",
"time": "2025-01-08T20:08:23.480Z",
"properties": {
"body": "Congrats on your new purchase!",
"deepLink": "https://www..google.com",
"deliveryId": 12345,
"liquidBody": "Congrats on your new purchase. Call {% catalog_items Purchase_PushNotifications {{custom_attribute.${organizationId}}} %} {{ items[0].PN_name | default: 'your representative' }} for a free upgrade.",
"milestoneType": "upgrade",
"notificationType": "PREMIUM",
"templateId": 107,
"title": "✨ Congratulation!"
},
"_update_existing_only": false
}
]
I’ve set up a message step in the Canvas to send iOS and Android notifications. To handle the notification content dynamically, I’m using the following Liquid logic:
{% if canvas_entry_properties.${liquidBody} %}
{{ canvas_entry_properties.${liquidBody} }}
{% else %}
{{ canvas_entry_properties.${body} }}
{% endif %}
The idea is that if the liquidBody property exists in the event payload, the notification should use it as the content. Otherwise, it should fall back to the body property.
The Issue
The liquidBody property contains a dynamic Liquid template, but when the notification is sent, the template is rendered literally as a string rather than being dynamically evaluated and resolved. For example, placeholders like {% catalog_items ... %} are not being processed; they appear in the notification as-is.
My Question
Is it currently possible in Braze to pass dynamic Liquid templates (e.g., the liquidBody property) through an event payload and have them evaluated dynamically in the final push notification?
If not, is there another way to achieve this? My goal is to generate these templates dynamically outside of Braze and have them rendered properly within notifications. I’d appreciate any suggestions or guidance on whether this is achievable, or if there are alternative approaches that might work better!
Thanks in advance for your help!
- inespaisMentor
Hey devakone. Braze does not support processing Liquid inside custom event properties as dynamic templates, that's why it's being treated as a string. Braze processes Liquid at the message rendering level (inside messages or templates), and it doesn't automatically parse dynamic Liquid syntax inside event payloads.
In order to achieve what you described, it might be better to either:
1. Move Liquid processing to your backend so as to send the payload already pre-rendered. You'd need a process in the backend to build the message dynamically before sending the event to Braze. Since this will likely require some technical work maybe check with your devs/data team if they have different suggestions and what's doable.
1.a Alternatively, you could setup a Webhook campaign triggered by the event Purchase Milestone Reached that extracts the raw event properties > transforms them by enriching them with the dynamic content already within Braze (catalogs, attributes, etc) > re-send a new event to Braze with the updated payload that triggers your main canvas.
2. If the logic between using liquidBody vs body relies solely on the availability of catalog_items Purchase_PushNotifications {{custom_attribute.${organizationId}}} and {{ items[0].PN_name | default: 'your representative' }} and the "Congrats on your new purchase" is an always-on, you could maybe just use some liquid tags to build the message directly in the message template. But I'm guessing you also want that copy to be very dynamic (?) and this would make those 2 properties in the current payload of little use, so the first option might be ideal.{% catalog_items Purchase_PushNotifications {{custom_attribute.${organizationId}}} %} {% if canvas_entry_properties.${liquidBody} %} Congrats on your new purchase. Call {{ items[0].PN_name | default: 'your representative' }} for a free upgrade. {% else %} Congrats on your new purchase! {% endif %}
Sorry if above won't be the most helpful but it's what I can think of right now.
- Bhanu5150Collaborator
Your approach is passing a Liquid template (liquidBody) dynamically through the event payload, expecting Braze to evaluate it at runtime. However, Braze does not support nested Liquid evaluation—meaning if a Liquid template is stored as a string in a property (e.g., liquidBody), it will not be reprocessed dynamically when used inside another Liquid expression.
Instead of rendering the evaluated Liquid template, Braze treats it as a static string, which is why you're seeing the raw {% catalog_items ... %} appear in the notification rather than its resolved value.
Here are a few potential ways to solve this:- Move the Dynamic Processing Logic to Braze Itself (Recommended)
Since Braze does not support Liquid within Liquid, you can reconstruct the logic directly in Braze instead of passing a pre-formed Liquid template in liquidBody.
Updated Liquid Logic in Braze
Modify your Liquid logic to dynamically generate the content directly inside Braze using the event properties:
{% if canvas_entry_properties.milestoneType == "upgrade" %}
Call {% catalog_items Purchase_PushNotifications {{canvas_entry_properties.organizationId}} %}
{{ items[0].PN_name | default: 'your representative' }} for a free upgrade.
{% else %}
{{ canvas_entry_properties.body }}
{% endif %}Instead of passing a Liquid template in liquidBody, you pass structured event properties and let Braze generate the final message.
- Move the Dynamic Processing Logic to Braze Itself (Recommended)
Related Content
- 4 months ago
- 9 months ago