Automation Workflows

Automating a Customer Onboarding Sequence Step by Step

A real build of a five-step onboarding automation, including the exact trigger and condition logic behind each step, not just "send a welcome email."

By Aissam Ait Ahmed Automation Workflows 0 comments

Most articles about onboarding automation stop at "set up a welcome email and then a drip sequence." That's not a workflow, it's a scheduling problem. A real onboarding automation has to make decisions: has this person actually done anything since signing up, and if not, does an email even make sense anymore, or does a human need to step in? Here's the sequence I built for a B2B SaaS trial flow, with the actual logic behind each step.

The onboarding problem I was solving

The product had a healthy signup rate but a mediocre trial-to-paid conversion rate, and support kept hearing the same thing from lost trials: "I signed up, got busy, and forgot the tool existed." The fix isn't more emails — it's emails and interventions that are conditional on what the user has actually done, sent at the moment they're likely to matter, with a clear point where automation hands off to a human being instead of continuing to talk to an inactive inbox.

Step 1: trigger on signup, not on "add to list"

The trigger was a webhook fired by the application itself the moment a trial account is created, carrying the user's email, name, plan tier, and a timestamp. This matters more than it sounds: a lot of onboarding automations trigger off "contact added to email list," which introduces a delay and decouples the automation from the actual product event. If the CRM sync that adds the contact to the list runs on a 15-minute batch job, your "instant" welcome email is now instant-ish, and the day-3 check-in timestamp is calculated from the wrong moment.

Step 2: the welcome email logic

The welcome email itself isn't interesting — what's interesting is the condition attached to it. Before sending, the workflow checks the plan tier field from the signup payload. Free-trial signups on the entry plan get a short, single-CTA email pointing at the one setup action that correlates most with retention (in this case, connecting a data source). Signups on a higher tier, which in this product usually meant a slightly more sophisticated buyer, got a different email offering a 15-minute onboarding call instead of a self-serve checklist. Same trigger, branched by one field, two very different next steps. That branch alone did more for conversion than any copywriting change to the email itself.

Step 3: day-3 check-in and the condition that actually matters

Three days after signup, the workflow doesn't just fire an email — it first checks a product usage flag: has the user completed the core setup action from step 2? This requires the automation tool to query the product's API (or a synced field in the CRM/database that the product updates) rather than relying on email engagement data, because open and click rates tell you about the email, not about the product.

  • If the setup action is complete, the day-3 message shifts to a "next step" nudge pointing at a secondary feature, because this user is engaged and the goal now is depth, not activation.
  • If the setup action is incomplete, the day-3 message is a short, specific nudge addressing the most common blocker at that exact step, not a generic "still there?" email.
  • If the account shows zero logins since signup, the day-3 email is skipped entirely and replaced with a shorter one-line re-engagement message, because a wall of onboarding content to someone who hasn't opened the product once is noise.

How the usage check actually queried the product

"Check if the user completed setup" sounds like one condition, but building it meant deciding what "setup" actually meant in database terms, and that took longer than building the rest of the branch. The product team's first answer was "check if they connected a data source," but a data source connection could exist and still be broken (bad credentials, an empty sync), which would have counted plenty of genuinely stuck users as activated. I ended up querying two fields together: a `data_source_connected` boolean and a `first_successful_sync_at` timestamp, and only treated the user as activated if both were true. That distinction mattered in practice — roughly a fifth of the accounts that had "connected" a source in the narrow sense had never actually gotten a successful sync, and the old, looser definition would have silently routed all of them into the wrong branch, sending a feature-adoption email to someone whose core setup was actually broken.

Step 4: day-7 usage nudge, branched by behavior

By day 7, the workflow re-checks the same usage flag plus a login-recency field. This is where most templated onboarding sequences just send "day 7 email" regardless of context, and it's the biggest missed opportunity in the whole sequence. My version split into three paths: users who completed setup and logged in within the last 3 days got a feature-adoption email; users who completed setup but hadn't logged in recently got a "pick up where you left off" email referencing their specific configured setup, pulled via a merge field from the product API; users who never completed setup by day 7 skipped the email track entirely and moved to step 5.

Step 5: escalate to a human when the automation should stop

This is the step that's almost always missing from "automated onboarding," and it's the one that actually protects revenue. Any trial account that reaches day 7 with zero setup completion and a plan tier above the entry level gets flagged — not emailed again, flagged. The automation creates a task in the CRM assigned to a rep, posts a summary to a Slack channel with the account's signup details and usage data, and stops sending automated emails to that contact entirely. The logic explicitly treats "the automation isn't working for this person" as a valid, expected outcome that requires a different kind of response, not a reason to send one more email hoping this time it lands.

For entry-tier accounts, where a 1:1 human touch doesn't make financial sense at scale, the equivalent "give up gracefully" step is a single low-pressure email offering a short video or help article, sent once, with no further automated follow-up until the trial expiry reminder.

What broke when I first shipped this

The first version of this sequence had a bug that took nine days to notice: the day-3 and day-7 usage checks were both querying the product API for a "setup_complete" field, but that field was set by a background job that ran on a delay of up to a few hours for accounts created near the top of the hour. For a small number of users, the day-3 check fired before the field had updated, so they got the "not activated" branch even though they'd technically finished setup minutes earlier. The fix was adding a short buffer — checking usage 15 minutes before the nominal 3-day mark against data as of 3 days minus that buffer — but the real fix was realizing I needed to actually watch what the automation was doing for a sample of real accounts, not just trust that the logic diagram was correct. That experience is a big part of why I now treat "did the branch actually fire the way I expected" as a thing to verify weekly, not something you set up once and trust forever — a habit covered in more detail in why onboarding and other automations fail without throwing an obvious error.

What changed after this actually shipped

I'm wary of automation write-ups that lead with a suspiciously tidy percentage, so here's the honest version: trial-to-paid conversion improved after this shipped, but so did two other things around the same time — a pricing page redesign and a change to the trial length — so I can't credit the automation alone with any specific number, and I'd be skeptical of anyone who claims they can isolate it that cleanly from a single change in a live product. What I can say with more confidence, because it's directly observable rather than inferred, is that support tickets referencing "I forgot I signed up" dropped noticeably, and the sales team started reaching out to stalled trial accounts on day 7 or 8 instead of day 20 or not at all, simply because the Slack alert put the account in front of them at the right moment instead of relying on someone remembering to check a report.

The other honest caveat: this sequence needed real tuning after launch, not because the logic was wrong but because the specific thresholds were guesses. Three days turned out to be slightly too early for the check-in on the higher-tier plan, where the onboarding call itself often didn't get scheduled until day 4 or 5, so that branch's timing got pushed to day 5 for call-offer signups specifically. Nothing about the underlying framework changed — only the number of days in one condition — which is exactly the kind of small, low-risk tuning an automation should make easy.

The full logic, condensed

Written out as trigger-condition-action, the sequence looks like this:

TRIGGER: webhook on trial_account_created

STEP 1 (immediate):
  IF plan_tier = "entry" -> send welcome_email_selfserve
  IF plan_tier > "entry" -> send welcome_email_call_offer

STEP 2 (day 3, minus 15 min buffer against day-3 usage snapshot):
  IF setup_complete = true -> send nudge_secondary_feature
  IF setup_complete = false AND last_login within 3 days -> send nudge_specific_blocker
  IF last_login = null -> send reengage_short

STEP 3 (day 7):
  IF setup_complete = true AND last_login within 3 days -> send feature_adoption_email
  IF setup_complete = true AND last_login > 3 days ago -> send resume_configured_setup_email
  IF setup_complete = false -> go to STEP 4

STEP 4 (day 7 escalation):
  IF plan_tier > "entry" -> create CRM task + Slack alert to rep, stop automated emails
  IF plan_tier = "entry" -> send single low_pressure_help_email, stop automated emails

One practical detail worth building in from the start: every link inside these emails should be trackable back to the exact step and variant that sent it, so when you're debugging conversion later you know whether the day-3 "specific blocker" email is actually getting clicked. I ran every outbound link through the URL Shortener with a distinct slug per email variant, which made it trivial to see click-through per branch without needing full marketing-automation-suite analytics bolted on.

Before automating any of this, it's worth being honest about whether the process is stable enough to automate yet — I go into that decision in more depth in when to automate a process versus leave it manual, because an onboarding sequence built on top of a product flow that's still changing every two weeks will need constant rework, and that cost is easy to underestimate at the start.

Comments

Join the conversation on this article.

Comments are rendered server-side so the discussion stays visible to readers without relying on a separate widget or client-side app.

No comments yet.

Be the first visitor to add a thoughtful comment on this article.

Leave a comment

Share a useful thought, question, or response.

Be constructive, stay on topic, and avoid posting personal or sensitive information.

Back to Blog More in Automation Workflows Free Resources Explore Tools