Braze Liquid: Complete Guide
Quick Summary:
Liquid is Braze's templating language for dynamic personalization -- conditional logic, loops, and data formatting that go meaningfully beyond simple merge-field substitution.
What Is Liquid?
Liquid is the templating language Braze uses to power genuinely dynamic message personalization. Where a simple merge field inserts one stored value directly, Liquid supports conditional branching (showing different content based on user attributes), loops (iterating over list-type data like cart contents), and filters (transforming how a value displays) -- capability that turns a static template into something that adapts meaningfully to each individual recipient.
Common Liquid Use Cases
| Use Case | What Liquid Does |
|---|---|
| Conditional content | Show different message sections based on user attributes or segment |
| Loops over data | Generate repeated blocks for each item in a list (cart contents, recommendations) |
| Data formatting | Format dates, numbers, and currency for consistent display |
| Combined with Connected Content | Format and conditionally display live-fetched external data |
Simplified Liquid Conditional Example
{% if user.purchase_count > 5 %}
Thanks for being one of our best customers!
{% elsif user.purchase_count > 0 %}
Welcome back -- here's something new.
{% else %}
Check out what's popular right now.
{% endif %}Liquid and the Broader Braze Personalization Stack
Liquid rarely works in isolation -- its real power shows up combined with Braze's other data capabilities. Connected Content or a Catalog fetches the raw data (live external data or stored reference data, respectively), and Liquid logic then formats, filters, and conditionally displays that data within the actual message. A product recommendation email, for instance, might use a Catalog to source product data and a Liquid loop to generate a repeated block for each recommended item, with conditional logic hiding out-of-stock items entirely.
⚠️ Test Liquid Logic Thoroughly Before Live Sends
A Liquid error -- referencing an undefined variable, a malformed conditional -- can result in blank content, broken formatting, or in some cases blocked sends. Given how central Liquid often becomes to a message's actual content, testing with realistic sample data before a live send is genuinely important, not an optional nicety.
Common Liquid Patterns Worth Knowing
Null/blank checking: Before referencing a user attribute that might not exist for every user, wrapping it in a check (like verifying it's not blank) prevents a missing data point from breaking the entire message rather than just that one section.
Default value fallbacks: Providing a sensible default when a personalization value is missing (like "there" instead of a blank space where a first name would go) keeps messages feeling polished even for incomplete profiles.
Nested conditionals for genuinely complex logic: Multiple layers of if/else logic can express more sophisticated business rules (like different messaging for new vs. returning vs. lapsed customers), though nesting too deeply makes templates genuinely hard to read and maintain -- there's a real tradeoff between sophistication and maintainability worth being deliberate about.
Combining loops with conditionals: Iterating over a list while also filtering which items actually display (like showing only in-stock items from a cart) combines both capabilities for genuinely useful, real-world personalization logic.
Debugging Liquid Issues
When Liquid-driven content doesn't render as expected, a few common culprits are worth checking first.
Syntax errors: Missing or mismatched tags (an unclosed if statement, a typo in a filter name) are the most common source of broken rendering -- careful attention to matching opening and closing tags resolves a large share of issues.
Data type mismatches: Comparing a number to a string, or applying a text filter to numeric data, can produce unexpected results -- confirming the actual data type of the attribute or event property being referenced avoids this category of error.
Missing data for test users: A template that references an attribute your test user doesn't have populated may render differently than it will for real users with complete profiles -- testing with genuinely representative sample data, not just whatever test account happens to be convenient, catches this before it reaches production.
How to Get Started
Start with simple conditional logic (showing/hiding content based on a segment or attribute) before attempting more complex expressions.
Use Braze's preview tools to test how Liquid renders for different sample users before committing to a live send.
Combine Liquid with Connected Content or Catalogs for genuinely dynamic, data-driven personalization.
Build defensive logic (like checking whether a variable exists before referencing it) to avoid broken content from missing data.
Document more complex Liquid templates for your team, since intricate nested logic can be genuinely hard to parse months later without context.
A Real-World Example
A retail brand's post-purchase email needs to show different content depending on whether the customer bought one item or multiple, and needs to list every item purchased with its specific details. A Liquid loop iterates over the order's line items, generating a repeated content block for each one, while a conditional check adjusts the email's opening message depending on order size -- a single template genuinely adapting to each specific order, rather than requiring separate templates for every possible order composition.
The same brand later extends this template to conditionally recommend a complementary product based on what was purchased, using Liquid logic referencing product category data from a Catalog. A customer who bought running shoes sees a recommendation for athletic socks; a customer who bought a dress shirt sees a tie recommendation instead -- genuinely relevant cross-sell logic driven entirely by template conditionals rather than requiring separate campaigns built for every possible product combination.
💡 Pro Tip
Keep a library of tested, reusable Liquid snippets for common patterns (formatting currency, checking for null values, standard conditional structures) rather than rebuilding the same logic from scratch in every new template -- this both saves time and reduces the chance of reintroducing a bug that was already solved once, especially valuable as your team and template library grows.
Frequently Asked Questions
What is Liquid, in the context of Braze?
Liquid is the templating language Braze uses for dynamic personalization within messages -- conditional logic, loops, and variable insertion that go meaningfully beyond simple merge-field substitution.
Is Liquid unique to Braze, or used elsewhere?
Liquid was originally developed by Shopify and is used across several platforms; Braze adopted it as its personalization language, along with some Braze-specific extensions and functions on top of standard Liquid.
What\'s the difference between a simple merge field and a Liquid expression?
A merge field inserts a single stored value (like a first name) directly; Liquid supports conditional logic (if/else branching), loops (iterating over a list of items), and filters (transforming a value), enabling genuinely dynamic content beyond simple substitution.
Can Liquid be used to conditionally show or hide content based on user attributes?
Yes, this is one of the most common Liquid use cases -- showing different message content depending on a user's segment, purchase history, or any other tracked attribute.
Does Liquid work across all Braze channels, or just email?
Liquid is available across Braze's messaging channels including email, push, SMS, and in-app messages/Content Cards, not restricted to a single channel.
Can Liquid combine with Connected Content and Catalogs?
Yes, this is a genuinely powerful combination -- Connected Content or Catalog queries fetch the raw data, and Liquid logic formats, filters, and conditionally displays that data within the message.
What happens if a Liquid expression has an error, like referencing an undefined variable?
Depending on the specific error, Braze may render a blank value, skip the affected section, or in some cases prevent the message from sending -- testing Liquid logic thoroughly before a live send is genuinely important to avoid broken content reaching users.
Can Liquid loops iterate over a list, like multiple items in a cart?
Yes, Liquid's for-loop syntax can iterate over array-type data (like cart contents or a list of recommended products), generating repeated content blocks for each item.
Is coding experience required to use Liquid effectively?
Basic Liquid (simple conditionals, variable insertion) is approachable without deep programming background, but more sophisticated logic (nested conditionals, complex filters) benefits from genuine familiarity with programming concepts.
Can Liquid be used to format dates, numbers, or currency for display?
Yes, Liquid includes built-in filters for common formatting needs -- date formatting, number formatting, currency display -- avoiding the need for pre-formatted data just for display purposes.
How do I test Liquid logic before sending to a live audience?
Braze provides preview and testing tools that let you see how Liquid-driven content renders for specific test users or sample data before committing to a live send.
Can Liquid reference custom events, not just standard user attributes?
Yes, custom event data (and its associated properties) can be referenced within Liquid logic, letting message content adapt based on genuinely custom, business-specific behavioral data.
Can Liquid variables be reused across multiple sections of a long email template?
Yes, once a value is captured into a variable, it can be referenced repeatedly throughout the same template without needing to re-fetch or redefine it each time.
Does Braze provide a library of pre-built Liquid filters, or must all logic be written from scratch?
Braze provides a set of built-in filters for common needs (date formatting, string manipulation, math operations), reducing how much genuinely custom logic needs to be written for standard formatting tasks.
Related Articles