---
title: "How do you chain email sequences so that what a prospect does decides what happens next?"
blueprint: 016
slug: chaining-email-sequences-on-engagement
category: Outreach
revised: 2026-09-21
platform: Coevera CRM (formerly Pipeliner CRM)
canonical: https://blueprints.coevera.com/blueprints/chaining-email-sequences-on-engagement/
publisher: Coevera
customer_data: none
---

# How do you chain email sequences so that what a prospect does decides what happens next?

**Short answer.** **An email sequence is a closed loop.** It enrols a record, sends its steps, and
ends. There is no node that enrols anyone into *another* sequence — so a multi-stage ladder cannot
be built out of sequences alone.

What a sequence does have is **global actions**: hooks that fire on **reply**, **unsubscribe**,
**bounce**, and a **custom condition** — the last being how an open or a click is caught. Each can
create a record from a template. So the chain is built like this: the sequence **creates a task
carrying a pointer to the next sequence**, and a catcher process triggered on task creation writes
that pointer onto the contact and re-enrols. **The task is the message bus** between two sequences
that cannot see each other.

The warning that matters more than the mechanism: those tasks are **bookkeeping, not work**. Build
the ladder so that nothing ever asks a human to act, and a stalled campaign becomes invisible —
hundreds of activity records, nobody to notice.

## 01 · The business problem

You have a list of people worth contacting and a message worth more than one send. A single email
is ignored; five identical ones are spam. What you actually want is a ladder where **behaviour
decides the rung**:

- somebody who **replies** should stop receiving the campaign immediately and reach a person;
- somebody who **opens or clicks** has shown interest and should get the next, different message;
- somebody who **never engages** should progress on a timer, or stop;
- somebody who **unsubscribes or bounces** should be suppressed everywhere, permanently;
- and you should be able to answer **"is this campaign still running?"** without opening five
  screens.

The first four are mechanism. The fifth is the one that decides whether the machine is worth
having, and it is the one that is almost never built.

## 02 · Why the obvious approach fails

### One long sequence with every step in it

The simplest reading of "multi-touch campaign" is one sequence with ten steps. It sends on a timer
and it cannot branch: a recipient who clicks at step two receives step three exactly as though
they had not. The only behavioural lever a sequence has over its own flow is **unenrol** — it can
stop, but it cannot turn.

### Expecting a sequence to hand over to another sequence

The next idea is a set of short sequences with the last step of each enrolling into the next.
There is no such step. A sequence's nodes send emails, wait, and create records — **enrolment into
a sequence is not an action a sequence can take**. Nothing in the editor hints at this until you
look for the node and find it absent.

### Sweeping with a scheduled process instead

A daily scheduled process over contacts, moving anyone whose engagement changed, does work — and
throws away the thing that made this worth doing. Engagement is an **event**: opened at 09:14,
clicked the pricing link, replied. A nightly sweep sees only state, arrives up to a day late, and
cannot tell you *which* message produced the reaction.

### Letting the catcher fire for anybody

Once the task-based chain is built, the catcher process watches task creation. Leave its actor at
**any user** — the default reading of "when a task is created" — and every task a salesperson
creates by hand is evaluated by the campaign machinery. The fix is a single setting, and §05 is
about why it is not optional.

## 03 · Data model

Three objects and one convention carry the whole design.

| Piece | Role |
|---|---|
| **Email sequence** | Sends the steps. Ends. Cannot chain |
| **Task** (created by a global action) | **The message.** Carries the pointer to the next sequence |
| **Catcher process** | Triggered on task creation; writes the pointer onto the contact and hands off |
| **Step counter** on the contact | Which rung the contact is on. The enrolment process branches on it |

### What a sequence enrols, and on what

A sequence's trigger names an **entity type** and a specific **field id** — the email field it
sends to — with an optional **lookup** so it can reach an address on a related record. That detail
matters more than it sounds: a sequence enrolling leads can send to the primary contact's email
through the relation, which is why the enrolled record and the addressee need not be the same
thing.

### The settings that bound a sequence

| Setting | What it does |
|---|---|
| `timezone`, `dayOfWeek`, `fromTimeOfDay`/`toTimeOfDay` | Sending window — sends are held outside it |
| `activeFrom`, `activeTo` | Campaign life, as dates |
| `autoUnenrollWhenExpired` | Whether anyone still in flight is released when it expires |
| `everyEmailStartsConversation` | Whether each send opens a new thread or continues one |
| `triggerProcess`, `triggerProcessId` | **The named catcher.** One process per sequence |

### Why the message has to be a record

A global action can create a **task**, a **lead**, or a text — and the statistics count each
separately. A task is the right carrier here because it is cheap, it attaches to the contact, it
holds custom fields, and its creation is a trigger surface. The pointer rides in one of those
fields.

> **The rejected alternative.** The tidy instinct is a counter the chain increments — step 1
> becomes step 2 becomes step 3. What a real ladder does instead is have each sequence **name its
> successor**, because the task template is where the value is written and the template is per
> sequence. That makes the chain a set of hard-coded pointers, which is more flexible (a branch
> can skip a rung) and more fragile (§06).

## 04 · Field-level configuration

### The four global actions, in full

These are the sequence's only behavioural hooks. There are exactly four events:

| Event | Unenrol | Send a different email | Create a record | Also |
|---|---|---|---|---|
| **On reply** | ✅ | ✅ | ✅ | — |
| **On unsubscribe** | implicit | — | ✅ | — |
| **On custom condition** | ✅ | ✅ | ✅ | **takes a filter** |
| **On bounce** | ✅ | — | — | **can unsubscribe the recipient** |

Each is a flag plus its payload — a reply can unenrol, send a holding reply, and create a task,
independently of one another.

### The custom condition is where opens and clicks live

Reply, unsubscribe and bounce are fixed events. **Open and click are not events you subscribe to**
— they are conditions you describe. The custom condition takes an ordinary filter, and the working
shape is two clauses:

```
Message.subject         Is  "{the subject of the step you are watching}"
Email.tracking_status   Is  Opened  OR  Clicked
```

The subject clause is what scopes the condition to *one step* of the sequence rather than any
message ever sent. It also means **editing a step's subject line silently breaks the condition
watching it** — the filter still matches a string nobody sends any more.

### The pointer and the counter

| Field | Lives on | Written by | Read by |
|---|---|---|---|
| Next-sequence pointer | Task | The sequence's task template | The catcher |
| Step counter | Contact | The catcher (and the entry process, once) | The enrolment process's branches |
| Campaign membership | Contact | The entry process | Every gate in the chain |
| Suppression flags | Contact | Unsubscribe, bounce, or a person | Every gate in the chain |

**Name the pointer field for what it does.** It is the single most load-bearing value in the chain
and the easiest to mistake for something harmless — §06 has the consequence.

### A note on boolean conditions in filters

Suppression gates test booleans, and a boolean "is false" test is stored with **no operator at
all** — `operator: null` with a value of `0`. This is consistent wherever booleans are filtered,
so a rule with a null operator against a checkbox field is normal rather than broken. It is worth
knowing before you go hunting for a missing operator that was never meant to be there.

## 05 · Automation & logic

### The catcher, and the setting that makes it safe

One process, triggered on **task creation**, reads the pointer and routes. Its trigger actor is
the part to get right. A record trigger's actor takes one of four values:

| Actor | Fires when the record is created by… |
|---|---|
| `AnyUser` | anyone at all — **including a person** |
| `ProcessOwner` | the process's own owner |
| `SelectedUnitsAndUsers` | a named set of units or users |
| **`ApplicationsOnly`** | **automation only — never a human** |

**Applications-only is the correct choice for a catcher**, and it is the difference between a
closed loop and one anybody can accidentally push someone into. A salesperson logging a call
should not re-enrol a prospect in a drip campaign.

### The route, end to end

```
sequence step / global action fires
  └─ creates Task  { pointer = "next sequence" }
       └─ catcher process  (Task · Create · ApplicationsOnly)
            ├─ filter: task activity type is an engagement type
            ├─ filter: pointer is not empty
            ├─ filter: contact is in this campaign, not unsubscribed, not archived
            └─ write Contact.step_counter = Task.pointer
                 └─ hand off to the enrolment process
                      └─ branch on step_counter → enrol into that sequence
```

The hand-off at the end is a sub-process call, which is how anything crosses a process boundary
here — the constraint and the naming discipline are in [Blueprint
011](https://blueprints.coevera.com/blueprints/keeping-hundreds-of-automations-maintainable/).

### The shared enrolment ladder is the fragile part

In practice the enrolment process is not built per campaign — it accumulates. One production
example carries dozens of unrelated campaigns in a single process of over a hundred nodes, with
one campaign's gate sitting nineteen deep. Because a filter is one gate whose branches are
**first-match-wins**, a contact's enrolment depends on its position relative to nineteen campaigns
it has nothing to do with. Anything that makes an earlier gate match first silently removes the
later one from reach.

Give a campaign its own enrolment process when it matters. The shared ladder is convenient once
and expensive thereafter.

### Make one rung produce work

The whole chain above is machinery. Somewhere in it, **one branch must create a task a person is
actually expected to do** — open, assigned to a real owner, with a due date. The obvious candidate
is the reply hook, and the next is a click on something commercially meaningful. [Blueprint
014](https://blueprints.coevera.com/blueprints/customer-health-score-churn-risk/) makes the same
argument from the other side: automation should route attention to a human, and a human should be
the one who commits.

## 06 · Limits & trade-offs

> **A completed task is not work.** Where every task template is created with a status of
> already-completed, owned by a single administrator, and consumed by a process that accepts only
> automation, the ladder produces **activity records and no work items**. It is easy to do by
> accident, because the tasks exist to carry a value rather than to ask anybody anything — and the
> result is a campaign that looks busy in every report and asks nothing of anyone.

- **Because nothing asks, nothing notices.** Observed on a live ladder: a cohort parked at the
  first step for months, with no recorded response, no meeting and no disqualification against any
  of them. The chain was working; the feed into it had stopped. Nothing reports the absence of new
  records, because an empty campaign and a quiet week are the same shape — the same failure class
  as the replication outage in [Blueprint
  009](https://blueprints.coevera.com/blueprints/automating-on-integration-owned-fields/).
- **A misnamed pointer field is a live wire.** A field labelled as a duration in minutes, carrying
  the number of the next sequence, is doing the most consequential job in the chain under a name
  that invites edits. Anyone who changes it — a person tidying a task, or any future automation
  touching a field of that name — silently reroutes contacts into a different campaign. Name it
  for its function, and treat any short generic label on a control field as a defect waiting to
  happen.
- **The ladder can terminate on a setting rather than on its data.** A final sequence whose task
  template still points back to an earlier rung, and which stops only because its create-task flag
  is switched off, is **one checkbox away from an infinite loop**. Make the last rung's pointer
  terminal in the data — zero, or a value no branch matches — so that turning the flag on is safe.
- **Nothing advances the counter except engagement.** The entry process writes step one; only the
  catcher moves it on. A contact who never opens, clicks or replies stays at step one forever —
  correct behaviour, and invisible unless someone reports on it.
- **Editing a subject line breaks the condition that watches it.** The custom condition matches on
  the subject string, so a copy tweak silently detaches the hook. Nothing fails; the rung simply
  stops catching anybody.
- **Bounce handling burns addresses permanently.** On-bounce can unsubscribe the recipient, which
  is right for deliverability and unforgiving of a bad list: a poorly validated import suppresses
  a chunk of itself on first contact, and those contacts are then excluded from every future
  campaign by the same suppression gates. Validate before the first send — [Blueprint
  005](https://blueprints.coevera.com/blueprints/contact-migration-without-data-loss/) covers what
  an unvalidated import looks like.
- **Statistics are per sequence, not per chain.** Each sequence reports enrolments, sends,
  recipients, opens, clicks, replies, bounces, unsubscribes, created tasks and leads, and a
  **current-enrolment count** — but nothing aggregates a ladder. The health of the campaign as a
  whole has to be assembled by hand from five screens, which is exactly why nobody does it.

### The trade-off worth stating plainly

Building the ladder from tasks buys real behavioural branching on a platform whose sequences
cannot branch, using nothing but native parts. What it costs is that the chain's logic lives in
three places at once — the task template inside each sequence, the catcher's filters, and the
enrolment process's gates — and no screen shows all three together. That is survivable with a
naming convention and a diagram, and unsurvivable without. If the campaign is genuinely linear and
nobody needs to branch on behaviour, one sequence with more steps is the honest answer and costs a
fraction as much to keep alive.

## 07 · Verification

Read from a live production space: a five-rung sequence ladder, its catcher process, the shared
enrolment process, and the schema behind all three.

- **The global-action set was read from the schema**, confirming exactly four events — reply,
  unsubscribe, custom condition, bounce — with their independent unenrol, send-email and
  create-record flags, that only the custom condition carries a filter, and that bounce alone
  offers to unsubscribe the recipient.
- **The custom condition was read from a live sequence:** a subject-line clause combined with an
  email tracking status of opened or clicked.
- **The sequence settings** — sending window, timezone, active-from and active-to, auto-unenrol on
  expiry, every-email-starts-conversation, and the named trigger process — were read from the
  schema and confirmed populated on live sequences.
- **The catcher was traced in production:** triggered on task creation with actor
  `ApplicationsOnly`, filtering on engagement activity type, a non-empty pointer and the contact's
  campaign membership and suppression flags, then writing the pointer onto the contact and handing
  off.
- **The four actor values were confirmed from the enum**, as were the trigger events, which
  include email-sent and email-received alongside create, update and delete.
- **The ladder's pointer scheme was read from the task templates** — each rung writing the number
  of its successor, and the final rung still carrying a pointer back to an earlier one while
  relying on a switched-off flag to terminate.
- **The shared enrolment process was measured:** over a hundred nodes, dozens of unrelated
  campaigns in one first-match-wins ladder, one campaign's gate nineteen deep, and the process
  itself carrying a warning status.
- **The null-operator boolean convention was confirmed** across three independent processes: a
  boolean "is false" test stores no operator and a value of zero.

**Not observed, and stated as such:**

- A sequence sending during this work. Every finding is read from stored configuration and stored
  statistics, not from a campaign run for the purpose.
- What happens if the final rung's create-task flag is switched on — the loop is inferred from the
  stored pointer value, not watched.
- Whether editing a step's subject line detaches the custom condition, which follows from the
  filter's shape but was not tested.
- The behaviour of the lead and text record types a global action can create; only the task path
  was traced.

### What would signal a regression

- **Every sequence in the ladder reporting zero current enrolments.** The single cheapest health
  check, and the only one that distinguishes "nobody is in flight" from "nobody has engaged yet".
- **Tasks accumulating while the step counter stays at one.** The catcher is firing and the
  hand-off is not, so contacts are being marked and never moved.
- **A rung's created-task count falling to zero while sends continue.** Its custom condition has
  stopped matching — most often because a subject line was edited.
- **Any human-owned open task of the campaign's activity type.** Either the catcher's actor has
  been loosened off applications-only, or somebody is working inside the machine's task types, and
  both will produce surprising enrolments.

## Related blueprints

- [Blueprint 011 — How do you keep hundreds of CRM automations
  maintainable?](https://blueprints.coevera.com/blueprints/keeping-hundreds-of-automations-maintainable/)
  — first-match-wins filters and sub-process hand-offs, which this chain is built from.
- [Blueprint 014 — How do you spot customers at risk of churning before
  renewal?](https://blueprints.coevera.com/blueprints/customer-health-score-churn-risk/) — the
  same argument from the other side: automation routes attention, a person commits.
- [Blueprint 009 — How do you automate on CRM fields that another system
  owns?](https://blueprints.coevera.com/blueprints/automating-on-integration-owned-fields/) — why
  a stopped feed is silent rather than broken.
- [Blueprint 005 — How do you migrate contacts from another system without silently losing
  data?](https://blueprints.coevera.com/blueprints/contact-migration-without-data-loss/) — what an
  unvalidated list does on first contact.

---

Published by Coevera. Abstracted to the reusable pattern — no customer names, no client
data, no personal data.
