Naming and Tagging Conventions for Workflows, Messages, Segments, and Contact Fields
Workflows, messages, segments, and contact fields are the core building blocks of your Yespo account. The more objects you create, the harder it becomes to navigate them — unless names follow a shared logic from the start.
Consistent naming helps your team understand what each object does without opening it, find what they need without scrolling through dozens of similar names, build on existing logic instead of recreating it, and read campaign data correctly in analytics and reports.
This article covers naming and tagging conventions for workflows, messages, segments, and contact fields. Names define an object's stable identity, tags handle filtering and status, and descriptions hold free-form context. For naming conventions that apply to custom events and their parameters, see Naming Custom Events.
Why It Matters
Consistent names improve analytics. Message names flow through to UTM parameters, which means they appear directly in Google Analytics. A name like AbandonedCart_S01 filters cleanly by flow and sequence; a name like new email copy creates noise that's hard to untangle months later.
Teams work from the same logic. When everyone uses the same naming structure, there's no guesswork about what a segment covers, which workflow is live, or whether a message is a draft or a production template.
AI-assisted work becomes more reliable. When workflows, segments, fields, and tags follow predictable patterns, AI agents can better understand what each object means and use the right data in campaign setup or analysis. Vague or inconsistent names increase the risk of misinterpretation.
Three Tools for Organizing Objects
Yespo gives you three ways to describe and organize objects. Each has a different role:
Name — the stable identity of the object. It should tell you what the object is and where it fits, without needing to open it. Names appear in lists, reports, and UTM parameters, so they need to be readable and consistent.
Description — free-form notes. Use descriptions for the reasoning behind a segment rule, the hypothesis behind an A/B test, or any context that would make the name too long.
Tags — additional labels for filtering and grouping. Use tags for dimensions you frequently filter by but don't want to encode into every name: campaign season, lifecycle stage, experiment ID, status, owner.
A well-organized account uses all three. If your names are getting long and hard to read, some of that information probably belongs in a tag or description instead.
Core Principles
General → specific. Fields in a name follow the same order every time, moving from broad context to specific detail. This lets lists naturally group by type, funnel stage, or flow.
Controlled vocabulary. Use a fixed, agreed-upon set of abbreviations across your team. For country or market codes, align with ISO 3166 alpha-2 country codes so values like DE, PL, and US stay standardized across systems and reports. For other dimensions, apply the same consistency rule: pick one form and stick to it. Every abbreviation you introduce should be documented in your naming dictionary.
Names describe role, not version. A name should tell you what an object does, not track its edit history. Version markers like _v2, _new, or _copy accumulate over time and tell you nothing useful. If you need to track changes, use the description field or your version control. Note: V1/V2 suffixes are a separate convention — they apply only to A/B test variants within a single campaign (see Messages below).
Avoid decoration. Filler words (new, copy, test) and personal markers make names ambiguous. A name like BF_Nov14_v2_copy is unreadable in six months. Use a structured name and move context to the description.
Include launch dates for broadcast campaigns; use sequence numbers for lifecycle messages. For one-off sends like BF2025_S01, adding a date — BF2025_1114_S01 — helps you trace GA traffic back to a specific send months later. For triggered lifecycle messages, the relevant dimension is not when the message was sent but where it sits in the series: AbandonedCart_S01, AbandonedCart_S02. A date here adds no value — the message fires continuously, not on a specific day.
Different objects need different naming density. Workflows and segments benefit from readable, business-language names. Messages need more compact notation because they appear in long lists and need to be scannable at a glance. Contact fields also need to work in API calls and personalization templates, so they follow a closer-to-developer convention. The sections below reflect this.
Workflows
A workflow name should answer: what funnel stage is this, and what is it trying to achieve?
Pattern: [Stream]_[Goal (if needed)]_[Market (optional)]
| Field | What it means | Examples |
|---|---|---|
Stream | Lifecycle stage or campaign type | Welcome, AbandonedCart, BrowseAbandonment, PostPurchase, Reactivation, Loyalty |
Goal | What the workflow is designed to achieve — include only when the Stream alone is ambiguous | RecoverCart, UpsellAfterPurchase, WinbackDormant, ActivateVIP |
Market | Country or region — only if your flows differ meaningfully by market (different currency, social channels, content) | US, DE, PL |
A note on localization. Yespo supports multilingual messages natively, which means you often don't need to separate flows by language. If you're running the same flow logic across markets, use a single workflow with multilingual message content. Add a market suffix only when the flow itself differs — for example, different offer structure, different channel mix, or market-specific legal requirements.
Examples:
| ❌ Bad | ✅ Good |
|---|---|
cart email | AbandonedCart |
reactivation new | Reactivation_WinbackDormant |
after purchase flow copy | PostPurchase_UpsellAfterPurchase |
browse flow 2 | BrowseAbandonment |
vip winback | Loyalty_ActivateVIP_DE |
Some streams are self-explanatory and don't need a Goal suffix — AbandonedCart already implies recovering the cart. Add a Goal when the same Stream can serve different purposes: Reactivation_WinbackDormant vs Reactivation_ReturnFromChurn.
Messages
A message name should identify the flow it belongs to and its position in the sequence — without opening the message. The channel is already defined by where the message lives in the system. Send type (triggered vs. broadcast) is handled via tags.
Pattern: [Stream]_[Seq]_[Variant (optional)]
| Field | What it means | Examples |
|---|---|---|
Stream | Campaign or lifecycle flow this message belongs to | AbandonedCart, Welcome, PostPurchase, BF2025 |
Seq | Position in a series | S01, S02, S03 |
Variant | A/B test variant — append only when running a test | V1, V2 |
To distinguish triggered from broadcast messages in filtered views, use type_triggered and type_broadcast tags.
Examples:
| ❌ Bad | ✅ Good |
|---|---|
cart email 1 | AbandonedCart_Reminder |
cart_ab / cart_ab2 | AbandonedCart_Reminder_V1 / AbandonedCart_Reminder_V2 |
welcome new | Welcome_S02 |
BlackFriday_final_FINAL | BF2025_S01 |
sms test 3 | Reactivation_S01 |
post purchase push copy | PostPurchase_S02 |
Sequence numbers vs. role-based names. Sequential notation works well for short series. For longer drip flows, role-based names often scale better — AbandonedCart_Reminder, AbandonedCart_Urgency, AbandonedCart_LastCall — because inserting or reordering steps doesn't require renaming anything. If you're already using sequence numbers and need to insert a step between S01 and S02, use S01b or plan gaps from the start (S10, S20, S30) so new steps slot in cleanly without breaking historical analytics.
Segments
A segment name should answer: what lifecycle stage are these contacts in, and what is the defining rule?
Pattern: [LifecycleStage]_[SegmentRule]
| Field | What it means | Examples |
|---|---|---|
LifecycleStage | Where contacts are in the funnel | New, Active, AtRisk, Churned, VIP, Prospect |
SegmentRule | The key condition that defines this segment, in plain readable terms | NoPurchase60D, OrderedLast30D, CartAbandoned7D, AOVover200 |
Examples:
| ❌ Bad | ✅ Good |
|---|---|
Active buyers | Active_OrderedLast30D |
at risk NEW | AtRisk_NoPurchase60D |
cart seg 2 | AtRisk_CartAbandoned7D |
Inactive | Churned_NoPurchase180D |
New | New_RegisteredLast7D |
big spenders | VIP_AOVover200 |
Avoid vague lifecycle terms used interchangeably across your account. Define once what each stage means — for example, Active = placed an order in the last 30 days — and apply that definition consistently. Document the definition in the segment description so it's visible to everyone working in the account.
Contact Fields
Contact fields are used in message personalization, segmentation conditions, and API integrations. A poorly named field causes errors in all three.
Rules:
- Use
camelCasefor technical consistency, especially in integrations and personalization: first word lowercase, subsequent words capitalized. Avoid spaces, underscores, and special characters where possible. - Name the field after the data it holds, not where it came from or how it will be used.
- Be specific enough that the field is unambiguous without documentation.
- Don't store unrelated values in one field (e.g., don't combine a loyalty tier and its expiry date as a single string).
- Don't create a field for a single temporary campaign. A contact field should represent a stable attribute of the contact, not a campaign state.
| ❌ Bad | Why | ✅ Good |
|---|---|---|
plan | Ambiguous — what kind of plan? | loyaltyTier |
date | Could mean anything | lastPurchaseDate |
last | Requires context to decode | lastOrderId |
cat2 | Version number is naming debt | preferredCategory |
lang_pref | Inconsistent format | preferredLanguage |
ordersNUM | Ambiguous abbreviation | totalOrdersCount |
TotalRevenue | Uppercase first letter breaks camelCase | totalRevenue |
💡 When several fields belong to the same domain, use a shared prefix. It groups fields together in the field list and makes segmentation conditions easier to read:
loyaltyTier
loyaltyPoints
loyaltyJoinDate
loyaltyExpiryDate
Using Tags
Tags are additional labels you apply to messages, workflows, segments, and reports. They let you filter and group objects across your account without making names longer or harder to read.
Contact fields sit outside the tag system — for them, the name is the only organizational tool.
Yespo has two tag types:
- Communication tags — apply to messages, workflows, and reports.
- Segment tags — apply exclusively to segments.
Both types follow the same naming logic. Use tags for:
- Send type (triggered vs. broadcast)
- Lifecycle stage (for cross-object filtering)
- A/B experiment
- Object status
- Owner or team
Tag Naming Pattern
Follow a category_value format to keep tags scannable:
| Category | Examples |
|---|---|
| Send type | type_triggered, type_broadcast |
| Lifecycle stage | lc_new, lc_active, lc_atrisk, lc_vip |
| A/B experiment | ab_CartSubject, ab_WelcomeOffer |
| Status | status_active, status_draft, status_deprecated |
| Owner / team | team_retention, team_growth |
Avoid bare tags like active, test, or promo without a category prefix — they become ambiguous as the list grows.
If you need to mark a temporary test object, use status_draft or status_test rather than putting test in the name. Delete or archive temporary objects once testing is complete.
Marking Deprecated Objects
When a workflow, message, or segment is replaced, add status_deprecated to the old object. This keeps it findable for reference but out of your active filtered views when you filter by status_active.
Putting It Together
Here's how the conventions work across a single lifecycle flow:
| Object | Name | Tags |
|---|---|---|
| Workflow | AbandonedCart | lc_atrisk, team_retention |
| Message 1 | AbandonedCart_S01 | type_triggered, status_active |
| Message 2 | AbandonedCart_S02 | type_triggered, status_active |
| A/B variant | AbandonedCart_S02_V1 / AbandonedCart_S02_V2 | ab_CartSubject |
| Segment | AtRisk_CartAbandoned7D | lc_atrisk |
| Contact field | lastPurchaseDate | — |
Each name tells you what the object is and where it fits. Tags handle the rest — filtering by team, tracking experiments, marking what's active or deprecated.
Naming Quick Reference
| Object | Pattern | Example |
|---|---|---|
| Workflow | Stream[_Goal][_Market] | PostPurchase_UpsellAfterPurchase_DE |
| Message | Stream_Seq[_Variant] | AbandonedCart_S01, AbandonedCart_S01_V1 |
| Segment | LifecycleStage_SegmentRule | AtRisk_NoPurchase60D |
| Contact field | Descriptive camelCase name | lastPurchaseDate, loyaltyTier |
Tag Quick Reference
| Category | Format | Examples |
|---|---|---|
| Send type | type_value | type_triggered, type_broadcast |
| Lifecycle stage | lc_value | lc_new, lc_active, lc_vip |
| A/B experiment | ab_value | ab_CartSubject, ab_WelcomeOffer |
| Status | status_value | status_active, status_draft, status_deprecated |
| Owner / team | owner_value, team_value | team_retention |
Maintaining the Convention
- Assign an owner. One or two people (Marketing Ops or CRM lead) should review new objects and enforce the convention.
- Document your abbreviations. Every shorthand your team uses —
lc_,ab_,type_— should live in an internal naming dictionary so new team members can onboard without guessing. - Touch and fix. When editing an old object that doesn't follow the convention, rename it as part of the task — don't wait for a dedicated cleanup sprint.
- If you're applying these conventions to an existing account, don't rename everything at once. Start with new objects and rename old ones as you work on them. A gradual rollout is more sustainable than a one-time cleanup sprint that never gets finished.
- Archive, don't delete. When an object becomes outdated, add
status_deprecatedso it stays findable but disappears from active filtered views.
Naming conventions are not a one-time cleanup project — they're a habit that pays off the longer you maintain them. The earlier you establish a shared logic, the less time your team spends decoding names, fixing duplicate logic, or untangling analytics. Start with the object types you create most often, apply the patterns consistently, and refine as your account grows.
Updated about 2 hours ago
