Skip to content

Personalization Beyond First Name — Using Merge Tags in AcelleMail

Drop a subscriber's name, location, last-purchase, or any custom field straight into your email subject and body. The AcelleMail builder has a merge-tag picker that surfaces every field on your list — no syntax to memorize. This guide walks the UI; raw Twig syntax for power users is in the collapsible section.

What a merge tag actually does

A merge tag is a placeholder you drop into your email subject or body that AcelleMail replaces — per recipient, at send time — with that subscriber's actual value.

Subject Hey {{ subscriber.first_name }}, your invoice for July becomes Hey Maria, your invoice for July for Maria, Hey Tobias, your invoice for July for Tobias.

The values come from list fields — every list has at least email + first_name + last_name, and you can add unlimited custom fields like city, signup_plan, last_purchase_total.

Insert a merge tag from the campaign builder

1. Start typing in the subject line

In any campaign, the Subject field accepts merge tags inline. Click the field and start typing — AcelleMail shows a hint about merge-tag insertion:

Subject field — merge tag hint visible

You can paste a tag directly ({{ subscriber.first_name }}) OR open the picker for the full list.

2. The merge-tag picker (autosuggest)

Type {{ in the subject — or open the body builder's right-side panel — and the autosuggest dropdown lists every available tag, scoped to this list's actual fields:

Merge-tag autosuggest picker

Click a tag to insert it. The picker scopes to:

  • Subscriber fields — every column on your list (email, first_name, custom fields)
  • System tags{{ unsubscribe_url }}, {{ web_view_url }}, {{ campaign.name }}, {{ send_date }}
  • Conditional helpers{% if %} ... {% endif %} (Twig syntax — see Advanced)

3. Manage the list's custom fields

The picker only shows fields that exist on the list. To add a new field, Audience → [list] → Fields:

List fields configuration

For each field, set:

  • Tag (the key) — e.g. city becomes {{ subscriber.city }} in emails
  • Type — text / number / date / dropdown / multi-select
  • Required at signup — appears on the signup form, blocks if blank
  • Default value — fallback for existing subscribers without this field set

After adding a field, re-run an import (or update via API) to back-fill values for existing subscribers — they won't be back-filled automatically.

Common UI patterns that work

What you want How to write it
First name with a fallback if unknown Hi {{ subscriber.first_name | default('there') }}
Full name (joined) {{ subscriber.first_name }} {{ subscriber.last_name }}
Date formatting {{ subscriber.signup_date | date('F j, Y') }}
Uppercase a value {{ subscriber.city | upper }}
Truncate a string {{ subscriber.bio | truncate(80) }}
Numeric formatting ${{ subscriber.lifetime_value | number_format(2) }}

These filters use Twig syntax — the AcelleMail builder renders them at send time. You can test any tag by clicking Preview in the campaign builder and toggling the Use sample subscriber dropdown:

Sample subscriber preview

Common pitfalls + UI fixes

Symptom Likely cause UI fix
Email shows literal {{ subscriber.city }} instead of "Berlin" Field doesn't exist on this list, OR typo in tag name Open Audience → [list] → Fields — confirm the tag matches exactly
First name field empty for half the list Imported CSV had no first_name column Use | default('friend') filter, OR re-export source + re-import with field mapping
Picker doesn't show a field you added Page cached pre-add Hard refresh (Cmd-Shift-R / Ctrl-F5), or close + reopen the builder
Subject renders blank for some recipients The field is empty for those subscribers + no default filter Add | default('something') to the merge tag
Advanced: Twig conditionals, loops, and computed merge tags

AcelleMail's body and subject support the full Twig templating language — including conditionals and loops — for cases the autosuggest picker doesn't cover.

Conditional content blocks:

{% if subscriber.signup_plan == 'enterprise' %}
  <p>Your Enterprise account manager is Sarah — book a call here.</p>
{% elseif subscriber.signup_plan == 'pro' %}
  <p>Pro users get priority support — reply to this email anytime.</p>
{% else %}
  <p>Get faster response times by upgrading.</p>
{% endif %}

Tag-based blocks (using the multi-value tags field):

{% if 'vip' in subscriber.tags %}
  <p>VIP early access: <a href="...">claim your slot</a></p>
{% endif %}

Loops over array fields (when a custom field is JSON-encoded list):

<ul>
{% for product in subscriber.recent_purchases %}
  <li>{{ product.name }} — ${{ product.price }}</li>
{% endfor %}
</ul>

Computed values inline:

{% set discount = subscriber.lifetime_value > 500 ? 20 : 10 %}
Your loyalty discount: {{ discount }}%

Default filter chains for safety:

Hi {{ (subscriber.first_name | default(subscriber.email | split('@') | first)) | capitalize }}

This says: try first_name, fall back to the part of the email before @, then capitalize. Bullet-proof against missing fields.

Per-campaign override fields — if you need a value computed at send time (e.g. discount code unique per recipient), use the AcelleMail API to populate a custom field just before launching the campaign, OR set up an automation that sets the field when the trigger fires.

For a deeper Twig reference, the upstream syntax docs at twig.symfony.com apply directly — AcelleMail uses Twig 3.x.

Related articles

9 comments

7 comments

  1. Aditi
    any guidance on how this interacts with the tie-of-day send optimization? conflicts with our scheduled-blast pattern.
    1. Admin
      They don't interact. Merge tags resolve per subscriber at handoff to the sending server, not at schedule time. Only catch is a field that changes mid-window, freeze it before the blast.
  2. Sofia
    Pro tip from our team: build campaign templates with a single CTA. Multiple CTAs always underperform in our data
  3. Quân
    The personalization-beyond-first-name section is what I needed. Most articles talk about it abstractly.
  4. Marcus
    saved this. going to use as a reference for our next campaign cycle...
  5. Emma
    Confirming the A/B-test sample size guidance. We were testing too small for too long — switching to bigger batches over fewer cycles was the right call
  6. Brian
    Our open rate jumped from 18% to 24% after we restructured around these principles. Took about 6 weeks to see the full lift
  7. Vera
    How do you handle this when your campaign list spans multiple language audiences? We have EN + ES + FR subscribers in one campaign
    1. Admin
      The honest answer is don't do it inside one email body. Merge tags substitute values, they don't translate the copy around them, so a single template ends up English with a Spanish first name pasted in. What works: add a `language` custom field on the list, then build three segments (language = EN / ES / FR) and send the same campaign three times with the translated template. Merge tags stay identical across the three, only the surrounding copy changes. Takes two extra minutes at setup and your reports stay per-language, which you'll want anyway when the open rates differ. Two things to watch. Set a default value on the `language` field so subscribers who never told you don't fall out of all three segments, that's the usual leak. And if you use fallbacks like `{FIRST_NAME|there}`, remember the fallback is per-tag literal text, so it needs to be translated too or your ES send says "Hola there". Conditional blocks inside one template to swap whole paragraphs by language are not supported today. It comes up enough that I'll look at it, but segmentation is the path right now and it's the one I'd pick regardless.

More in Email Marketing