Using Custom Fields and Tags to Drive Automations
Custom fields email automation works best when fields and tags are treated as two different kinds of data: fields hold one current value per contact, tags record facts that can be true in any combination. Get that split right and your automations stay readable as the list grows; get it wrong and you end up with contradictory tags, silently overwritten values, and branches that never fire.
The difference between a field and a tag (and why it decides your architecture)
A field stores a single current value for a contact. plan_name can be "Starter" or "Growth", never both. trial_end_date holds one date. When you write a new value to a field, the old one is gone.
A tag is a boolean fact attached to a contact. A contact can carry source:webinar, intent:pricing_page and lifecycle:trial_active at the same time, and removing one has no effect on the others.
The decision rule is one sentence: if a contact can hold two values at once, it is a tag; if only one value can be current, it is a field.
Applied to real attributes:
| Attribute | Field or tag | Why |
|---|---|---|
| Current plan | Field (plan_name) |
A contact is on one plan at a time |
| Webinars attended | Tag (source:webinar_q3) |
A contact can attend many |
| Trial end date | Field (trial_end_date) |
One current date |
| Pages visited recently | Tag (intent:pricing_page) |
Many pages, many tags |
| Lifecycle stage | Field (lifecycle_stage) |
One stage at a time |
| Email preferences | Tags (pref:product_news) |
Multiple opt-ins coexist |
Two failure modes follow from breaking this rule.
Using tags for state. If you tag contacts trial_active and later trial_expired, nothing stops both from being present after a sync error or a missed cleanup step. Your condition "has tag trial_active" then fires for someone who already churned. State belongs in a field, where writing a new value replaces the old one by definition.
Using fields for sets. If you store attended webinars in a field called webinar, each new attendance overwrites the last. You lose the history and your "attended 3+ webinars" branch can never be true. Sets belong in tags.
What you'll set up and what you need
Before creating anything, gather four things:
- A naming convention, agreed and written down. Retrofitting one across 200 tags is painful.
- A list of events your product or site already emits — signup, trial start, purchase, cancellation, key page views. These become your tags and field updates.
- A source of truth per attribute. Decide whether your app, your CRM or your email platform owns
plan_name. Two systems writing the same field is the most common cause of flapping values. - Access to your platform's field and tag settings, plus an API key or webhook endpoint if you sync from an app.
In Mailerflow, custom fields and tags can be created during CSV import, which runs duplicate and validity checks — useful when you are backfilling a list. Dynamic segments can be built on fields, tags, engagement, events and website behavior, which matters here because you can define a segment once and reuse it across automations instead of rebuilding the same conditions in every branch.
Step-by-step: designing the scheme
1. Write the naming convention. Fields in snake_case with a clear noun: plan_name, plan_renewal_date, ltv_band, trial_end_date. Tags in lowercase with a namespace prefix and a colon: source:webinar, intent:pricing_page, lifecycle:trial_active, pref:product_news. The prefix is what makes tag lists scannable at 500 tags.
2. Classify every attribute using the rule above. Do this in a spreadsheet before touching the platform. One row per attribute, one column for field-or-tag, one for the owner system.
3. Define field types explicitly. Text, number, date or boolean. Set defaults deliberately, because an empty date field behaves differently from an empty string in a condition. A wait step that references an empty date can leave contacts stuck indefinitely.
4. Decide tag lifecycle. Some tags are permanent (source:* — where the contact came from never changes). Others expire (intent:* — a pricing page visit from eight months ago should not drive today's branch). Pick an expiry window and enforce it.
5. Map each automation trigger to exactly one field or tag, and record it in a table:
| Automation | Trigger | Enters when |
|---|---|---|
| Trial onboarding | Signup event | lifecycle_stage = trial |
| Pricing follow-up | Tag added | intent:pricing_page present |
| Renewal reminder | Date | 7 days before plan_renewal_date |
| Win-back | Inactivity | No open or click in 60 days |
6. Build the segment layer. Create dynamic segments that read fields and tags, then have automations enter on segment membership rather than on raw conditions. When the definition changes — say, trial now means 21 days instead of 14 — you edit one segment instead of ten automations.
7. Add a verification step to each automation. More on this below.
8. Version the scheme. Keep it in a shared doc with a changelog: date, what was added, who added it, which automations depend on it.
A worked example: a B2B trial-to-paid sequence
This is an illustrative scenario, not a customer story.
A SaaS product runs a 14-day trial. The scheme:
Fields: plan_name (text), trial_start_date (date), trial_end_date (date), seats (number), lifecycle_stage (text).
Tags: source:demo_request, source:content_download, intent:pricing_page, intent:docs_deep_dive, lifecycle:trial_active, lifecycle:trial_expired, lifecycle:paid.
The automation:
- Trigger: signup event. Condition:
lifecycle_stageequalstrial. - Wait: 1 day.
- Condition:
seatsis greater than 5 → higher-touch branch (assign to sales, send a calendar link). Otherwise → self-serve branch. - Wait until:
trial_end_dateminus 3 days. - Condition: tag
intent:pricing_pageis present → send the pricing-objection email. Tag not present → send the feature-adoption email. - On
trial_end_date: checklifecycle_stage. Ifpaid, move to onboarding. If stilltrial, move to the win-back branch and addlifecycle:trial_expired. - Webhook step: push the outcome back to your app so the CRM and the email platform agree on
lifecycle_stage.
In a visual builder those conditions read as plain statements: field equals value, tag is present, tag is not present. The important detail is step 7 — one writer per field. If the app also updates lifecycle_stage on its own schedule, you get a race condition.
If you would rather not hand-build the skeleton, Mailerflow's AI automation builder takes a one-sentence description and drafts the trigger, waits, conditions and emails for review before activation, and the AI email builder can produce the branch emails from a description. The field and tag scheme is still your call, because the draft is written against the names you already have.
How to check it works
Verification is the part most guides skip, and it is where broken schemes surface.
- Walk a test contact through manually. Use a known alias you control, trigger the entry event, and step through.
- Inspect the contact record after each step. Confirm the field value and the full tag set match what you expect — not just the tag you were looking for.
- Read the activity log. Confirm each branch was entered and exited exactly once. Twice means duplicate entry; never means a condition is wrong.
- Test the negative case. Create a contact who should not enter, and confirm they do not. This catches conditions written as "tag is not present" when you meant "field does not equal".
- Trigger the same event twice and check for duplicate entry. This is the single most common production bug.
- If you use webhooks, confirm the delivery log shows a 2xx and that retries are not firing. Signed webhooks with retries and delivery logs make this checkable rather than guesswork.
What a broken scheme looks like in the logs: contacts piled up on a wait step because a date field is empty; a branch that never fires because the tag is spelled Pricing_Page in one place and pricing_page in another; a contact who receives the win-back email twice because two automations both trigger on the same tag.
If you are testing a multi-channel flow, the same discipline applies to SMS steps — see combining email and SMS in one automation for how the trigger and consent logic differ.
Common mistakes and fixes
| Mistake | Fix |
|---|---|
| Tag sprawl from one-off campaign tags | Namespace everything; delete tags unused for 90 days |
| Storing a set in a field, overwriting values | Move sets to tags |
| Inconsistent casing or separators | Lint tag names before creation; enforce lowercase |
| Same condition duplicated in ten automations | Move it into a dynamic segment |
| Intent tags never expiring | Cleanup automation that removes intent:* after N days |
| PII in free-text fields with no retention plan | Define retention; use erasure and export tooling where required |
| Two systems writing one field | Pick one writer per field, document it |
On the last two: if your fields hold anything personal, note that Mailerflow provides data export, erasure, consent logs and configurable retention, with data hosted in Europe.
Next steps
Audit your existing tags and delete anything unused for 90 days. Convert duplicated conditions into segments. Add a changelog entry whenever a field or tag is introduced. And before you build the next automation by hand, consider describing it in a sentence and reviewing the draft against your naming rules — the review is where the value is.
If the cleanup is happening during a platform move, Mailerflow offers free migration help for contacts, suppression lists, templates and core automations on eligible paid plans. For a structured pre-launch checklist, how to test an email automation before going live covers the test matrix in more detail.
FAQ
How many custom fields should I create? As few as your automations actually read. Every field is a maintenance obligation and a place for bad data to accumulate. If no condition, segment or personalization token references a field, you probably do not need it.
Should I use a tag or a field for lifecycle stage? A field. A contact is in one stage at a time, and writing a new stage should replace the old one. Tags let contradictory states coexist, which is exactly what you do not want for lifecycle.
What happens to automations if I rename a field? It depends on the platform. Some update references automatically, some break the condition silently. Check your platform's documentation before renaming, and treat renames as a change that requires re-testing every automation that reads the field.
How do I stop a contact entering an automation twice?
Combine a trigger condition with a guard: check that a field such as lifecycle_stage is not already in the target state, or that a completion tag is absent. Then test by firing the trigger event twice.
Can I build segments from tags and fields together?
Yes, and you should. A segment like "trial contacts with seats > 5 who have intent:pricing_page" combines a field, a numeric comparison and a tag in one reusable definition. In Mailerflow, dynamic segments can also read engagement, events and website behavior, and AI segmentation can draft one from a plain-language description.
Describe this automation in a sentence and Mailerflow drafts the workflow for you to review — start free.


