Customer.io and Courier are the two leading multi-channel orchestration tools. You design a workflow once and it fans out to push, SMS, in-app, Slack and email. Observability on push and SMS is binary: either the carrier accepted the message or it rejected it. Email has a third, nastier state: accepted by the provider, silently filed into Junk or Promotions. Your multi-channel dashboard says “delivered” and the user never sees the message.
Add seed addresses as contacts in Customer.io or Courier, target a filter that delivers only the email leg to seeds, and run that alongside your real multi-channel workflow. Push/SMS/in-app stay real-user-only; email placement gets continuous per-provider monitoring.
Why multi-channel platforms hide email problems
A multi-channel workflow is typically designed as “reach-the-user-on-any-channel”. The UI celebrates reach: 100% of your users got something. The problem is that for a user who has push disabled and ignores SMS, the email is the channel that actually had to work — and that user has no idea they are missing your email because it landed in Junk.
Customer.io's metrics and Courier's logs both show email as “delivered” if the SMTP 250 came back. They cannot see folder. Push and SMS have delivery receipts with finer granularity — and that creates a false sense that the whole workflow is instrumented. It is not. Email is the unlit room.
Design pattern: email-only seed branch
The anti-pattern is sending push + SMS + email to seed addresses — seeds are email mailboxes, they cannot receive push or SMS and the workflow will error or silently drop those legs. The clean pattern is a branch in the workflow that filters channels per audience.
- Tag seeds clearly. Add an attribute
is_seed(or a segment membership) on every seed contact. In Customer.io use traits; in Courier use recipient profile fields. - Branch the workflow. Add a conditional split on
is_seed == true. The seed branch delivers only the email channel. The real-user branch delivers the full multi-channel experience. - Share the email content. Both branches point at the same email template. The seed's placement reflects exactly what a real user sees.
- Read per-provider placement. The placement-check tool shows you per-provider folder within minutes of the workflow firing.
Customer.io: gating channels with Liquid
Customer.io uses Liquid for conditions. Gating push and SMS so seeds only receive email:
{%- comment -%}
Only deliver Push if this is NOT a seed contact.
Seeds are email-only; attempting push will error.
{%- endcomment -%}
{% if customer.is_seed %}
{% abort_message "Skipping Push for seed contact" %}
{% endif %}Drop that into the push channel's pre-send Liquid (or the “Stop Sending” condition). Repeat for SMS. The email channel has no filter and delivers normally. Seeds traverse the workflow end-to-end, but only the email leg actually sends.
Courier: channel routing per profile
Courier's routing lets you express the same rule via channel selection:
{
"message": {
"to": { "user_id": "seed_gmail_01" },
"template": "onboarding-day-1",
"routing": {
"method": "all",
"channels": ["email"]
},
"data": { "is_seed": true }
}
}Seeds get sent with routing.channels: ["email"]; real users get the default multi-channel routing. Same template, same substitution data, same delivery pipeline.
Per-campaign seed monitoring at multi-channel scale
Multi-channel campaigns fire at high volume with many entry points. Putting seeds on every single message will flood your inbox; the right model is sampling plus pre-flight.
- Pre-flight seed before launching a new workflow. Before turning the workflow on for real users, run it with only the seed segment as the audience. Read email placement. Fix any Spam results before green-lighting.
- Sampled seed on running workflows. Add seeds to 1–5% of triggers on long-running lifecycle workflows. Low enough to be invisible in cost, high enough to catch drift within a day.
- Incident seed. When customer support flags “I never got the email”, fire the workflow manually against the seed segment and check placement now, not two days later when Customer.io logs finally surface.
The free Inbox Check tool generates 20+ fresh seed addresses per test across Gmail, Outlook, Yahoo, Mail.ru, Yandex, ProtonMail and more. No signup, no credit card.
What multi-channel dashboards miss
Customer.io's Delivery report and Courier's Logs view are excellent at what they track. What they do not track:
- Folder placement. Both platforms see SMTP 250 as “delivered”. Gmail Promotions, Spam and Primary all look identical from the platform's view.
- Per-provider asymmetry. A campaign may land Primary on Gmail and Junk on Outlook. Neither platform surfaces this unless you add seeds that span both.
- Deliverability drift over time. Yesterday's onboarding email was Primary; today it slid to Promotions. Only a seed monitor watching day-over-day placement will detect the drift early.
- Authentication alignment. A DKIM signature that passes verification but does not align with the From: domain will still show as “delivered”. Seeds in an authentication-aware provider (like SendForensics-style headers view) expose it.
Common mistakes multi-channel teams make
- Adding seeds to push/SMS audiences. Seeds are email addresses. Pushing to a seed contact will either error or silently drop, polluting your delivery metrics.
- Forgetting to branch at workflow level. Seeding at the audience level without a channel filter means seeds trigger push and SMS nodes too — and those nodes error. Always split on
is_seedat the workflow entry. - Treating a push delivery receipt as workflow success. Your push partner returns “delivered”, so the workflow looks healthy. Meanwhile 30% of your email leg is in Junk and your re-engagement curve is quietly dying.
- One-off pre-flight only. Running a seed before the launch is table stakes. The interesting signal is drift over weeks — keep sampled seeds on continuously.