What You’ll Learn in This Module

Filters are Liquid’s tools for transforming data. In this module, you’ll learn every standard text filter available in Cast β€” the tools for changing capitalization, trimming whitespace, replacing or removing characters, adding text to the beginning or end of a value, cutting text short, counting characters, splitting strings into arrays, and providing safe fallbacks for missing data.

By the end of this module, you’ll be able to take any messy text value from a CRM and transform it into exactly the clean, formatted output your Cast narration needs.


What Is a Text Filter?

A filter is a small transformation you apply to a value using the pipe character (|). Text filters specifically work on strings β€” they take text in, change it somehow, and pass the changed text out.

Excel analogy: Text filters are Liquid’s equivalent of Excel’s text functions β€” UPPER(), LOWER(), TRIM(), SUBSTITUTE(), LEFT(), and so on. If you’ve ever cleaned up messy spreadsheet data with those functions, you already understand what text filters do. The only difference is the syntax: instead of =UPPER(A1), you write {{ value | upcase }}.

You can chain multiple filters together, and they execute left to right:


{{ value | filter1 | filter2 | filter3 }}

The original value flows into filter1, the result flows into filter2, and that result flows into filter3. What comes out the end is what the customer sees.

Why text filters matter in Cast

CRM data is messy. Company names arrive in ALL CAPS. Names have extra spaces. Fields contain characters you need to remove or replace. Text filters are how you take raw CRM data and make it presentation-ready β€” clean, properly formatted, and professional.


Quick Reference β€” All Standard Text Filters

Before diving into each filter, here’s the complete list for reference. Each one is explained in detail below.

Filter What It Does Input β†’ Output
upcase Convert to ALL CAPS "acme" β†’ "ACME"
downcase Convert to all lowercase "ACME" β†’ "acme"
capitalize Uppercase first letter only "acme corp" β†’ "Acme corp"
strip Remove leading/trailing spaces " acme " β†’ "acme"
replace Replace all occurrences of text "hello" \| replace: "l", "r" β†’ "herro"
remove Remove all occurrences of text "hello" \| remove: "l" β†’ "heo"
append Add text to the end "hello" \| append: "!" β†’ "hello!"
prepend Add text to the start "hello" \| prepend: "Say " β†’ "Say hello"
truncate Cut to n characters (adds ...) "hello world" \| truncate: 8 β†’ "hello..."
truncatewords Cut to n words (adds ...) "one two three" \| truncatewords: 2 β†’ "one two..."
size Count characters (or array items) "hello" \| size β†’ 5
split Split string into an array "a,b,c" \| split: "," β†’ ["a","b","c"]
default Fallback if nil or empty "" \| default: "N/A" β†’ "N/A"

Now let’s explore each one.


upcase β€” Convert to ALL CAPS

What is it?

The upcase filter converts every letter in a string to uppercase. Numbers, spaces, and punctuation are unaffected.

Excel analogy: Identical to =UPPER(A1).

Why it matters in Cast

Use upcase when you want to emphasize a word or ensure consistency in labels, headings, or status values that should always appear in capitals.

Liquid syntax


{{ "acme corp" | upcase }}       β†’ ACME CORP
{{ product_tier | upcase }}      β†’ ENTERPRISE (if product_tier is "Enterprise")

Real Cast example


Status: {{ product_tier | upcase }}

If product_tier is "Professional", output: Status: PROFESSIONAL

Common mistakes

❌ Using upcase on company names for display:


{{ contact_account_name | upcase }}    β†’ ACME LLC

This works, but most of the time you want title case, not ALL CAPS. Company names in all caps look like they’re shouting.

βœ… Use cast_titlecase for company names (Module 8):


{{ contact_account_name | cast_titlecase }}    β†’ Acme LLC


downcase β€” Convert to All Lowercase

What is it?

The downcase filter converts every letter to lowercase. The opposite of upcase.

Excel analogy: Identical to =LOWER(A1).

Why it matters in Cast

Use downcase when you need to normalize text for comparison. String comparisons in Liquid are case-sensitive β€” "Enterprise" does not equal "enterprise". Converting both sides to lowercase before comparing ensures you catch all variations.

Liquid syntax


{{ "ACME CORP" | downcase }}     β†’ acme corp
{{ contact_email | downcase }}   β†’ jason@acme.com

Real Cast example

Normalizing a value before comparison:


{%- assign tier = product_tier | downcase -%}
{% if tier == "enterprise" %}
  You have access to all premium features.
{% endif %}

This catches "Enterprise", "ENTERPRISE", "enterprise", and any other casing variation.

Common mistakes

❌ Case-sensitive comparison without normalizing:


{% if product_tier == "enterprise" %}

This fails if the CRM stores it as "Enterprise" or "ENTERPRISE".

βœ… Normalize with downcase first:


{%- assign tier = product_tier | downcase -%}
{% if tier == "enterprise" %}


capitalize β€” Uppercase First Letter Only

What is it?

The capitalize filter makes the first character of the string uppercase and leaves everything else exactly as it is. It does not capitalize the first letter of every word β€” only the very first character of the entire string.

Excel analogy: Similar to =PROPER(A1), but only for the first letter β€” not each word. There isn’t a perfect Excel equivalent; it’s more like =UPPER(LEFT(A1,1)) & MID(A1,2,LEN(A1)).

Why it matters in Cast

capitalize is useful for ensuring a sentence or label starts with a capital letter, especially when the value comes from a CRM field that might be all lowercase. However, it’s not the right tool for company names β€” for that, use cast_titlecase.

Liquid syntax


{{ "acme corp" | capitalize }}       β†’ Acme corp
{{ "hello world" | capitalize }}     β†’ Hello world
{{ "ACME CORP" | capitalize }}       β†’ ACME CORP  (only affects the first character)

Notice the critical detail: capitalize does NOT lowercase the rest of the string. If the input is "ACME CORP", the first character is already uppercase, so nothing changes.

Real Cast example


{%- assign status = account_status | downcase | capitalize -%}
Account status: {{ status }}

If account_status is "ACTIVE":

  • downcase β†’ "active"
  • capitalize β†’ "Active"

Output: Account status: Active

Common mistakes

❌ Expecting capitalize to title-case every word:


{{ "acme corp" | capitalize }}    β†’ "Acme corp"  (NOT "Acme Corp")

βœ… Use cast_titlecase for proper company name casing:


{{ "acme corp" | cast_titlecase }}    β†’ "Acme Corp"


❌ Using capitalize on ALL CAPS input expecting it to fix casing:


{{ "JOHN SMITH" | capitalize }}    β†’ "JOHN SMITH"  (unchanged!)

capitalize only uppercases the first character. It doesn’t lowercase anything.

βœ… Chain downcase first, then capitalize:


{{ "JOHN SMITH" | downcase | capitalize }}    β†’ "John smith"

(Still not ideal for names β€” but correct behavior for how these filters work.)


strip β€” Remove Leading and Trailing Whitespace

What is it?

The strip filter removes spaces, tabs, and newlines from the beginning and end of a string. It does not touch whitespace in the middle of the string.

Excel analogy: Identical to =TRIM(A1), which removes extra spaces from both ends of a cell value.

Why it matters in Cast

CRM data frequently arrives with invisible extra spaces β€” a name field might contain " Jason " or a snippet might return " yes ". These hidden spaces cause string comparisons to fail silently. strip is your first line of defense.

Liquid syntax


{{ "  hello world  " | strip }}      β†’ "hello world"
{{ "  Jason " | strip }}             β†’ "Jason"

Real Cast example

The most critical use of strip is when comparing snippet output:


{%- assign region = IsEMEA | strip -%}
{% if region == "yes" %}
  EMEA-specific content.
{% endif %}

Without | strip, if the snippet returns " yes" (with a leading space), the comparison " yes" == "yes" would be false, and the EMEA content would never appear. This is one of the most common silent bugs in Cast narrations.

Common mistakes

❌ Comparing snippet output without stripping first:


{% if IsEMEA == "yes" %}

If the snippet returns "yes " (with a trailing space), this comparison fails.

βœ… Always strip snippet output before comparing:


{%- assign region = IsEMEA | strip -%}
{% if region == "yes" %}


πŸ’‘ Make it a habit: Whenever you assign a snippet result to a variable for comparison, add | strip. It costs nothing and prevents an entire category of bugs.


replace β€” Find and Replace All Occurrences

What is it?

The replace filter finds every occurrence of one piece of text and replaces it with another. It works on the entire string and replaces all matches, not just the first one.

Excel analogy: Identical to =SUBSTITUTE(A1, "old", "new") β€” replaces all occurrences throughout the text.

Why it matters in Cast

Use replace to clean up CRM data β€” swap unwanted characters, fix formatting, or adapt text for different contexts.

Liquid syntax


{{ "hello world" | replace: "world", "there" }}      β†’ "hello there"
{{ "2024-01-15" | replace: "-", "/" }}                β†’ "2024/01/15"
{{ "$95,000" | replace: "$", "" | replace: ",", "" }} β†’ "95000"

The filter takes two arguments separated by a comma: the text to find and the text to replace it with. To remove text entirely, replace it with an empty string "".

Real Cast example

Cleaning a currency field before converting to a number:


{%- assign arr_raw = arr | default: "0" -%}
{%- assign arr_clean = arr_raw | replace: "$", "" | replace: ",", "" -%}
{%- assign arr_numeric = arr_clean | plus: 0 -%}

Your annual recurring revenue is ${{ arr_numeric }}.

If arr is "$250,000":

  • replace: "$", "" β†’ "250,000"
  • replace: ",", "" β†’ "250000"
  • plus: 0 β†’ 250000 (number)

Output: Your annual recurring revenue is $250000.

Common mistakes

❌ Forgetting that replace is case-sensitive:


{{ "Hello World" | replace: "hello", "hi" }}    β†’ "Hello World"  (no change!)

The lowercase "hello" doesn’t match the uppercase "Hello".

βœ… Match the exact casing, or normalize first:


{{ "Hello World" | downcase | replace: "hello", "hi" }}    β†’ "hi world"


❌ Forgetting the replacement argument:


{{ "hello" | replace: "l" }}    β†’ error or unexpected behavior

βœ… Always provide both arguments β€” use "" to delete:


{{ "hello" | replace: "l", "" }}    β†’ "heo"


remove β€” Delete All Occurrences

What is it?

The remove filter deletes every occurrence of the specified text from the string. It’s a shortcut for replace: "text", "".

Excel analogy: Like =SUBSTITUTE(A1, "text", "") β€” replacing something with nothing to delete it.

Why it matters in Cast

Use remove when you need to strip out unwanted characters β€” dollar signs, commas, special characters, or any text that shouldn’t appear in the output.

Liquid syntax


{{ "hello world" | remove: "world" }}      β†’ "hello "
{{ "$95,000" | remove: "$" | remove: "," }}  β†’ "95000"
{{ "Contact: Jason" | remove: "Contact: " }} β†’ "Jason"

Real Cast example

Cleaning a phone number for display:


{%- assign phone = contact_phone | default: "" -%}
{%- assign clean_phone = phone | remove: "(" | remove: ")" | remove: "-" | remove: " " -%}

{% if clean_phone != "" %}
  Phone on file: {{ contact_phone }}
{% endif %}

Here, remove cleans the phone number for validation purposes (checking if anything is actually there), while the original formatted version is displayed to the customer.

Common mistakes

❌ Using remove when you need replace:


{{ "2024-01-15" | remove: "-" }}    β†’ "20240115"

If you wanted slashes instead of hyphens, remove is the wrong tool.

βœ… Use replace when you need to substitute, not just delete:


{{ "2024-01-15" | replace: "-", "/" }}    β†’ "2024/01/15"


append β€” Add Text to the End

What is it?

The append filter adds a string to the end of the value. The original value stays the same; the new text is tacked on after it.

Excel analogy: Like =A1 & " Inc." β€” concatenating text onto the end of a cell value.

Why it matters in Cast

Use append to add units, suffixes, punctuation, or any trailing text to a value dynamically.

Liquid syntax


{{ "hello" | append: "!" }}           β†’ "hello!"
{{ "Acme" | append: " Inc." }}        β†’ "Acme Inc."
{{ score | append: " points" }}       β†’ "85 points"

Real Cast example


{%- assign pct = used | divided_by: reserved | times: 100 | round: 0 -%}
Your license utilization is {{ pct | append: "%" }}.

Output: Your license utilization is 75%.

πŸ’‘ In many cases, you can achieve the same result by putting the trailing text directly in the narration: Your utilization is {{ pct }}%. The append filter is most useful inside assign or capture blocks where you’re building up a value before using it later.

Common mistakes

❌ Using append to build text that should use capture:


{% assign msg = "" %}
{% assign msg = msg | append: "Hello " %}
{% assign msg = msg | append: name %}
{% assign msg = msg | append: ", welcome!" %}

This works, but it’s hard to read.

βœ… Use capture for complex text assembly:


{% capture msg %}Hello {{ name }}, welcome!{% endcapture %}


prepend β€” Add Text to the Start

What is it?

The prepend filter adds a string to the beginning of the value. The mirror image of append.

Excel analogy: Like ="Dear " & A1 β€” putting text before a cell value.

Why it matters in Cast

Use prepend to add prefixes, titles, or labels before a dynamic value.

Liquid syntax


{{ "hello" | prepend: "Say " }}          β†’ "Say hello"
{{ "Smith" | prepend: "Dr. " }}          β†’ "Dr. Smith"
{{ arr_numeric | prepend: "$" }}         β†’ "$250000"

Real Cast example


{%- assign arr_val = arr | default: 0 | plus: 0 -%}
{%- assign arr_display = arr_val | prepend: "$" -%}

Your current ARR is {{ arr_display }}.

Output: Your current ARR is $250000.


truncate β€” Cut Text to a Character Limit

What is it?

The truncate filter shortens a string to a specified number of characters. If the string is longer than the limit, it cuts off the excess and adds an ellipsis (...) by default. The character count includes the ellipsis characters.

Excel analogy: Similar to =LEFT(A1, 10), but with an automatic β€œβ€¦β€ added to show that text was cut.

Why it matters in Cast

Use truncate when you need to fit long text values β€” like company names, descriptions, or notes β€” into limited space on a slide or narration box.

Liquid syntax


{{ "hello world" | truncate: 8 }}              β†’ "hello..."
{{ "hello world" | truncate: 8, "…" }}         β†’ "hello…"
{{ "hello world" | truncate: 8, "" }}          β†’ "hello wo"
{{ "hello" | truncate: 10 }}                   β†’ "hello" (not truncated β€” under limit)

The second argument (optional) lets you customize the trailing text. Use "" for no trailing indicator at all.

Real Cast example


{%- assign company = contact_account_name | default: "your company" | cast_titlecase -%}

Slide header: {{ company | truncate: 25 }}

If the account name is "International Business Machines Corp":

  • After cast_titlecase: "International Business Machines Corp"
  • After truncate: 25: "International Business..." (25 characters including ...)

Common mistakes

❌ Forgetting that the ellipsis counts toward the character limit:


{{ "abcdefghij" | truncate: 5 }}    β†’ "ab..."  (NOT "abcde...")

The 5-character limit includes the 3 characters of ..., leaving room for only 2 characters of actual content.

βœ… Account for the ellipsis length when choosing your limit: If you want to show 10 characters of actual text plus ..., set the limit to 13:


{{ "abcdefghij" | truncate: 13 }}    β†’ "abcdefghij..."


truncatewords β€” Cut Text to a Word Limit

What is it?

The truncatewords filter shortens a string to a specified number of words (not characters) and adds an ellipsis. It cuts at word boundaries, so you never get a word chopped in half.

Excel analogy: No direct equivalent β€” but imagine a formula that counts spaces to find the nth word and cuts everything after it.

Why it matters in Cast

Use truncatewords when you want to preview a longer text field β€” like notes, descriptions, or feature lists β€” without worrying about cutting words in the middle.

Liquid syntax


{{ "one two three four five" | truncatewords: 3 }}       β†’ "one two three..."
{{ "one two three four five" | truncatewords: 3, "β€”" }}  β†’ "one two threeβ€”"
{{ "one two" | truncatewords: 5 }}                        β†’ "one two" (not truncated)

Real Cast example


{%- assign notes = private_notes | default: "No notes available." -%}
Summary: {{ notes | truncatewords: 15 }}

If private_notes is a long paragraph, only the first 15 words appear, followed by ....

Common mistakes

❌ Using truncate (characters) when you mean truncatewords (words):


{{ "Your account has been active for several years now" | truncate: 3 }}    β†’ "..."

truncate: 3 allows only 3 characters total β€” and the ... uses all three.

βœ… Use truncatewords when you want to cut by word count:


{{ "Your account has been active for several years now" | truncatewords: 3 }}
β†’ "Your account has..."


size β€” Count Characters or Items

What is it?

The size filter returns the number of characters in a string, or the number of items in an array. It doesn’t change the value β€” it produces a number.

Excel analogy: For strings, it’s identical to =LEN(A1). For arrays, it’s like =COUNTA(A1:A10).

Why it matters in Cast

Use size to check the length of a value before displaying it, to count items in a list, or to provide dynamic counts in narration text.

Liquid syntax


{{ "hello" | size }}                β†’ 5 (characters)
{{ "" | size }}                     β†’ 0
{{ "Analytics,Reporting" | split: "," | size }}    β†’ 2 (array items)

Real Cast example


{%- assign features = feature_list | split: "," -%}
You are currently using {{ features | size }} features.

{%- assign name = contact_first_name | default: "" -%}
{% if name | size > 0 %}
  Hi {{ name }},
{% else %}
  Hi there,
{% endif %}

⚠️ Note on using size in conditions: In some Liquid implementations, {% if name | size > 0 %} may not work as expected inside a tag. The safer pattern is to assign first:


{%- assign name = contact_first_name | default: "" -%}
{%- assign name_length = name | size -%}
{% if name_length > 0 %}
  Hi {{ name }},
{% else %}
  Hi there,
{% endif %}

Common mistakes

❌ Using size on nil without a default:


{{ contact_first_name | size }}

If the field is nil, this may error in strict mode.

βœ… Always provide a default before checking size:


{%- assign name = contact_first_name | default: "" -%}
{{ name | size }}


split β€” Turn a String into an Array

What is it?

The split filter breaks a string apart at every occurrence of a specified separator and produces an array (a list of items). This is how you convert a comma-separated text field from your CRM into individual items you can loop through, count, or access by position.

Excel analogy: Similar to the β€œText to Columns” feature in Excel, where you split a cell’s contents at each comma (or other delimiter) into separate cells.

Why it matters in Cast

Multi-value fields from CRMs β€” feature lists, product names, region lists, task lists β€” typically arrive as a single comma-separated string. Before you can loop through the items, check if a specific value is in the list, or count the items, you need to split the string into an array.

Liquid syntax


{% assign items = "a,b,c" | split: "," %}
{{ items | size }}     β†’ 3
{{ items | first }}    β†’ a
{{ items[1] }}         β†’ b

You can split on any separator β€” commas, semicolons, spaces, pipes, or any character sequence:


{% assign words = "hello world" | split: " " %}
{% assign parts = "one;two;three" | split: ";" %}
{% assign segments = "first||second||third" | split: "||" %}

Real Cast example


{%- assign features = feature_list | split: "," -%}

Your active features:
{% for feature in features limit: 5 %}
  {{ forloop.index }}. {{ feature | strip }}
{% endfor %}

{% if features.size > 5 %}
  ...and {{ features.size | minus: 5 }} more.
{% endif %}

If feature_list is "Analytics, Reporting, Alerts, Dashboards, API Access, Integrations, SSO":


Your active features:
  1. Analytics
  2. Reporting
  3. Alerts
  4. Dashboards
  5. API Access

  ...and 2 more.

πŸ’‘ Notice | strip inside the loop β€” when the source string has spaces after commas (like "Analytics, Reporting"), splitting on "," produces items with leading spaces (" Reporting"). The strip filter cleans each one.

Common mistakes

❌ Splitting on ", " (comma-space) when some items don’t have the space:


{% assign items = "a,b, c" | split: ", " %}
{{ items | size }}    β†’ 2  (only "c" got split off; "a,b" is one item)

βœ… Split on comma only, then strip each item:


{% assign items = "a,b, c" | split: "," %}
{% for item in items %}
  {{ item | strip }}
{% endfor %}


default β€” Safe Fallback for Missing Values

What is it?

The default filter provides a replacement value when the input is nil, false, or an empty string. If the input has an actual value, default does nothing and passes it through unchanged. It’s your primary safety net for missing CRM data.

Excel analogy: Similar to =IF(A1="", "N/A", A1) or the IFBLANK pattern β€” if the cell is empty, show a fallback; otherwise, show the cell’s value.

Why it matters in Cast

In Cast’s strict mode, displaying a nil variable causes an error. And even if it didn’t error, a blank space in the middle of a spoken narration sounds awkward. default ensures there’s always something meaningful in every position, no matter how incomplete the CRM data is.

Liquid syntax


{{ contact_first_name | default: "there" }}
{{ health_score | default: "not available" }}
{{ csm_name | default: "your account manager" }}

default triggers when the value is:

  • nil β€” the field doesn’t exist
  • empty string "" β€” the field exists but is blank
  • false β€” the boolean value false

default does NOT trigger when the value is:

  • any non-empty string β€” even "0" or " " (a single space)
  • any number β€” even 0

Real Cast example

A complete safe greeting pattern:


{%- assign name    = contact_first_name | default: "there" -%}
{%- assign company = contact_account_name | default: "your company" | cast_titlecase -%}
{%- assign csm     = csm_name | default: "your account manager" -%}
{%- assign score   = health_score | default: "N/A" -%}

Hi {{ name }},

Welcome to {{ company | cast_apostrophe }} review.
Your CSM, {{ csm }}, has prepared this overview.
Your current health score is {{ score }}.

Every variable has a natural-sounding fallback. The worst case β€” every field missing β€” still produces a coherent narration:


Hi there,

Welcome to Your Company's review.
Your CSM, your account manager, has prepared this overview.
Your current health score is N/A.

default with numeric conversion

When you need a numeric fallback, chain default before the number conversion:


{%- assign score = health_score | default: 0 | plus: 0 -%}

This reads as: β€œTake health_score. If it’s nil or empty, use 0. Then convert whatever we have to a number.”

⚠️ Order matters. If you reverse the chain:


{%- assign score = health_score | plus: 0 | default: 0 -%}

The plus: 0 runs first on a nil value, which may cause an error before default ever gets a chance to provide its fallback.

Common mistakes

❌ Relying on default to catch a single space " ":


{{ "  " | default: "fallback" }}    β†’ "  "  (NOT "fallback")

A string containing only spaces is technically not empty β€” it’s a string with space characters. default doesn’t trigger.

βœ… Use strip before default to catch whitespace-only values:


{{ "  " | strip | default: "fallback" }}    β†’ "fallback"

strip removes the spaces, producing "", which does trigger default.


❌ Forgetting default on a field used in arithmetic:


{%- assign score = health_score | plus: 0 -%}

If health_score is nil, this may error.

βœ… Always default before converting:


{%- assign score = health_score | default: 0 | plus: 0 -%}


Chaining Filters β€” The Power of Pipes

The real power of text filters comes from chaining them together. Each filter receives the output of the previous one, so you can build a multi-step transformation pipeline.

Here’s a realistic example β€” cleaning and formatting a company name:


{{ contact_account_name | default: "your company" | cast_titlecase | cast_apostrophe }}

Step by step:

  1. contact_account_name β†’ " ACME LLC " (raw CRM value with extra spaces)
  2. default: "your company" β†’ " ACME LLC " (not nil, so no change)
  3. cast_titlecase β†’ "Acme LLC" (proper casing β€” and cast_titlecase handles stripping internally)
  4. cast_apostrophe β†’ "Acme LLC's" (possessive added)

Another example β€” preparing a numeric value for display:


{{ arr | default: "0" | remove: "$" | remove: "," | plus: 0 }}

  1. arr β†’ "$250,000" (raw CRM value)
  2. default: "0" β†’ "$250,000" (not nil, so no change)
  3. remove: "$" β†’ "250,000"
  4. remove: "," β†’ "250000"
  5. plus: 0 β†’ 250000 (now a real number)

πŸ’‘ Reading filter chains: Always read left to right. Each pipe sends the current value to the next filter. If you’re ever confused about what’s happening, break the chain into separate assign steps:


{%- assign step1 = arr | default: "0" -%}
{%- assign step2 = step1 | remove: "$" -%}
{%- assign step3 = step2 | remove: "," -%}
{%- assign arr_numeric = step3 | plus: 0 -%}

This produces the same result but makes each transformation visible and easy to debug.


Putting It All Together β€” Common Cast Patterns with Text Filters

Pattern 1: Safe, clean greeting


{%- assign name = contact_first_name | default: "there" | strip -%}
Hi {{ name }},

Pattern 2: Normalized comparison


{%- assign tier = product_tier | default: "" | strip | downcase -%}
{% if tier == "enterprise" %}
  Enterprise content here.
{% endif %}

Pattern 3: Clean snippet comparison


{%- assign region = IsEMEA | strip -%}
{% if region == "yes" %}
  EMEA-specific content.
{% endif %}

Pattern 4: Formatted company name with possessive


{{ contact_account_name | default: "your company" | cast_titlecase | cast_apostrophe }}

Pattern 5: Truncated preview with item count


{%- assign features = feature_list | split: "," -%}
Top features ({{ features | size }} total):
{% for feature in features limit: 3 %}
  {{ forloop.index }}. {{ feature | strip }}
{% endfor %}

Pattern 6: Currency field cleanup


{%- assign arr_val = arr | default: "0" | remove: "$" | remove: "," | plus: 0 -%}


Try It Yourself β€” Module 4 Capstone Exercise

Exercise: You have the following CRM data:

  • contact_account_name = " JOHNSON & JOHNSON "
  • feature_list = "Advanced Analytics, Custom Reports, API Access, SSO, Data Export"
  • contact_first_name = nil (missing)

Write Liquid that produces this output:


Hi there,

Johnson & Johnson is using 5 features. Here are the top 3:
1. Advanced Analytics
2. Custom Reports
3. API Access

Hint: You’ll need default, strip, cast_titlecase, split, size, a for loop with limit, and strip inside the loop.

Click to reveal the answer ```liquid {%- assign name = contact_first_name | default: "there" -%} {%- assign company = contact_account_name | strip | cast_titlecase -%} {%- assign features = feature_list | split: "," -%} Hi {{ name }}, {{ company }} is using {{ features | size }} features. Here are the top 3: {% for feature in features limit: 3 -%} {{ forloop.index }}. {{ feature | strip }} {% endfor %} ``` Breakdown: - `default: "there"` provides the fallback for the missing name - `strip` removes the leading/trailing spaces from the account name before `cast_titlecase` processes it - `split: ","` turns the comma-separated string into an array - `features | size` counts the items (5) - `limit: 3` stops the loop after 3 iterations - `| strip` inside the loop removes the leading space from each feature name (e.g., `" Custom Reports"` β†’ `"Custom Reports"`)

What’s Next

You now have a complete toolkit for transforming text in Cast. In Module 5, you’ll learn the standard number filters β€” arithmetic, rounding, and the critical string-to-number conversion patterns that make comparisons and calculations work correctly.


πŸ“– Official documentation:

  • Standard Filters: https://school.cast.app/liquid/liquid-filters.html
  • Custom Cast Filters: https://school.cast.app/liquid/custom-cast-filters.html
  • Contact Variables: https://school.cast.app/fields-snippets-data-validation/contact-variables.html

This site uses Just the Docs, a documentation theme for Jekyll.