← Back to blog

How to Build a SaaS Onboarding Sequence with Conversion Goals

PushMail Team··4 min read

Every SaaS has an onboarding problem. New users sign up, get a welcome email, and then... maybe nothing happens, or maybe they get five more emails whether they've completed setup or not.

The broken version looks like this: a user connects their first integration on day one, and on day seven they still receive "You haven't finished setup yet." That erodes trust. It signals that your system doesn't know what it's doing.

The fix is a sequence with a conversion goal. When the user completes onboarding, the sequence detects it and stops — automatically, with no custom logic on your end.

Here's how to build it with PushMail.

The Scenario

You're building a SaaS. When a user signs up, they need to:

  1. Connect their first integration
  2. Set up their first project
  3. Invite a teammate

You want a drip sequence that guides them through each step. But the moment they finish, you want the emails to stop. No more nudges, no awkward "you haven't finished" messages to someone who finished three days ago.

Step 1: Create the Contact at Signup

When a user signs up, add them to PushMail immediately:

curl -X POST https://pushmail.dev/api/v1/contacts \
  -H "Authorization: Bearer pm_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "email": "user@example.com",
    "firstName": "Alex",
    "lastName": "Rivera",
    "siteId": "site_abc123"
  }'

Save the returned id. You'll use it to tag the contact and trigger the sequence.

Step 2: Create the Onboarding Sequence

This is a one-time setup. You create the sequence once; it runs for every user you enroll.

The key part is goalConfig. This tells PushMail what "success" looks like — in this case, clicking a link that contains /dashboard/setup-complete.

curl -X POST https://pushmail.dev/api/v1/sequences \
  -H "Authorization: Bearer pm_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Onboarding",
    "siteId": "site_abc123",
    "triggerType": "tag_add",
    "triggerConfig": {
      "tagName": "new-user"
    },
    "goalConfig": {
      "type": "click",
      "urlPattern": "/dashboard/setup-complete",
      "action": "complete"
    }
  }'

The triggerType: "tag_add" means the sequence starts whenever a contact is tagged new-user. You control when that happens, which means you control when the sequence starts.

Step 3: Create the Sequence Steps

Five emails, spaced out over two weeks:

Step 1 — Day 0: Welcome + quickstart

curl -X POST https://pushmail.dev/api/v1/sequences/{sequenceId}/steps \
  -H "Authorization: Bearer pm_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Welcome",
    "delayDays": 0,
    "subject": "Welcome to Acme — here is how to get started",
    "templateId": "tmpl_welcome"
  }'

Step 2 — Day 1: Connect your first integration

curl -X POST https://pushmail.dev/api/v1/sequences/{sequenceId}/steps \
  -H "Authorization: Bearer pm_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Connect Integration",
    "delayDays": 1,
    "subject": "Step 1: Connect your first integration",
    "templateId": "tmpl_connect_integration"
  }'

Step 3 — Day 3: Invite your team

curl -X POST https://pushmail.dev/api/v1/sequences/{sequenceId}/steps \
  -H "Authorization: Bearer pm_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Invite Team",
    "delayDays": 3,
    "subject": "Step 2: Invite your teammates",
    "templateId": "tmpl_invite_team"
  }'

Step 4 — Day 7: Setup reminder

curl -X POST https://pushmail.dev/api/v1/sequences/{sequenceId}/steps \
  -H "Authorization: Bearer pm_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Setup Reminder",
    "delayDays": 7,
    "subject": "You have not finished setup — here is what is left",
    "templateId": "tmpl_reminder"
  }'

Step 5 — Day 14: Last chance

curl -X POST https://pushmail.dev/api/v1/sequences/{sequenceId}/steps \
  -H "Authorization: Bearer pm_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Last Chance",
    "delayDays": 14,
    "subject": "Need help getting set up? We can jump on a call.",
    "templateId": "tmpl_last_chance"
  }'

Step 4: Tag the Contact to Start the Sequence

After creating the contact, apply the trigger tag. This is what starts the sequence:

curl -X POST https://pushmail.dev/api/v1/contacts/{contactId}/tags \
  -H "Authorization: Bearer pm_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "tag": "new-user"
  }'

From this point on, PushMail handles the rest. The welcome email goes out immediately, and subsequent steps fire on their scheduled days.

How Conversion Goals Work

The goalConfig you set on the sequence is evaluated on every click event.

When a contact clicks a link in any email, PushMail's webhook processor receives the event from your email provider and checks:

  1. Is this contact enrolled in a sequence that has a goalConfig?
  2. Does the clicked URL match the urlPattern?
  3. If yes, and action is "complete" — mark the enrollment as completed.

The enrollment status changes to completed with completionReason: "goal_completed". No more emails go out to that contact for this sequence. The check happens before any subsequent step is queued.

URL matching uses "contains" mode by default — the clicked URL just needs to include your pattern somewhere in the path. You can also use "exact" mode if you need a precise match.

So in your templates, any link that sends the user to /dashboard/setup-complete acts as the goal trigger:

<a href="https://app.acme.com/dashboard/setup-complete">
  Mark setup as complete
</a>

When they click it, the sequence ends. No extra API call, no webhook handler you need to write.

Checking Goal Completion Rates

You can pull enrollment data to measure how your onboarding funnel is performing:

curl https://pushmail.dev/api/v1/sequences/{sequenceId}/enrollments \
  -H "Authorization: Bearer pm_live_..."

Filter by status to see completed vs. active vs. finished (reached the end without hitting the goal):

curl "https://pushmail.dev/api/v1/sequences/{sequenceId}/enrollments?status=completed" \
  -H "Authorization: Bearer pm_live_..."

Contacts with status: "completed" and completionReason: "goal_completed" hit your conversion goal. Contacts with status: "finished" went through all five emails without completing onboarding — those are your re-engagement candidates.

The ratio tells you where your onboarding is breaking down. If 80% complete by day three and 20% make it to day 14, you know where to focus.

Why This Matters

Without conversion goals, you have two bad options:

Option A: Send all five emails to everyone, regardless of completion status. Users who finished onboarding on day one get a "you haven't finished setup" email on day seven. Bad experience. Unsubscribes.

Option B: Build custom logic. On each email send, check your database for onboarding completion status and cancel the enrollment via API if the user is done. This is extra infrastructure, extra failure modes, and something you have to maintain.

Conversion goals eliminate option B entirely. The goal is declared once in config, evaluated automatically, and requires nothing from your application after the initial tag.

PushMail vs. ActiveCampaign and Drip

ActiveCampaign and Drip both have automation goals — you set a condition, and when a contact meets it, they exit the automation. The concept is the same.

The difference is the interface. In those tools, you configure goals in a visual builder: drag a goal block, connect it to conditions, point it at your automation. For teams that live in those UIs, that works.

PushMail's approach is API-native. There is no visual builder. You define the goal as JSON in the sequence creation request, and that's it. If you're already writing code to create contacts and fire tags, adding goalConfig is one more field in the same request. It fits into your deployment pipeline, your tests, and your version control — not into a third-party UI that lives outside your codebase.

Get Started

If you're building a SaaS and want drip sequences that actually stop when users convert, sign up for PushMail and have your first sequence running in an afternoon.

Pay per email, no subscriber fees, full API control.