Skip to main content

Personalizing Campaigns with Custom Fields

D
Written by Deepak
Updated over a week ago

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

Email

{{.Email}}

Name

{{.Name}}

Sarah Johnson

Company

{{.Company}}

Acme Corp

First Name

{{.FirstName}}

Sarah

Last Name

{{.LastName}}

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 features

Advanced 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

eq

Equal to

{{if eq .plan_type "premium"}}

ne

Not equal to

{{if ne .status "cancelled"}}

lt

Less than

{{if lt .days_active 30}}

gt

Greater than

{{if gt .purchase_count 5}}

le

Less than or equal

{{if le .score 50}}

ge

Greater than or equal

{{if ge .points 100}}

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

todaydate

Today's date

{{todaydate "January 2, 2006"}}

tomorrowdate

Tomorrow's date

{{tomorrowdate "January 2, 2006"}}

yesterdaydate

Yesterday's date

{{yesterdaydate "January 2, 2006"}}

The format string follows Go's date formatting convention. Here are common formats:

Format String

Example Output

"January 2, 2006"

February 16, 2026

"Jan 2, 2006"

Feb 16, 2026

"2006-01-02"

2026-02-16

"01/02/2006"

02/16/2026

"02-Jan-2006"

16-Feb-2026

"Monday, January 2"

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}} complete

Returns 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 loops

  • Misspelled 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 fallback

Conditionals

{{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.

Did this answer your question?