Personalization lets you insert contact-specific information into your emails, making each message feel tailored to the individual recipient. Instead of sending "Hello there," you can send "Hello Sarah." Instead of generic content, you can reference a contact's company, past purchases, or any custom data you've collected.
This article covers everything from basic personalization tags to advanced template logic like conditionals and loops.
Where Personalization Works
You can use personalization tags in:
Subject lines: Make your email stand out in the inbox
Preview text: Personalize the snippet that appears after the subject
Email body: Customize any text content within your email
Personalization works in all SendX editors: Drag & Drop, Plain Text (HTML), and SendX AI Editor.
Basic Personalization
Default Contact Fields
SendX provides these default contact fields that you can personalize with:
Field | Tag | Example Output |
| ||
Name |
| Sarah Johnson |
Company |
| Acme Corp |
First Name |
| Sarah |
Last Name |
| Johnson |
Example usage in email body:
Hi {{.FirstName}}, Thank you for being a valued customer at {{.Company}}. We wanted to reach out...Example usage in subject line:
{{.FirstName}}, your weekly digest is ready
Custom Fields
Any custom fields you've created for your contacts can also be used in personalization. Use the exact field name as it appears in your contact settings.
Syntax: {{.field_name}}
For example, if you have custom fields for plan_type, signup_date, or favorite_color:
Your current plan: {{.plan_type}} You've been with us since {{.signup_date}}
Using Fallback Values
What happens when a contact doesn't have a value for a field? Without a fallback, you'd get an empty space or potentially broken-looking text. The fallback function solves this.
Syntax: {{fallback .FieldName "default value"}}
Examples:
Hi {{fallback .FirstName "there"}},If FirstName is empty, this outputs: "Hi there,"
We noticed you work at {{fallback .Company "your company"}}.If Company is empty, this outputs: "We noticed you work at your company."
This is especially important for subject lines where missing data would look unprofessional:
{{fallback .FirstName "Friend"}}, check out our new featuresAdvanced Personalization
Conditional Content with If/Else
You can show or hide content based on whether a field has a value or meets certain conditions.
Basic if statement:
{{if .FirstName}} Hi {{.FirstName}}, {{end}}
If/else statement:
{{if .FirstName}} Hi {{.FirstName}}, {{else}} Hi there, {{end}}
If/else if/else chain:
{{if .Company}} Thanks for representing {{.Company}}!
{{else if .FirstName}} Thanks, {{.FirstName}}!
{{else}} Thanks for being here! {{end}}
Comparison Operators
Use these operators to compare values:
Operator | Meaning | Example |
| Equal to |
|
| Not equal to |
|
| Less than |
|
| Greater than |
|
| Less than or equal |
|
| Greater than or equal |
|
Example: Different content based on plan type:
{{if eq .plan_type "premium"}} As a Premium member, you get exclusive access to our new features. {{else if eq .plan_type "basic"}} Upgrade to Premium to unlock all features. {{else}} Start your free trial today! {{end}}
Logical Operators
Combine conditions using and, or, and not:
And (both conditions must be true):
{{if and .FirstName .Company}} Hi {{.FirstName}} from {{.Company}}! {{end}}
Or (at least one condition must be true):
{{if or .phone .email}} We have your contact information on file. {{end}}
Not (inverts the condition):
{{if not .has_purchased}} Make your first purchase and get 20% off! {{end}}
Complex combinations:
{{if and .FirstName (or (eq .plan_type "premium") (eq .plan_type "enterprise"))}} {{.FirstName}}, as a valued {{.plan_type}} customer... {{end}}
Loops with Range
If you have custom fields that contain lists or arrays, you can iterate over them using range.
Basic loop:
Your recent items: {{range .recent_products}} - {{.}} {{end}}Loop with index:
{{range $index, $item := .items}} {{$index}}. {{$item}} {{end}}Loop with else (when list is empty):
{{range .wishlist_items}} - {{.}} {{else}} Your wishlist is empty. Start adding items! {{end}}
Date Functions
SendX provides several functions for working with dates in your emails.
Current Date Functions
Function | Description | Example |
| Today's date |
|
| Tomorrow's date |
|
| Yesterday's date |
|
The format string follows Go's date formatting convention. Here are common formats:
Format String | Example Output |
| February 16, 2026 |
| Feb 16, 2026 |
| 2026-02-16 |
| 02/16/2026 |
| 16-Feb-2026 |
| Monday, February 16 |
Example:
Today is {{todaydate "Monday, January 2, 2006"}}. This offer expires {{tomorrowdate "January 2"}}.
Date Calculations
Get a date X days from now:
{{date_after_x_days "January 2, 2006" 7}}Returns the date 7 days from today.
Get a date X days from a specific date:
{{date_after_x_days_from "2026-02-16" "January 2, 2006" 30}}Returns the date 30 days after February 16, 2026.
Format an existing date:
{{formatdate .signup_date "January 2, 2006"}}Formats a date stored in a custom field. The input date should be in YYYY-MM-DD format.
Date Difference Functions
Days since a date:
{{days_since .signup_date}}Returns the number of days since the date in the signup_date field.
Days until a date:
{{days_until .expiration_date}}Returns the number of days until the date in the expiration_date field.
Days between two dates:
{{days_between .start_date .end_date}}Returns the number of days between two dates.
Practical example:
{{if gt (days_since .signup_date) 365}}
Congratulations! You've been with us for over a year.
{{else if gt (days_since .signup_date) 30}}
Thanks for being a loyal customer this past month.
{{else}}
Welcome! You joined us {{days_since .signup_date}} days ago.
{{end}}Text Formatting Functions
Capitalize Words
Capitalizes the first letter of each word, similar to title case.
{{capitalize_words .job_title}}Input: "senior software engineer" Output: "Senior Software Engineer"
First Character
Returns just the first character of a string, useful for avatars or initials.
{{first_character .FirstName}}Input: "Sarah" Output: "S"
Trim Quotes
Removes surrounding quotes from a string.
{{trim_quotes .some_field}}Input: "Hello World" Output: Hello World
Math Functions
Increment
Adds 1 to a number. Useful for displaying counts or rankings.
You are customer #{{inc .customer_number}}
Divide
Divides two numbers and returns result with 2 decimal places.
{{divide .total_points .num_purchases}} points per purchase
Percentage
Calculates percentage of first number out of second number.
{{percentage .completed_tasks .total_tasks}} completeReturns formatted like: "75.00 %"
Custom Event Data Functions
When using custom events to trigger workflows, you can access the event data in your emails.
Get Value
Accesses a value from nested custom event data using dot notation.
{{get_value .EventData "order.product_name"}}This navigates through the event data structure. If you have event data like:
{
"order": {
"product_name": "Blue Widget",
"quantity": 3
}
}{{get_value .EventData "order.product_name"}} returns "Blue Widget"
Get Value with Fallback
Same as get_value but returns a fallback if the path doesn't exist.
{{get_value_with_fallback .EventData "order.discount_code" "No discount applied"}}Combining Functions
You can combine multiple personalization techniques for sophisticated content.
Example: Personalized renewal reminder
Hi {{fallback .FirstName "there"}},
{{if .subscription_end_date}} Your {{.plan_type}} subscription expires on {{formatdate .subscription_end_date "January 2, 2006"}}. That's just {{days_until .subscription_end_date}} days away! {{if eq .plan_type "basic"}} Upgrade to Premium before your renewal and save 20%. {{else}} Renew now to keep your Premium benefits. {{end}} {{else}} Start your subscription today! {{end}}
Best, The {{fallback .Company "Our"}} Team
Example: Dynamic subject line with conditional
{{if .FirstName}}{{.FirstName}}, {{end}}{{if gt (days_until .trial_end) 0}}{{days_until .trial_end}} days left in your trial{{else}}Your trial has ended{{end}}Template Validation
SendX validates your personalization templates before allowing you to schedule a campaign. When you create a campaign, SendX tests the template with dummy data to ensure it renders correctly.
If your template has syntax errors, you'll be notified and won't be able to schedule the campaign until the errors are fixed.
Common validation errors:
Missing closing
{{end}}for if statements or loopsMisspelled function names
Incorrect number of arguments to a function
Unclosed brackets or quotes
Best Practices
Always use fallbacks for critical fields
Especially in subject lines and greetings, always provide a fallback so emails look professional even when data is missing.
Hi {{fallback .FirstName "there"}},
Test with different scenarios
Before sending, think about contacts who might have:
All fields filled in
Only some fields filled in
No optional fields filled in
Make sure your email looks good in all cases.
Keep conditional logic readable
If your conditionals are getting complex, consider whether you might be better served by separate campaigns or segments.
Be mindful of date formats
When displaying dates to recipients in different regions, consider using formats that are unambiguous (like "February 16, 2026" rather than "02/16/2026" which could be confusing internationally).
Don't over-personalize
Using someone's name once or twice is friendly. Using it in every sentence feels robotic and can come across as creepy rather than personal.
Quick Reference
Basic Tags
{{.FieldName}} - Insert field value
{{fallback .Field "default"}} - Insert with fallbackConditionals
{{if .Field}}...{{end}}
{{if .Field}}...{{else}}...{{end}}
{{if eq .Field "value"}}...{{end}} {{if and .Field1 .Field2}}...{{end}}
{{if or .Field1 .Field2}}...{{end}} {{if not .Field}}...{{end}}Comparison Operators
eq (equal), ne (not equal) lt (less than), gt (greater than) le (less or equal), ge (greater or equal)
Date Functions
{{todaydate "January 2, 2006"}}
{{tomorrowdate "January 2, 2006"}}
{{yesterdaydate "January 2, 2006"}}
{{date_after_x_days "format" days}}
{{formatdate .date_field "format"}}
{{days_since .date_field}}
{{days_until .date_field}}
{{days_between .start .end}}Text Functions
{{capitalize_words .field}}
{{first_character .field}}
{{trim_quotes .field}}Math Functions
{{inc .number}}
{{divide .num1 .num2}}
{{percentage .part .whole}}Loops
{{range .list}}{{.}}{{end}}
{{range $i, $v := .list}}{{$i}}: {{$v}}{{end}}Frequently Asked Questions
Can I use personalization in all campaign types?
Yes. Personalization works in Newsletter campaigns, A/B Tests, Drip campaigns, RSS campaigns (combined with RSS tags), Auto Trigger campaigns, and Workflow emails.
What happens if a contact doesn't have a value for a field I'm using?
If you don't use a fallback, the field will be empty (blank). This can look awkward, especially in subject lines. Always use the fallback function for fields that might be empty.
Can I nest if statements?
Yes. You can nest conditional logic as deep as needed:
{{if .FirstName}} {{if eq .status "active"}} Hi {{.FirstName}}, welcome back! {{else}} Hi {{.FirstName}}, we miss you! {{end}} {{end}}
Why is my campaign failing validation?
Check for:
Unclosed
{{if}}blocks (every{{if}}needs an{{end}})Misspelled field names or function names
Missing arguments to functions
Unbalanced brackets
Can I do math operations on fields?
Basic operations like increment, divide, and percentage are available. For more complex calculations, you may need to pre-calculate values and store them in custom fields.
