In-Browser Message campaigns support dynamic content personalization using Profile Variables and Liquid template syntax. Variables are resolved at runtime by RT Personalization 2.0 and rendered by the TD Web SDK before the message is displayed in the browser.
Profile variables available in In-Browser Messages come from four sources, all derived from the campaign's linked Parent Segment:
| Source | Prefix | Description |
|---|---|---|
| Batch Attributes | rt_profile.imported.* | User profile attributes computed from batch processing and imported into RT 2.0 as External (EXT) attributes — loyalty tier, lifetime value, name, and similar. Accessed via rt_profile.imported.* in Liquid syntax (for example, rt_profile.imported.loyalty_tier). |
| RT Single Attributes | rt_profile.single.* | Scalar values updated in real time based on streaming events — most recent product viewed, current session data, and similar. |
| RT List Attributes | rt_profile.list.* | Array values updated in real time — cart items, browsing history, and similar. |
| RT Counter Attributes | rt_profile.counter.* | Numeric counters updated in real time — visit count, purchase count, and similar. |
Referencing fields from the triggering event (for example, product_id from a page view) in Liquid template content is not supported.
Use double curly braces to output a variable value directly into content:
<p>Welcome back, {{rt_profile.imported.first_name}}!</p>
<p>Your current tier: {{rt_profile.imported.loyalty_tier}}</p>
<p>Most recent product viewed: {{rt_profile.single.most_recent_product}}</p>All {{ variable }} output is automatically HTML-escaped by RT 2.0 before it is delivered to the browser. Characters such as <, >, ", and & in attribute values are escaped, so user-controlled fields do not produce XSS even though the Liquid escape filter is not supported.
In-Browser Messages support a limited subset of Liquid template syntax. Templates are translated by Realtime API into Reactor-compatible JavaScript expressions at configuration time, then evaluated at runtime on each personalization request.
| Construct | Supported | Notes |
|---|---|---|
{% if %} / {% elsif %} / {% else %} / {% endif %} | ✅ | No nesting depth limit. |
{% for item in collection %} / {% endfor %} | ✅ | Maximum 3 nesting levels overall. |
{{ variable }} output | ✅ | Use rt_profile.* prefixes (for example, rt_profile.imported.*, rt_profile.single.*). |
== , != comparison | ✅ | String and null comparisons. |
and / or logical operators | ✅ | Combining multiple conditions. |
{% assign %} variable assignment | ❌ | Not supported. |
{{ value \| filter }} filters | ❌ | upcase, downcase, truncate, etc. are not supported. |
{% unless %} | ❌ | Use {% if condition == false %} as a workaround. |
{% case %} / {% when %} | ❌ | Use chained {% if %} / {% elsif %} as a workaround. |
contains operator | ❌ | Not supported in {% if %} conditions. |
forloop.index, limit, offset | ❌ | Loop metadata and parameters are not supported. |
| Liquid Syntax | Attribute Type |
|---|---|
{{rt_profile.imported.attribute_name}} | Batch attribute (accessed via rt_profile.imported.* in In-Browser Messaging) |
{{rt_profile.single.attribute_id}} | RT single attribute |
{{rt_profile.list.attribute_id.sub_attribute}} | RT list attribute sub-field |
{{rt_profile.counter.attribute_id.total}} | RT counter attribute total |
{% if rt_profile.imported.tier == "gold" %}
<p>20% off for Gold members!</p>
{% elsif rt_profile.imported.tier == "silver" %}
<p>10% off for Silver members!</p>
{% else %}
<p>Sign up today for exclusive deals!</p>
{% endif %}{% if rt_profile.list.cart_items.item_list != null %}
<h2>Your Cart</h2>
<ul>
{% for item in rt_profile.list.cart_items.item_list %}
<li>{{ item }}</li>
{% endfor %}
</ul>
{% endif %}{% if rt_profile.single.most_recent_product %}
<p>You recently viewed <strong>{{ rt_profile.single.most_recent_product }}</strong>.</p>
{% if rt_profile.list.recommendations.product_ids != null %}
<ul>
{% for product in rt_profile.list.recommendations.product_ids %}
{% if product != rt_profile.single.most_recent_product %}
<li>{{ product }}</li>
{% endif %}
{% endfor %}
</ul>
{% endif %}
{% endif %}- Unsupported Liquid filters: String manipulation filters (
upcase,downcase,replace,truncate,split,join,date, etc.) are not available. Pre-process values as batch attributes if transformation is needed. - No variable assignment:
{% assign %}is not supported. Use the attribute system in Audience Studio to derive computed values. - For loop nesting:
{% for %}loops support a maximum nesting depth of 3 levels. - No
{% unless %}: Use{% if condition == false %}instead.