BlogESJoin the waitlist
← All articles

Iterable Handlebars default value: fix empty fields in your emails

How to set a default value in Iterable with defaultIfEmpty or #if and else, which values count as empty, and how to preview users with missing fields.

By Mario Calvo · · 12 min read

Quick answer

In Iterable you set a default value with the defaultIfEmpty helper: {{defaultIfEmpty firstName "there"}}. If firstName is null, missing or an empty string, the email shows "there" instead of a gap. When one word doesn't fix the sentence, use {{#if firstName}}...{{else}}...{{/if}} and write two versions of it. Then open the template's Preview with data, load a user without that field and check the result before you send.

What you'll find

How do you set a default value in Iterable?

Iterable templates use Handlebars. A field goes between double curly braces, like {{firstName}}. At send time, Iterable replaces it with the value from the user's profile or from the event that triggered the campaign.

If the value isn't there, Iterable prints nothing. "Hi {{firstName}}," becomes "Hi ,". That's the gap you want to avoid.

The shortest fix is the defaultIfEmpty helper. You give it the field and the text to show when the field is empty:

Hi {{defaultIfEmpty firstName "there"}},

A user called Ana sees "Hi Ana,". A user with no first name sees "Hi there,".

The second option is a block with #if and else. It does the same job, with more control over the whole sentence:

{{#if firstName}}Hi {{firstName}},{{else}}Hi there,{{/if}}

Both are valid. Which one you choose depends on the sentence, as the next sections show.

What you write What it does Good for
{{firstName}} Prints the value, or nothing Fields that are always filled
{{defaultIfEmpty firstName "there"}} Prints the value, or the default text A word that slots into the sentence
{{defaultIfEmpty nickname firstName}} Prints nickname, or firstName if it's empty Falling back from one field to another
{{#if firstName}}...{{else}}...{{/if}} Shows one block or the other Two different versions of a sentence
{{capitalize firstName}} Capitalizes the first letter of each word Names typed in lowercase

Checked against the Iterable documentation in October 2026: Personalizing Templates with Handlebars.

Which values count as empty?

This is where most "why is it still blank?" questions come from. The two options treat values almost the same way, with one detail worth knowing.

defaultIfEmpty shows the default when the field is null, undefined or an empty string. For #if, Iterable's Handlebars treats these values as false: null, an empty string, an empty array, the boolean false and any number equal to zero. Everything else is true.

So for a text field like a first name, both behave the same: the default appears when the field is missing or empty.

The catch is a field that only contains a space. A space is a value. Neither defaultIfEmpty nor #if will treat it as empty, so the user sees "Hi ," with a double space. The same happens with a name saved as "-" or "." from a careless form. The template can't fix those. The data has to.

Output of a greeting for five profiles (a normal name, an empty string, no field, a single space and a name in capitals) with a plain merge tag, with defaultIfEmpty and with #if and else

What the user profile has {{firstName}} defaultIfEmpty or #if What to do
"Ana" Hi Ana, Hi Ana, Nothing
"" (empty string) Hi , Hi there, Add a default
No firstName field Hi , Hi there, Add a default
" " (a space) Hi , Hi , Clean the data at the source
"ANA" Hi ANA, Hi ANA, Fix the data, or accept it
0 in a number field 0 Default with #if, value with defaultIfEmpty Use #if only when zero should hide the block

The last row matters for numbers. With #if, a field equal to zero counts as false. If you write {{#if points}}You have {{points}} points{{/if}}, a user with 0 points sees nothing. Sometimes that's what you want. Sometimes it isn't.

About capitals: capitalize turns "ana maría" into "Ana María". Iterable documents it as capitalizing the first letter of each word. It doesn't say it lowercases the rest, so preview a name saved as "ANA" before you rely on it. If your list has many names in capitals, lower before capitalize is worth a test, and fixing the data is the safer route.

When should you use #if and else instead?

defaultIfEmpty works when one word or short phrase slots into the sentence. "Hi there," reads fine. "Ana, your order is ready" with a default becomes "there, your order is ready", which doesn't.

When the sentence needs a different shape without the name, write both versions:

{{#if firstName}}
  {{firstName}}, your order is ready.
{{else}}
  Your order is ready.
{{/if}}

Other cases where #if is the better tool:

  • Whole blocks. If a user has no loyalty tier, hide the tier section instead of printing "Your tier: none".
  • Punctuation. A comma after the name has no place once the name is gone.
  • Languages with gender. In Spanish, many defaults have a gender. A neutral sentence without the name is often safer than a default word.
  • Several fields. Iterable also has #and, #or and else if to test more than one condition.

And when the email makes no sense without the field, don't send it. A coupon email without the coupon code is worse than no email. Iterable has a sendSkip helper that cancels the send for that user and records the skip with a reason:

{{#if couponCode}}
  Your code: {{couponCode}}
{{else}}
  {{sendSkip cause="missing coupon code"}}
{{/if}}

Decision tree: if the field can't be empty, a plain merge tag; if the email can't go out without it, sendSkip; if one word fixes the sentence, defaultIfEmpty; otherwise #if and else

Situation Best option Example
Greeting with the first name defaultIfEmpty Hi {{defaultIfEmpty firstName "there"}},
Name at the start of the sentence #if / else Two versions of the sentence
A section that only applies to some users #if without else Hide the loyalty block
One field or another defaultIfEmpty with two fields {{defaultIfEmpty nickname firstName}}
A coupon code or a price sendSkip Skip the users without the code
A field that is always filled Plain merge tag {{email}}

Which field does Iterable read?

A default only helps if Iterable is looking at the right field. Three details trip people up.

Event fields win over profile fields. If the event that triggers the campaign has a field with the same name as a profile field, Iterable uses the event value. If the event sends firstName empty and the profile has a name, the user can get the default when you expected the name. Use {{profile.firstName}} to force the profile value.

Field names are case-sensitive. firstName, FirstName and first_name are three different fields. If your template says firstName and your profiles store first_name, every user gets the default. Check the exact name in your project before you blame the data.

Spaces, periods and leading numbers need square brackets. A field called First Name is written {{[First Name]}}. The same goes for the default: {{defaultIfEmpty [First Name] "there"}}. Iterable advises against periods in field names, because they clash with nested objects.

If you work with more than one platform, the cheat sheet of name and unsubscribe tags across 21 platforms shows the same greeting in each syntax. The logic is the same in Klaviyo's default filter and in Braze custom attributes with Liquid, with different words.

Does it work in the subject line and preheader?

Yes. Iterable lets you use Handlebars in the subject line and the preheader, as well as in the body. The same defaults apply:

{{defaultIfEmpty firstName "Hey"}}, your cart is waiting

Two things to keep in mind. The subject line and preheader don't render HTML, so keep them to plain text and merge tags. And a default that reads fine in the body can look odd in a subject. "There, your cart is waiting" doesn't work. Write the default for the sentence it lives in.

The WYSIWYG editor has its own quirk. Block helpers like #if placed between HTML tags can cause errors when you switch to the visual editor. Iterable recommends wrapping each block helper in an HTML comment:

<!--{{#if firstName}}-->
  <p>Hi {{firstName}},</p>
<!--{{else}}-->
  <p>Hi there,</p>
<!--{{/if}}-->

Only comment out the block helpers. Don't comment out {{firstName}} itself, or the value won't render.

Iterable also keeps the spaces and line breaks around your merge tags. If a default sits inside a link or a code fragment, add a tilde to trim the whitespace: {{~defaultIfEmpty firstName "there"~}}.

How do you test it before sending?

Preview with real profiles, including the bad ones. Iterable's preview lets you do that without changing anyone's data.

  1. Save the template. Unsaved changes don't show up in the preview.
  2. Go to Content > Templates, open the menu with the three dots and choose Preview with data. Or open the template and click Preview.
  3. Enter the email of a user and click Load user data.
  4. Edit the loaded data to test a case: delete firstName, set it to an empty string, set it to a space. This doesn't change the real profile.
  5. Check the subject line, the preheader and the body.
  6. Send a test from the preview. It uses the loaded data.

Checked against the Iterable documentation in October 2026: Previewing Templates.

What goes wrong Likely cause How to fix it
Still "Hi ," with a default Field name in a different case Copy the exact name from the user profile
Default shows for users who have a name The event sends the field empty Use profile.firstName
"Hi ," with a double space The field contains a space Clean the data at the source
Error when opening the visual editor Block helpers between HTML tags Wrap them in HTML comments
Nothing renders where the name should be The merge tag was commented out Only comment out block helpers
Block hidden for users with 0 points #if treats zero as false Compare the value with #ifGt or #ifEq

To find how many users are affected, build a segment in Iterable for users where the first name field doesn't exist or is empty. If it's a large share of your list, a default is a patch. Collecting the name at signup is the real fix.

How to do it with Remite

Remite writes the merge tags and their defaults in Iterable's Handlebars when you export, so you don't type them by hand. This is the real flow.

  1. Brand. You set up your brand once and pick Iterable as your platform. Remite uses firstName for the name and locale for the language, unless you tell it otherwise. With Connect CRM and a server key, Remite reads your real user fields and links each variable to the right one. Your keys stay in your browser.
  2. Personalize with. In the brief, you choose whether the email uses the first name or other fields from your CRM.
  3. Before generating. Remite reviews the brief and may ask one or two quick questions before writing.
  4. The fallback is part of the text. When a sentence breaks without the name, Remite adds a fallback to that variable. When the sentence reads fine empty, it leaves the variable without one. You can change the fallback in the chat, or select the text and use Comment.
  5. Export. The Your contact fields section shows which Iterable field each variable uses. If your project calls it something else, change it there and confirm with Yes, they match. The name comes out as {{#if firstName}}{{firstName}}{{else}}there{{/if}}, the unsubscribe link as {{unsubscribeUrl}}, and several languages as #eq blocks on your language field if you choose One with every language.
  6. Checking before upload. Remite checks the final HTML: the weight and Gmail clipping, the unsubscribe link in Iterable's syntax, the fields against your connected CRM, public images and links.
  7. Send to Iterable (beta). Remite creates the template in your account with the subject and preheader, or updates it if it already exists. You find it in Iterable → Content → Templates. Send me a test sends you the email with sample data first.

Two limits, so you know what to expect. Remite writes the #if version, not defaultIfEmpty: the result is the same for empty fields, and you can switch it in Iterable if you prefer the short form. And it doesn't add sendSkip. If an email must never go out without a field, add that block in Iterable with the example above.

If you're sending in several languages, the guide to multilingual templates compares one template with every language against one per language. And if you're deciding which lifecycle emails to build first, the lifecycle page has the overview. An automatic lifecycle diagnosis is coming soon.

Frequently asked questions

What is the default value syntax in Iterable Handlebars?

Use {{defaultIfEmpty fieldName "default text"}}. For example, {{defaultIfEmpty firstName "there"}} prints the first name, or "there" when it's empty or missing.

Does defaultIfEmpty work when the field doesn't exist?

Yes. Iterable shows the default when the value is null, undefined or an empty string. A field that doesn't exist on the profile counts as undefined.

Why do I still see "Hi ," after adding a default?

Usually the field name doesn't match. Handlebars field names are case-sensitive, so firstName and first_name are different fields. It can also be an event field arriving empty: try profile.firstName.

Should I use defaultIfEmpty or #if?

Use defaultIfEmpty when one word slots into the sentence. Use #if and else when the sentence needs a different shape without the value, or when you want to hide a whole block.

Can I use a default in the subject line?

Yes. Handlebars works in the subject line and preheader in Iterable. Write a default that reads well in a subject, since those fields don't render HTML.

How do I fall back to another field?

Give defaultIfEmpty a field instead of a text: {{defaultIfEmpty nickname firstName}}. It prints the nickname, or the first name if the nickname is empty.

How do I stop the send when a field is missing?

Use sendSkip inside an #if block. Iterable cancels the send for that user and records the skip with the cause you give it.

Does Remite add the fallback for Iterable?

Yes, when a sentence would break without the value. It exports it as {{#if firstName}}{{firstName}}{{else}}...{{/if}} with the text you see in the editor.

If you'd rather not write these tags by hand for every platform, you can join the Remite waitlist.