DEV Community

Connor
Connor

Posted on Edited on AI-assisted

Building a Behavior-Based Email Welcome Flow Without Complex Automation

Most welcome email systems follow a predictable pattern: subscribe, receive three generic emails, then join a newsletter.

I think we can build something more useful without introducing an expensive automation platform.

Consider an application with 400 newsletter subscribers. Some are beginners, while others already understand your product. Sending identical onboarding messages to both groups wastes an opportunity to personalize communication.

Here's how I would design a lightweight, event-driven welcome sequence with three branches, five possible emails, and a few simple tags.

1. Model Subscribers With Minimal State

I would start with three tags:

  • beginner
  • experienced
  • unengaged

Each subscriber also needs signup time, email preferences, and consent information.

const subscriber = {
  id: "user_123",
  email: "user@example.com",
  tags: [],
  subscribedAt: new Date().toISOString(),
  consent: true,
  unsubscribed: false
};
Enter fullscreen mode Exit fullscreen mode

For production, I would persist this information in a database rather than storing it in memory.

2. Email 1: Capture Intent Immediately

My first email delivers whatever someone requested during signup.

Below download link, I would include two options:

  • I'm just starting out.
  • I've been doing this a while.

Each link points to an authenticated preference endpoint.

For example:

GET /preferences?choice=beginner&token=...
GET /preferences?choice=experienced&token=...
Enter fullscreen mode Exit fullscreen mode

One important detail: email security scanners sometimes follow links automatically.

I would therefore show a confirmation page before permanently updating preferences. Tokens must be signed, scoped, and expire after a reasonable period.

Actual preference changes should use a validated POST request.

3. Implement Three Branches

Once preference selection is confirmed, subscriber state determines upcoming emails.

function getWelcomeSchedule(segment) {
  const common = [
    { day: 0, template: "welcome" },
    { day: 8, template: "expectations" },
    { day: 12, template: "next-step" }
  ];

  const branches = {
    beginner: [
      { day: 2, template: "beginner-mistakes" },
      { day: 5, template: "beginner-checklist" }
    ],
    experienced: [
      { day: 2, template: "advanced-tactics" },
      { day: 5, template: "campaign-teardown" }
    ],
    unengaged: [
      { day: 3, template: "preference-reminder" },
      { day: 5, template: "general-example" }
    ]
  };

  return [...common, ...branches[segment]]
    .sort((a, b) => a.day - b.day);
}
Enter fullscreen mode Exit fullscreen mode

This function returns five scheduled messages for any supported segment.

I would initially classify subscribers without a preference as unselected, using unengaged only after a defined inactivity period.

4. Schedule Emails Reliably

For a small application, a queue worker or scheduled job is sufficient.

Every scheduled message should have a unique key:

const jobKey =
  `${subscriber.id}:${templateId}`;
Enter fullscreen mode Exit fullscreen mode

Before sending, I would check:

  1. Has this message already been sent?
  2. Is subscriber consent still valid?
  3. Has someone unsubscribed or reduced frequency?
  4. Has their preferred segment changed?

A database-backed uniqueness constraint and transactional job claiming can prevent duplicate sends across workers.

I would also suppress outdated branch messages whenever preferences change.

5. Measure Actual Engagement

Open tracking is increasingly unreliable because of privacy protections and automated activity.

I prefer measuring confirmed preference selections, meaningful clicks, replies, and unsubscribes.

Consider a hypothetical 400-subscriber cohort:

Segment Subscribers
Beginner 120
Experienced 80
No selection 200

Initial preference selection:

(120 + 80) / 400 * 100 = 50%
Enter fullscreen mode Exit fullscreen mode

If another 20 subscribers choose a preference after receiving a reminder:

220 / 400 * 100 = 55%
Enter fullscreen mode Exit fullscreen mode

That's a five-percentage-point increase in known preferences, not proof of improved revenue or retention.

For accurate reporting, I would exclude detected bot activity and track each cohort separately.

6. Avoid Overengineering

Small mailing lists rarely need complex customer-data infrastructure.

Before selecting an email service provider, I would evaluate automation support, API limits, webhook reliability, and pricing.

For additional platform context, Sprout24 maintains an independent email marketing software comparison directory.

I would also implement unsubscribe handling, bounce processing, retry limits, suppression lists, and relevant email authentication requirements before going live.

Final Thoughts

My preferred architecture is straightforward:

Signup → Welcome Email → Preference Selection → Branch Scheduling → Engagement Measurement

No complicated scoring engine is necessary.

I'd start with explicit user preferences, add behavior-based segmentation only when useful, and improve implementation using real subscriber feedback.

How would you handle preference changes while multiple email jobs are already queued?

Id be interested in comparing approaches using database jobs, queue workers, or serverless functions.

Top comments (0)