Skip to content

Module 12: Logic — if / elsif / else

Conditional logic lets you say: “If this condition is true, show this content. Otherwise, show something different.” It’s the foundation of all personalized narrations — different health score ranges get different commentary, different product tiers get different feature mentions, different regions get different support information.

{% raw %}> Excel analogy: Conditional logic in Liquid is the equivalent of Excel’s =IF() function. {% if health_score > 80 %}Great!{% else %}Let's improve.{% endif %} works just like =IF(B1>80, "Great!", "Let's improve.") — except each branch can contain entire paragraphs, not just short text.{% endraw %}

A narration that says the same thing to a customer with a health score of 95 and one with a score of 40 isn’t personalized — it’s just a mail merge. Conditional logic is what turns data insertion into genuine, context-aware communication. One template can express empathy, celebration, urgency, or encouragement depending on the customer’s actual situation.


The simplest conditional: show something only when a condition is true.

{% raw %}
Content shown when condition is true.
{% endraw %}

{% raw %}Every {% if %} must have a matching {% endif %}. Think of them as matching parentheses.{% endraw %}

{% raw %}
{%- assign score = health_score | default: 0 | plus: 0 -%}
Congratulations — your account health is excellent!
{% endraw %}

If the score is 80 or above, the congratulations message appears. If it’s below 80, nothing is shown — the narration simply skips that section.


When you want one thing for “true” and a different thing for “false”:

{% raw %}
Content when true.
{% else %}
Content when false.
{% endraw %}
{% raw %}
{%- assign score = health_score | default: 0 | plus: 0 -%}
Your account is in great shape!
{% else %}
Let's talk about how we can help strengthen your account.
{% endraw %}

Every customer sees one message or the other — never both, never neither.


When you need more than two branches — three, four, or more tiers of content:

{% raw %}
Content for condition 1.
{% elsif condition_2 %}
Content for condition 2.
{% elsif condition_3 %}
Content for condition 3.
{% else %}
Fallback content (none of the above).
{% endraw %}

Liquid checks each condition from top to bottom and executes the first one that’s true. Once a match is found, the rest are skipped — even if later conditions would also be true.

Real Cast example — three-tier health score

Section titled “Real Cast example — three-tier health score”
{% raw %}
{%- assign score = health_score | default: 0 | plus: 0 -%}
Your health score of {{ health_score }} puts you in the top tier
of our customers. Keep up the great work!
{% elsif score >= 60 %}
Your health score of {{ health_score }} shows solid engagement
with room to grow. Here are some suggestions.
{% else %}
Your health score of {{ health_score }} tells us there are areas
we should focus on together. Let's schedule time to review.
{% endraw %}

Three different tones — celebratory, encouraging, and supportive — all from one template.

{% raw %}💡 Notice that we display the original {{ health_score }} string for readability, but we use the converted score variable for the comparisons. This is a common and recommended pattern.{% endraw %}


{% raw %}Here are all the operators you can use inside {% if %} conditions:{% endraw %}

Operator Meaning Example
{% raw %} == Equals
{% raw %} != Not equal
{% raw %} > Greater than
{% raw %} < Less than
{% raw %} >= Greater than or equal
{% raw %} <= Less than or equal
{% raw %} contains String/array contains value

contains works on both strings and arrays:

On a string — checks if the substring exists:

{% raw %}
You're emailing from your Acme corporate account.
{% endraw %}

On an array — checks if the item is in the list:

{% raw %}
{%- assign features = feature_list | split: "," -%}
You have access to Analytics.
{% endraw %}

⚠️ contains is case-sensitive. "analytics" does not match "Analytics".


You can combine multiple conditions with and (both must be true) or or (either can be true):

{% raw %}
You're a high-performing, high-value account.
You have access to advanced reporting.
{% endraw %}

⚠️ Important: Liquid evaluates and/or strictly left to right — there is no operator precedence (no “and before or” rule like in math). If you mix and and or, the results might surprise you:

{% raw %}
{% endraw %}

{% raw %}This evaluates as (a or b) and c, not a or (b and c). To be safe, avoid mixing and and or in a single condition. Use separate &#123;% if %&#125; blocks or restructure your logic.{% endraw %}

{% raw %}
{%- assign score = health_score | default: 0 | plus: 0 -%}
{%- assign arr_val = arr | default: 0 | plus: 0 -%}
As a top-tier, high-value account, you qualify for our Executive Partnership program.
{% elsif score >= 80 %}
Your account health is excellent. Let's discuss growth opportunities.
{% elsif arr_val > 100000 %}
As a high-value account, we want to make sure you're getting the most from the platform.
{% else %}
We've prepared some recommendations to help strengthen your outcomes.
{% endraw %}

As you learned in Module 2, snippets return strings. This means snippet output must be compared as a string, not a boolean:

Unreliable — comparing string to boolean:

{% raw %}
{% endraw %}

Correct — comparing string to string:

{% raw %}
{% endraw %}

Best practice — use the yes/no pattern:

{% raw %}
{%- assign region = IsEMEA | strip -%}
EMEA-specific content.
{% endraw %}

This rule applies to every snippet result used in an if condition.


Numeric Comparisons — Always Convert First

Section titled “Numeric Comparisons — Always Convert First”

The other critical rule: always convert string fields to numbers before using >, <, >=, <=:

Unreliable — string comparison on numeric data:

{% raw %}
{% endraw %}

Correct — convert, then compare:

{% raw %}
{%- assign arr_val = arr | default: 0 | plus: 0 -%}
{% endraw %}

You can put if blocks inside other if blocks for more complex logic:

{% raw %}
{%- assign score = health_score | default: 0 | plus: 0 -%}
{%- assign tier = product_tier | default: "" | strip -%}
Your account health is excellent!
As an Enterprise customer, you also have access to our advanced analytics suite.
{% else %}
Let's work together to improve your account health.
{% endraw %}

💡 Keep nesting shallow. One level of nesting is fine; two levels gets hard to read; three or more should be restructured. Use elsif or separate the logic into snippets instead of deeply nesting.


Use blank to test whether a value is nil or empty before using it:

{% raw %}
Your contract renews on {{ renewal_date | date: "%B %d, %Y" }}.
{% else %}
We don't have a renewal date on file for your account.
{% endraw %}

You can also combine blank checks with other conditions:

{% raw %}
Your CSM, {{ csm_name }}, has prepared this review.
{% else %}
This review has been prepared for you by the Customer Success team.
{% endraw %}

Forgetting endif:

{% raw %}
Great job!
{% else %}
Let's improve.
{% endraw %}

{% raw %}Missing &#123;% endif %&#125; causes an error.{% endraw %}

Every if needs an endif:

{% raw %}
Great job!
{% else %}
Let's improve.
{% endraw %}

Using = (assignment) instead of == (comparison):

{% raw %}
{% endraw %}

Single = is for assign, not comparison.

Use double equals for comparison:

{% raw %}
{% endraw %}

Checking elsif conditions that overlap with earlier ones:

{% raw %}
Good score.
{% elsif score > 80 %}
Excellent score!
{% endraw %}

A score of 85 matches > 60 first and never reaches the > 80 check.

Order from most specific to least specific:

{% raw %}
Excellent score!
{% elsif score >= 60 %}
Good score.
{% else %}
Needs improvement.
{% endraw %}

Exercise: Write a conditional block that handles four scenarios based on product_tier (a string from CRM):

  • “Enterprise” → “You have access to all features including advanced analytics.”
  • “Professional” → “You have access to core features and standard reporting.”
  • “Starter” → “You have access to essential features. Talk to your CSM about upgrading.”
  • Any other value → “Contact your CSM to explore available plans.”

Include proper default and strip handling.

Click to reveal the answer
{% raw %}
{%- assign tier = product_tier | default: "" | strip -%}
You have access to all features including advanced analytics.
{% elsif tier == "Professional" %}
You have access to core features and standard reporting.
{% elsif tier == "Starter" %}
You have access to essential features. Talk to your {{ "CSM" | cast_pronounce }} about upgrading.
{% else %}
Contact your {{ "CSM" | cast_pronounce }} to explore available plans.
{% endraw %}

Key details:

  • default: "" handles nil values
  • strip removes whitespace that might cause comparison failures
  • The else block catches any unexpected tier values (typos, new tiers not yet accounted for)
  • cast_pronounce on “CSM” as a bonus touch for professional audio

In Module 13, you’ll learn two more logic structures: unless (the inverse of if) and case/when (a cleaner way to handle multiple specific values).


📖 Official documentation: