Loading tutorials…
Loading tutorials…
Customer.io rewards careful account setup. Identifier strategy, sending domains, and workspace/environment splits decided in week one save SaaS teams months of cleanup later. This is the build that scales past 100K users.
Who this is forSaaS founders, lifecycle marketers, and growth engineers spinning up Customer.io for the first time — or operators who inherited a messy workspace and want to know what 'right' looks like. If you're under 10K users you can take shortcuts; past that, every decision below compounds.
What you'll need
Step 1
Settings → Workspaces. Most SaaS teams want two workspaces: Production and Staging. Don't try to fake it with segments.
After sign-up, you land in a default workspace. In Settings → Workspaces, rename it to 'Production' so it's obvious.
Create a second workspace called 'Staging' (or 'Dev'). On Premium and above this is included; on Essentials you can use a separate free account.
Why two workspaces, not one workspace with a 'test' segment: API keys, sending domains, in-app credentials, and webhooks are all workspace-scoped. Mixing test traffic with production data risks accidentally messaging real users during development.
Wire your staging product environment to Staging, production to Production. The Track API site_id + api_key are different per workspace — keep them in env vars (CUSTOMER_IO_SITE_ID, CUSTOMER_IO_API_KEY) and never hardcode.
Optional: a third 'EU' workspace if you serve EU users — Customer.io has a separate EU region (track-eu.customer.io) for data residency.
Step 2
Settings → Workspace Settings → Identifiers. Choose `id` (your internal user_id) as primary. Email is secondary. This is the most important setup decision.
Settings → Workspace Settings → Identifiers (or 'People settings' depending on UI version).
Set the primary identifier to `id` — meaning Customer.io will store each user keyed off your internal user_id (UUID, integer, whatever your DB uses). Email is a profile attribute, not the primary key.
Why: in SaaS, users change email addresses (work email → personal email, name changes, account merges). If email is the primary key, the same human gets two Customer.io profiles and workflow attribution splits. If user_id is primary, the profile follows the human regardless of email changes.
Caveat: if you're an e-commerce / newsletter use case where you only ever know the email (no logged-in user_id), email-as-primary is fine. For SaaS with authenticated users, always pick user_id.
Enable 'CIO Identify on email' so anonymous email-collected leads (from marketing pages, lead magnets) get matched to user_id once they sign up. This is the 'cio_id' merge feature — turn it on now, not later.
Step 3
Content → Settings → Email Settings → Sending Domains. Add a subdomain like `mail.yourapp.com`. Set up all four DNS records before sending one campaign.
Content → Settings → Email Settings → Sending Domains → Add new domain. Use a subdomain (`mail.yourapp.com`, `notifications.yourapp.com`, or `e.yourapp.com`) — never your root domain.
Customer.io generates 3-4 DNS records: 2 DKIM CNAMEs, 1 SPF (TXT include), and a Return-Path CNAME. Add all of them to your DNS provider verbatim.
Add DMARC separately at the root domain: TXT record at `_dmarc.yourapp.com` with `v=DMARC1; p=quarantine; rua=mailto:dmarc@yourapp.com;`. Start with `p=quarantine` (not `p=none` and not `p=reject`).
Wait 10-30 minutes for DNS to propagate. Click "Verify" in the Customer.io UI. All four should turn green. If DKIM stays red, the record probably has a typo or your DNS provider is wrapping the value in quotes that need stripping.
Test with mail-tester.com: send a real test broadcast to a mail-tester address. You want 9.5+/10. Anything below 9 means an auth record is misconfigured.
Step 4
Settings → Members → Invite. Don't give everyone Admin. Customer.io has fine-grained roles per workspace.
Settings → Members → Invite member. Add by email.
Choose role per workspace: Admin (everything including billing), Editor (build campaigns, edit segments, no billing/auth changes), Read-only (view-only).
Per-workspace assignment matters: someone can be Admin on Staging and Editor on Production. Use this to give engineers more freedom in Staging without risking Production.
Set SSO if you're on Premium+: Settings → SSO → SAML setup. Worth doing on day one if your company uses Okta/Google Workspace SSO. Adding it later means migrating every existing user.
Audit access quarterly. Most accounts accumulate ex-employee Admin access for years — high security risk.
Step 5
Customer.io needs to see your users. Either wire the Track API directly, or — on Premium+ — use a Data Pipeline Source (covered in a separate tutorial).
Get the Track Site ID + API Key: Settings → API Credentials → Track API.
In your app backend, install the Customer.io SDK (Node, Python, Ruby, Go, etc.) or call the REST API directly: `POST https://track.customer.io/api/v1/customers/{id}` with the user attributes.
On user signup, fire an `identify` call with their user_id, email, name, plan, created_at, and any other attributes you'll want to segment on later. Don't be stingy — add attributes liberally; storage is cheap.
On every meaningful product event (account_created, feature_used, plan_upgraded, invite_sent, etc.), fire a `track` event with the event name + properties.
Verify: in Customer.io → People → find your test profile by user_id. Confirm the identify call landed, attributes populated, and event timeline shows the test event.
Step 6
Confirm sending works end-to-end before you ever build a workflow. Send a Broadcast and a transactional message to yourself.
Newsletters: Customer.io → Newsletters → + Create Newsletter. Pick an audience (your test segment or yourself by user_id). Build a simple email. Send to yourself.
Verify the email arrives. Check headers: From should be `your-from-address@mail.yourapp.com`, DKIM should pass, SPF should pass.
Then test transactional: Content → Transactional Messages → + Create. Build a simple transactional template. Call its API endpoint from your backend (curl works) with a test user. Verify delivery.
Healthy benchmark for a brand-new domain: arrives in Inbox (not Promotions, not Spam) at Gmail, Outlook, Apple Mail. If it lands in Promotions for Gmail, that's fine for marketing but a problem for transactional. Open a deliverability ticket if transactional lands anywhere but Inbox.
Step 7
Final pre-launch checklist: data retention, suppression imports, IP allowlists, and webhook event logging.
Settings → Privacy & Compliance → confirm data retention defaults match your contract (most plans default to 'forever' for people, 13 months for event data — adjust if needed).
Import existing suppression list: if migrating from Mailchimp, Klaviyo, Iterable, etc., export the suppression/unsubscribe list and upload to Customer.io → Settings → Suppression List. Without this, you risk emailing people who already opted out elsewhere.
Enable Reporting Webhooks: Settings → Webhooks → + Create. Forward all email events (delivered, opened, clicked, unsubscribed, bounced) to your data warehouse or to Mixpanel/Amplitude for full attribution.
If you're on Enterprise, set IP allowlists on the API. Belt and suspenders for the API key.
Document everything in a runbook: workspace IDs, API keys (in your secrets manager, not the runbook), sending domain, identifier choice, environments map. Future you (or your replacement) will thank you.
Common mistakes
Using email as the primary identifier in a SaaS workspace
What goes wrong: Users with multiple emails (work + personal + alias) get split into 2-3 profiles. Workflow attribution splits. Activation funnels look broken. Typically loses 10-20% of activation revenue signal — for a $200/mo SaaS, that's $4K-8K/mo of attribution you can't trust.
How to avoid: On day one, set primary identifier to `id` (user_id). Email is a profile attribute. Already past day one? Hire a specialist for the merge migration — DIY merges have a 30%+ data-loss rate.
Sending from the root domain instead of a subdomain
What goes wrong: Marketing reputation contaminates transactional reputation. One bad campaign sends password-reset and billing emails to spam. SaaS churn spikes when users can't reset passwords. $2K-15K/mo of recovery revenue evaporates while the team scrambles to fix DNS.
How to avoid: Set up `mail.yourapp.com` or similar subdomain in Customer.io → Email Settings → Sending Domains. Migrate marketing to the subdomain. Keep transactional on a separate subdomain (e.g., `notify.yourapp.com`) for full isolation.
One workspace for both staging and production
What goes wrong: QA team accidentally blasts production users with test campaigns. Or worse: dev environment events pollute production user profiles, breaking workflow triggers. Either incident typically costs $5K-20K in opt-outs + ESP reputation damage.
How to avoid: Create separate Production and Staging workspaces. Different API keys per workspace. Wire backend env vars to switch. 2-hour setup, prevents 6-figure incidents.
No DMARC, or DMARC at p=none forever
What goes wrong: Without DMARC at p=quarantine or stricter, spoofing your domain is trivial. Phishing emails impersonating your app erode user trust and brand. Gmail's 2024 sender requirements also penalize p=none senders sending >5K/day with downranked inbox placement.
How to avoid: Add DMARC TXT at `_dmarc.yourapp.com` with `p=quarantine; rua=mailto:dmarc@yourapp.com`. Monitor reports for 30 days, then escalate to `p=reject`. Gmail and Yahoo now require DMARC for bulk senders — non-compliance drops Inbox placement 15-30%.
Skipping the suppression list import during migration
What goes wrong: You email 500 people who unsubscribed from your old platform. Spam complaints spike from 0.05% to 0.6%+, well past Gmail's 0.3% complaint threshold. Sending reputation tanks for 60-90 days. Open rate drops from 35% to 18% on your activation campaigns.
How to avoid: Export suppression list from your old ESP. Upload to Customer.io → Settings → Suppression List BEFORE sending the first campaign. This is non-negotiable.
Giving the whole team Admin role
What goes wrong: When an engineer leaves, they take API keys with them. Ex-employees can reset 2FA and delete workflows. Insurance/compliance audits flag this. Worst case: a disgruntled ex-marketer deletes 18 months of campaign templates.
How to avoid: Use Editor role for people who build campaigns. Admin only for billing owners and lifecycle leads. Audit quarterly via Settings → Members. Remove ex-employees within 24 hours of departure.
Recap
Done — what's next
How to instrument Customer.io event tracking for a SaaS product
Read the next tutorial
Hand it off
Customer.io setup is the kind of work that's invisible when done right and catastrophic when done wrong. A specialist who's stood up 30+ workspaces will hit every landmine in 4-6 hours of focused work — typically $400-900 at $14-16/hr. The alternative is finding the landmines yourself in production over the next 12 months.
See specialist rates
Track API is the legacy direct-to-Customer.io ingest path — works on every plan. Data Pipelines (also called Sources/Destinations, available on Premium and above) is a CDP layer that lets you ingest from one Source (your app, Segment, Rudderstack, etc.) and fan out to many Destinations (Customer.io + Mixpanel + Amplitude + your data warehouse). For new SaaS setups, use Data Pipelines — single instrumentation, more Destinations.
On Premium and above, yes — Data Pipelines covers most Segment use cases (Sources, Destinations, transformations) at lower cost. The gap is Segment Protocols (schema enforcement) and Segment Connections to certain niche destinations. For SaaS teams paying Segment $1K-10K/mo, Customer.io Data Pipelines usually consolidates the cost.
Essentials ($150/mo, up to 5K profiles) covers the basics — Journeys, Newsletters, Broadcasts, Transactional, basic segments. Premium adds Data Pipelines, in-app messaging at scale, and SSO. Enterprise adds dedicated IPs, custom contracts, and compliance certifications. Most SaaS teams start on Essentials and upgrade to Premium around 25K profiles or when they need Data Pipelines.
Klaviyo is purpose-built for e-commerce — deeply integrated with Shopify, BigCommerce, WooCommerce. Customer.io is purpose-built for product-led SaaS — flexible event tracking, in-app messaging, push, SMS, and Liquid templating from anywhere in the user profile. If you sell physical products, choose Klaviyo. If you have an authenticated product with users and events, choose Customer.io.
No. Dedicated IPs need 30-60 days of warmup and consistent volume (15K+ sends/week minimum) to be worth it. Customer.io's shared IP pool is well-managed and gives better deliverability than a cold dedicated IP for under-50K/week senders. Switch to dedicated only when you cross 50K sends/week consistently.
Yes. Customer.io is SOC 2 Type II certified and GDPR-compliant. Use the EU workspace (track-eu.customer.io) for EU data residency. Set up Subject Access Request webhooks. Enable data retention policies in Settings → Privacy & Compliance. The platform handles most compliance plumbing; your team owns consent capture and DSAR response process.
Customer.io
Customer.io is only as smart as the events you send it. Sloppy instrumentation — events fired client-side, inconsistent naming, missing properties — silently sabotages every workflow you build on top. This is the schema that scales.
Customer.io
Segments are how Customer.io decides who. Workflows are how it decides when and what. Most SaaS teams get one or the other right but rarely both — and the gap shows up as activation campaigns missing 40% of eligible users.
Customer.io
Customer.io's email side has three distinct surfaces — Broadcasts, Newsletters, and Transactional — and each has its own rules. Mix them up and you'll send marketing content from your transactional IP (bad) or transactional from your marketing IP (worse).
Customer.io
Customer.io Data Pipelines is the CDP layer that lets you instrument once and fan out to many tools. For SaaS teams paying Segment $1K-10K/mo, this typically consolidates the spend while keeping the same instrumentation pattern.
Customer.io
DIY Customer.io is the right call — until it isn't. In healthy SaaS, lifecycle email + in-app should drive 20-35% of activation and 10-20% of retention. If yours is at 5-10%, the gap is the program isn't being worked. Here's the honest framework for when to hire.