Dynamic Content
Bird Email Template Language Documentation
Introduction
The Bird Email Template Language is a powerful tool based on Shopify's Liquid syntax, with custom extensions designed specifically for email marketing. This language allows you to create dynamic, personalized email templates efficiently, enabling you to deliver targeted content to your subscribers.
Key features of the Bird Email Template Language include:
- Easy personalization using predefined variables
- Conditional content display based on subscriber attributes or segments
- Integration with your product catalog and external data sources
- Support for internationalization through translations
- Advanced formatting options with filters
This guide will walk you through the essential components of the language, providing examples and best practices to help you create effective email templates.
For a comprehensive reference on the underlying Liquid syntax, please refer to the Shopify Liquid documentation.
Predefined Variables
Predefined variables allow you to easily personalize your emails with recipient information and organization details.
Contact Variables
Use these to insert recipient-specific information into your emails:
代码示例
{{ contact.attributes.firstName }}
{{ contact.attributes.lastName }}
{{ contact.attributes.email }}You can also use any custom attributes that you've defined for your contacts.
Organization Variables
Include your company information consistently across all emails:
代码示例
{{ organization.name }}
{{ organization.fullAddress }}
{{ organization.websiteUrl }}
{{ organization.street }}
{{ organization.city }}
{{ organization.state }}
{{ organization.country }}
{{ organization.zipCode }}Other Variables
| Namespace | Variables |
|---|---|
| Template | {{ template.name }}, {{ template.versionId }}, {{ template.projectId }} |
| Message | {{ message.id }} |
| Campaign | {{ campaign.id }}, {{ campaign.name }} |
| Journey | {{ journey.id }}, {{ journey.name }}, {{ journey.runID }} |
Email Address Variable
Reference the recipient's email address directly:
代码示例
{{ emailAddress }}Best Practice: Always have a fallback for personalization variables in case they're not set for a particular recipient.
Special Tags
Special tags provide quick access to common email marketing requirements, such as unsubscribe links and web views.
Unsubscribe Links
Essential for compliance with email regulations:
代码示例
{% unsubscribe %} <!-- Outputs: <a href="...">Unsubscribe</a> -->
{% unsubscribe 'Click here to unsubscribe' %} <!-- Custom text -->
<a href="{% unsubscribeLink %}">Manage your preferences</a> <!-- Custom HTML -->Web View Links
Provide an option to view the email in a web browser:
代码示例
{% webView %} <!-- Outputs: <a href="...">View in browser</a> -->
{% webView 'View this email online' %} <!-- Custom text -->
<a href="{% webViewLink %}">Trouble viewing? Click here</a> <!-- Custom HTML -->Date Tags
Useful for displaying current dates in your emails:
代码示例
Today's Date: {% currentYear %}-{% currentMonthName %}-{% currentDay %}
Sent on: {% currentWeekday %}Best Practice: Always include an unsubscribe link in your emails, typically in the footer.
Control Flow
Conditional logic and loops allow you to create dynamic content that adapts to each recipient's attributes or preferences.
If Statements
Use if statements to show different content based on recipient attributes:
代码示例
{% if contact.attributes.membership == "gold" %}
<h2>Exclusive Gold Member Offer</h2>
<p>Enjoy 20% off your next purchase!</p>
{% elsif contact.attributes.membership == "silver" %}
<h2>Special Silver Member Discount</h2>
<p>Get 15% off select items!</p>
{% else %}
<h2>Limited Time Offer</h2>
<p>Save 10% on your next order!</p>
{% endif %}Checking Segment Membership
Target content to specific segments of your audience:
代码示例
{% if contact.segments contains "abcd-1234-efgh-5678" }
This contact is a member of the segment with ID "abcd-1234-efgh-5678".
{% endif %}Case Statements
代码示例
{% case shipping_method %}
{% when 'ground' %}
Estimated delivery: 5-7 business days
{% when 'express' %}
Estimated delivery: 2-3 business days
{% else %}
Please contact us for shipping information
{% endcase %}Loops
Iterate over arrays of data to create dynamic lists:
代码示例
<h3>Your Favorite Colors:</h3>
<ul>
{% for color in contact.attributes.favoriteColors %}
<li style="color: {{ color }};">{{ color }}</li>
{% endfor %}
</ul>Best Practice: Use conditional logic to tailor your message to different audience segments, increasing relevance and engagement.
Working with Products
Integrate your product catalog directly into your email templates for dynamic product displays.
Single Product Lookup
Display details of a specific product:
代码示例
{% catalog 'PRODUCT-ID-123' %}
<div class="product">
<h2>{{ catalogItem.title }}</h2>
<img src="{{ catalogItem.imageUrl }}" alt="{{ catalogItem.title }}">
<p>Price: {{ catalogItem.price | currencyFormat: catalogItem.currency }}</p>
{% if catalogItem.originalPrice > catalogItem.price %}
<p>Original Price: <strike>{{ catalogItem.originalPrice | currencyFormat: catalogItem.currency }}</strike></p>
{% endif %}
<a href="{{ catalogItem.url }}">Shop Now</a>
</div>
{% endcatalog %}Product Feed
Display multiple products from a feed:
代码示例
<h2>Recommended for You</h2>
<div class="product-grid">
{% productfeed 'FEED-ID-456' %}
{% for item in catalogItems limit:3 %}
<div class="product">
<h3>{{ item.title }}</h3>
<img src="{{ item.imageUrl }}" alt="{{ item.title }}">
<p>{{ item.price | currencyFormat: item.currency }}</p>
<a href="{{ item.url }}">View Product</a>
</div>
{% endfor %}
{% endproductfeed %}
</div>Best Practice: Use product feeds to create dynamic content like "Recommended Products" or "New Arrivals" sections in your emails.
Events
Leverage event data to create highly relevant, timely emails based on subscriber actions.
代码示例
{% if event.type == "abandoned_cart" %}
<h2>Did you forget something?</h2>
<p>We noticed you left some items in your cart:</p>
<ul>
{% for item in event.properties.items %}
<li>{{ item.product_name }} - {{ item.price | currencyFormat: event.properties.currency }}</li>
{% endfor %}
</ul>
<a href="{{ event.properties.checkout_url }}">Complete your purchase</a>
{% elsif event.type == "purchase_confirmation" %}
<h2>Thank you for your purchase!</h2>
<p>Order Total: {{ event.properties.total_price | currencyFormat: event.properties.currency }}</p>
<p>Order ID: {{ event.properties.order_id }}</p>
{% endif %}Best Practice: Use event data to trigger timely, relevant emails such as abandoned cart reminders or purchase confirmations.
Discount Codes
Generate and display unique discount codes in your emails to incentivize purchases.
代码示例
<h2>Your Exclusive Offer</h2>
<p>Use this code for 15% off your next purchase:</p>
<div class="discount-code">{% discountCode "SUMMER_SALE_POOL" %}</div>Best Practice: Use unique discount codes to track the performance of different email campaigns or segments.
Reusing discounts
If you'd like to reuse discounts previously sent to a contact instead of assigning a new discount on each send, pass the reuse named parameter.
代码示例
<h2>Your Exclusive Offer</h2>
<p>Use this code for 15% off your next purchase:</p>
<div class="discount-code">{% discountCode "SUMMER_SALE_POOL", reuse: true %}</div>This will cause the latest assigned discount for the contact to be rendered, or a fresh discount if none was previously assigned.
Translations
Create multilingual email templates using the translation feature.
First, set up your translation files (in JSON format) for each language you support. For example:
代码示例
{
"welcome_message": "Welcome to our store!",
"sale_announcement": "Don't miss our big sale, {{name}}!",
"product_of_the_day": "Product of the day: {{product}}"
}Then use the t filter in your templates:
代码示例
<h1>{{ "welcome_message" | t }}</h1>
<p>{{ "sale_announcement" | t: "name", contact.attributes.firstName }}</p>
<h2>{{ "product_of_the_day" | t: "product", featuredProduct.title }}</h2>Best Practice: Use translations to create a single template that can be used for multiple languages, reducing maintenance overhead.
External Data Sources
Integrate real-time data from external sources into your emails. You can learn more about external data sources here.
Basic Usage
代码示例
{% datafetch "weather-api" %}
<p>Current temperature in your area: {{ dataFetchResponse.temperature }}°C</p>
<p>Weather condition: {{ dataFetchResponse.condition }}</p>
{% enddatafetch %}Using Dynamic URLs
For APIs that require dynamic parameters:
代码示例
{% datafetch "user-recommendations", "userId", contact.attributes.userId %}
<h2>Recommended for You</h2>
<ul>
{% for product in dataFetchResponse.recommendations %}
<li>{{ product.name }} - {{ product.price | currencyFormat: 'USD' }}</li>
{% endfor %}
</ul>
{% enddatafetch %}Best Practice: Use external data sources to include up-to-date, personalized information in your emails, such as account balances, loyalty points, or personalized recommendations.
Supported Liquid Filters
Text Formatting
Filter: capitalize
Capitalizes the first letter of a string.
代码示例
{{ "hello world" | capitalize }}
{{ user.name | capitalize }}Filter: upcase
Converts string to uppercase.
代码示例
{{ "hello world" | upcase }}
{{ product.category | upcase }}Filter: downcase
Converts string to lowercase.
代码示例
{{ "HELLO WORLD" | downcase }}
{{ user.email | downcase }}Filter: strip
Removes leading and trailing whitespace from strings.
代码示例
{{ " hello world " | strip }}
{{ user_input | strip }}Filter: lstrip
Removes leading (left) whitespace from strings.
代码示例
{{ " hello world " | lstrip }}
{{ user_input | lstrip }}Filter: rstrip
Removes trailing (right) whitespace from strings.
代码示例
{{ " hello world " | rstrip }}
{{ user_input | rstrip }}Filter: append
Appends text to the end of a string.
代码示例
{{ "Hello" | append: " World!" }}
{{ filename | append: ".txt" }}Filter: prepend
Prepends text to the beginning of a string.
代码示例
{{ "World" | prepend: "Hello " }}
{{ filename | prepend: "backup_" }}Filter: replace
Replaces all occurrences of a substring.
代码示例
{{ "Hello World" | replace: "World", "Universe" }}
{{ content | replace: "\n", "<br>" }}Filter: replace_first
Replaces only the first occurrence of a substring.
代码示例
{{ "Hello World World" | replace_first: "World", "Universe" }}
{{ text | replace_first: " ", " " }}Filter: remove
Removes all occurrences of a substring.
代码示例
{{ "Hello World" | remove: "World" }}
{{ phone | remove: "-" }}Filter: remove_first
Removes only the first occurrence of a substring.
代码示例
{{ "Hello World World" | remove_first: "World" }}
{{ text | remove_first: " " }}Filter: slice
Extracts a substring starting at a position with optional length.
代码示例
{{ "Hello World" | slice: 0, 5 }}
{{ product.sku | slice: 0, 3 }}Filter: truncate
Truncates a string to a specified length, adding "..." if truncated.
代码示例
{{ product.description | truncate: 100 }}
{{ title | truncate: 50, "..." }}Filter: truncatewords
Truncates a string to a specified number of words.
代码示例
{{ article.content | truncatewords: 20 }}
{{ description | truncatewords: 10, "..." }}Filter: escape
Escapes HTML characters in strings.
代码示例
{{ user_content | escape }}
{{ "<script>" | escape }}Filter: escape_once
Escapes HTML characters, but doesn't double-escape already escaped characters.
代码示例
{{ mixed_content | escape_once }}
{{ "<div>" | escape_once }}Filter: strip_html
Removes HTML tags from strings.
代码示例
{{ "<p>Hello <strong>World</strong></p>" | strip_html }}
{{ product.description | strip_html }}Filter: strip_newlines
Removes newline characters from strings.
代码示例
{{ multiline_text | strip_newlines }}
{{ content | strip_newlines }}Filter: newline_to_br
Converts newline characters to HTML <br /> tags.
代码示例
{{ multiline_text | newline_to_br }}
{{ comment.body | newline_to_br }}Filter: url_encode
URL-encodes strings for safe use in URLs.
代码示例
{{ search_query | url_encode }}
{{ "hello world" | url_encode }}Filter: url_decode
URL-decodes strings.
代码示例
{{ encoded_param | url_decode }}
{{ "hello%20world" | url_decode }}Filter: titleCase
Converts text to title case, lowercasing small words.
代码示例
{{ "wAr aNd pEaCe HTML" | titleCase }}
{{ contact.firstName | titleCase }}Filter: titleCaseKeepAllCaps
Converts text to title case while preserving fully uppercase words.
代码示例
{{ "wAr aNd pEaCe HTML" | titleCaseKeepAllCaps }}
{{ "API documentation guide" | titleCaseKeepAllCaps }}Arrays and Collections
Filter: join
Joins array elements with a separator.
代码示例
{{ tags | join: ", " }}
{{ product.categories | join: " | " }}Filter: split
Splits strings into arrays using a delimiter.
代码示例
{{ "apple,banana,cherry" | split: "," }}
{{ user.full_name | split: " " }}Filter: size
Returns the size of strings or arrays.
代码示例
{{ "hello" | size }}
{{ products | size }}Filter: first
Gets the first element of an array.
代码示例
{{ products | first }}
{{ tags | first }}Filter: last
Gets the last element of an array.
代码示例
{{ products | last }}
{{ user.addresses | last }}Filter: where
Filters arrays by property values.
代码示例
{% assign clothingProducts = products | where: 'type', 'clothing' %}
{% assign availableProducts = products | where: 'available' %}
{% assign discountedProducts = products | where: 'discount' %}Filter: sort
Sorts arrays in ascending order.
代码示例
{{ tags | sort }}
{{ products | sort: 'price' }}Filter: sort_natural
Performs natural sorting (handles numbers in strings properly).
代码示例
{{ filenames | sort_natural }}
{{ versions | sort_natural }}Filter: reverse
Reverses the order of array elements.
代码示例
{{ products | reverse }}
{{ tags | sort | reverse }}Filter: uniq
Removes duplicate elements from arrays.
代码示例
{{ categories | uniq }}
{{ tags | uniq | sort }}Filter: compact
Removes nil/null items from arrays.
代码示例
{{ addresses | compact }}
{{ product.variants | compact }}Filter: concat
Combines two arrays into one.
代码示例
{{ array1 | concat: array2 }}
{{ featured_products | concat: regular_products }}Filter: map
Extracts a specific property from each array element.
代码示例
{{ products | map: 'title' }}
{{ users | map: 'email' }}Default Values
Filter: default
Provides default values for nil/empty variables.
代码示例
{{ product.description | default: "No description available" }}
{{ user.avatar | default: "/images/default-avatar.png" }}Currency Formatting
Filter: currencyFormat
Formats currency values with locale-specific formatting.
代码示例
{{ "100.00" | currencyFormat: "EUR", "nl-NL" }}
{{ product.price | currencyFormat: "USD" }}
{{ amount | currencyFormat: "EUR", "es-ES" }}Best Practice: Use the currencyFormat filter for all price displays to ensure consistency and proper formatting across different regions.
Filter: moneyWithoutCurrency
Formats numbers as currency without currency symbols, with custom separators.
代码示例
{{ 1234567890.98 | moneyWithoutCurrency: 2, ',', '.' }}
{{ product.price | moneyWithoutCurrency: 0, ',', '.' }}
{{ "1234.56" | moneyWithoutCurrency: 2, '', '.' }}Math & Numbers
Filter: abs
Returns the absolute value of a number.
代码示例
{{ -5 | abs }}
{{ product.discount | abs }}Filter: ceil
Rounds a number up to the nearest integer.
代码示例
{{ 4.2 | ceil }}
{{ price | divided_by: 3 | ceil }}Filter: floor
Rounds a number down to the nearest integer.
代码示例
{{ 4.8 | floor }}
{{ total | divided_by: count | floor }}Filter: round
Rounds a number to the nearest integer or specified decimal places.
代码示例
{{ 4.6 | round }}
{{ 3.14159 | round: 2 }}Filter: plus
Adds numbers together.
代码示例
{{ 5 | plus: 3 }}
{{ product.price | plus: tax }}Filter: minus
Subtracts numbers.
代码示例
{{ 10 | minus: 3 }}
{{ total | minus: discount }}Filter: times
Multiplies numbers.
代码示例
{{ 3 | times: 4 }}
{{ price | times: quantity }}Filter: divided_by
Divides numbers.
代码示例
{{ 12 | divided_by: 3 }}
{{ total | divided_by: count }}Filter: modulo
Returns the remainder of division.
代码示例
{{ 7 | modulo: 3 }}
{{ index | modulo: 2 }}Date & Time
Filter: date
Formats dates using strftime patterns.
代码示例
{{ order.created_at | date: "%B %d, %Y" }}
{{ "2024-09-26" | date: "%A, %b %d" }}Filter: timezone
Converts timestamps to different timezones.
代码示例
{{ meetingDate | timezone: "Europe/London" | date: "%d %B %Y %H:%M" }}
{{ "2024-09-25T10:30:00Z" | timezone: "America/New_York" }}Data Lookup
Filter: lookup
Retrieves data from lookup tables with nested key support.
代码示例
{{ 'global_links' | lookup: 'compliance', 'terms_and_conditions' }}
{% assign compliance = 'global_links' | lookup: 'compliance' %}
{{ table_name | lookup: 'key', 'nested_key', 'deep_key' }}Encoding
Filter: base64_encode
Encodes values using standard base64 encoding.
代码示例
{{ "hello world" | base64_encode }}
{{ contact.data | base64_encode }}
{{ 123 | base64_encode }}Filter: base64_decode
Decodes base64 encoded strings.
代码示例
{{ "aGVsbG8gd29ybGQ=" | base64_decode }}
{{ encoded_data | base64_decode }}Filter: base64url_encode
Encodes values using URL-safe base64 encoding (RFC 4648).
代码示例
{{ "hello world" | base64url_encode }}
{{ url_parameter | base64url_encode }}Filter: base64url_decode
Decodes URL-safe base64 encoded strings.
代码示例
{{ url_safe_data | base64url_decode }}
{{ token | base64url_decode }}Utility & Debug
Filter: json
Converts values to JSON format.
代码示例
{{ product | json }}
{{ user.preferences | json }}Filter: inspect
Returns a debug representation of a value.
代码示例
{{ complex_object | inspect }}
{{ array | inspect }}Filter: type
Returns the type of a value.
代码示例
{{ variable | type }}
{{ product.price | type }}Notes
- Base64 filters have a 1MB input size limit for security
- Currency formatting defaults to en-US locale when not specified
- Where filter supports both property existence checks and value matching
- Lookup tables are cached during template rendering for performance
For a comprehensive guide on these advanced Liquid features, please refer to the Shopify Liquid documentation.
Best Practice: While these advanced features are powerful, use them judiciously. Overly complex templates can be difficult to maintain and may impact email rendering performance.
Remember to thoroughly test your email templates across different email clients to ensure consistent rendering and optimal performance. The Bird platform provides tools for previewing and testing your templates before sending.
By mastering the Bird Email Template Language, you'll be able to create highly dynamic, personalized, and engaging email campaigns that resonate with your audience and drive results.