Summarize this documentation using AI
Overview
If you’re moving to Customer.io, the migration isn’t “copy campaigns and go live.” The real work is getting people, events, and identifiers flowing in cleanly so your cart recovery, post-purchase, and winback triggers fire exactly when they should. If you want a second set of eyes on your event map and identity plan before you flip traffic, book a strategy call.
In most retention programs, migrations fail quietly: events arrive without the right customer identifier, anonymous sessions never merge, and segments drift for weeks—so you think performance dropped when it’s really a data mismatch.
How It Works
Customer.io is only as good as the data you feed it. During a migration, you’re basically rebuilding three things: (1) person profiles (attributes), (2) event streams (behavior), and (3) identity resolution (how Customer.io knows an “anonymous browser” and a “known email” are the same person).
- People (profiles) enter Customer.io when you create/update a person via your chosen ingestion method (commonly the Track API, SDKs, or a pipeline/integration). Profiles are keyed off an identifier (often
idoremaildepending on your setup), and then enriched with attributes likefirst_name,accepts_marketing,customer_type,last_order_at, etc. - Events enter Customer.io as named actions (e.g.,
product_viewed,added_to_cart,checkout_started,order_completed) with properties (SKU, cart value, currency, product category, etc.). Journeys and segments depend heavily on consistent event naming and timestamps. - Anonymous activity matters for D2C because most cart and browse behavior happens before login. Customer.io supports anonymous people/activity and then merges anonymous activity into a known profile when you identify the person (for example, when they submit email at checkout or via a popup).
- Identity resolution is the migration make-or-break: if your old tool used email as the primary key but your new implementation uses a generated customer ID (or vice versa), you need a deliberate mapping plan so the same human doesn’t become multiple profiles—and so event-triggered campaigns don’t double-send.
Real D2C scenario: you run a 3-step cart abandonment sequence triggered by checkout_started. In the old platform, that event was tied to email captured at checkout. In the new setup, if checkout_started is sent while the user is still anonymous and you never merge/identify them, the event exists—but no email can send, and the customer never enters the journey. Fixing this is less about the journey and more about when/how you call “identify” and which identifier you use.
Step-by-Step Setup
Before you migrate anything, decide what “good” looks like: the same customer should resolve to one profile, key purchase and cart events should arrive with the right properties, and your highest-value segments should match what you expect within a day—not weeks later.
- Inventory your current tracking plan
Export a list of: person fields, event names, event properties, and the primary identifier used today (email, internal user ID, Shopify customer ID, etc.). Flag the events that power retention: cart, checkout, purchase, refund, subscription, replenishment signals. - Choose your canonical identifier strategy
Decide what Customer.io should treat as the “source of truth” identifier. In practice, D2C brands usually land on one of these:- Email-first when guest checkout dominates and email capture happens early.
- Customer ID-first when you have accounts/subscriptions and a stable internal ID.
- Define your identity resolution moments
Pick the exact points where you’ll convert anonymous to known:- Email capture popup submit
- Checkout email step
- Account creation / login
- Map your person attributes (and clean them)
Create a mapping table from old fields to new fields. Normalize types (booleans as booleans, timestamps as timestamps). Decide which attributes are “computed” (likelifetime_value) and where they’ll be calculated (warehouse, ecommerce platform, or your app) before they enter Customer.io. - Map your event taxonomy with parity in mind
Keep names stable where possible, but don’t drag legacy mess forward. For retention reliability, focus on:- One clear purchase event (e.g.,
order_completed) - One clear cart/checkout start event (e.g.,
checkout_started) - Consistent SKU/product identifiers across events
- Currency + value on revenue events
- One clear purchase event (e.g.,
- Send test profiles + events into a non-production workspace (or a controlled environment)
Create a small set of test people and replay a realistic timeline: browse → add to cart → checkout started → purchase. Confirm the person resolves to a single profile and that events appear in the activity feed with expected properties. - Backfill only what you’ll actually use
Don’t backfill every historical event “because you can.” Backfill the minimum that improves segmentation and timing:- Last purchase date
- Purchase count
- LTV (if you use it for VIP segmentation)
- Last product/category purchased (if used for replenishment/cross-sell)
- Validate segments and triggers before sending volume
Compare counts for your top segments (recent purchasers, high AOV, cart abandoners, lapsed 60/90 days). Then validate triggers by forcing entry (create a test cart abandonment and ensure the journey starts within your expected delay window).
When Should You Use This Feature
You don’t migrate data “for completeness.” You migrate data to keep retention automation accurate on day one and avoid a month of muddled reporting and broken triggers.
- When cart recovery relies on pre-checkout behavior and you need anonymous browsing and cart events to merge into known profiles after email capture.
- When repeat purchase flows depend on purchase history (last order date, order count, product category) and you need those attributes available immediately for segmentation.
- When reactivation is driven by lapsed windows and you need clean timestamps (last purchase, last site visit) so “60 days lapsed” actually means 60 days.
- When you’re consolidating tools (ESP + CDP + SMS) and you need one consistent identity graph so customers don’t get duplicated across channels.
Operational Considerations
Migrations tend to break in the gaps between systems: your ecommerce platform, your frontend tracking, and Customer.io each have their own ideas of identity and timing. Getting ahead of that is what keeps segmentation stable and orchestration predictable.
- Segmentation accuracy depends on stable identifiers: if the same person can arrive as
emailsometimes andcustomer_idother times without a merge plan, you’ll inflate audience sizes and double-trigger messages. - Event timing affects journey logic: if your ingestion introduces delays (batching, queueing, retries), “send 30 minutes after checkout started” can become “send 2 hours later,” which tanks recovery rate. Confirm expected latency end-to-end.
- Property consistency is what makes personalization work: cart templates usually assume
items[],cart_value,currency, and product URLs exist. If those properties are missing or shaped differently between events, your emails render poorly or fail QA. - Backfills can pollute recency-based segments: importing old events with current timestamps (or wrong timezones) can accidentally qualify customers for “recently active” segments and trigger inappropriate sends.
- Suppression and consent must be mapped early: if your old platform stored SMS/email consent differently, you need those fields flowing into Customer.io before you turn on sends, or you’ll either under-send (too strict) or over-send (compliance risk).
Implementation Checklist
If you only do one thing, make it this: treat migration as a tracking-plan project, not an ESP swap. This checklist is the minimum to keep triggers reliable.
- Canonical identifier chosen (email vs customer_id) and documented
- Anonymous-to-known merge points defined (popup submit, checkout email, login)
- Person attribute map created with data types and naming conventions
- Event taxonomy finalized for retention-critical events (cart/checkout/purchase)
- Event property requirements documented for each retention use case (cart, post-purchase, winback)
- Test profiles created and full funnel event sequence replayed
- Top 5 segments validated against expected counts
- Trigger latency measured (event occurs → appears in Customer.io → journey entry)
- Consent/suppression fields mapped and validated before enabling sends
- Backfill plan defined (what, how far back, and how timestamps are handled)
Expert Implementation Tips
The fastest migrations aren’t the ones with the most engineering. They’re the ones where someone owns the event map and refuses to ship until identity and timestamps are correct.
- Design for “email captured after the cart event”: for many D2C stores,
added_to_carthappens before you know the email. Make sure you’re capturing anonymous events and merging them later, otherwise your cart program will underperform and you’ll blame creative. - Pick one purchase event and make it sacred: keep
order_completedconsistent and includeorder_id,total,currency, and line items. Every repeat purchase, VIP, and winback segment gets easier when purchase data is boring and consistent. - Store “last_*” attributes deliberately: rather than segmenting off complex event queries for everything, maintain attributes like
last_order_atandlast_category_purchasedupstream and sync them in. It makes segments faster, easier to QA, and less fragile. - Run a parallel period for critical triggers: for cart abandonment and post-purchase, run old and new systems in parallel for a short window (even just internal testing) so you can compare entry volume and timing before you cut over.
Common Mistakes to Avoid
Most “Customer.io isn’t working” complaints during migrations come down to a few predictable data issues. Fix these and your journeys usually stabilize immediately.
- Sending events without an identifier strategy, creating duplicate profiles and double-sends.
- Forgetting anonymous merge, which silently kills cart and browse-based programs.
- Changing event names without updating triggers, so journeys never fire even though data is flowing.
- Backfilling with wrong timestamps/timezones, which breaks recency segments and “wait until” logic.
- Inconsistent product identifiers (SKU vs variant_id vs product_id), making cross-sell and replenishment segmentation unreliable.
- Assuming consent fields will “just work”, then discovering after launch that half your list is unintentionally suppressed (or worse, not suppressed).
Summary
If your people, events, and identity resolution are clean, Customer.io becomes a retention engine fast. If they’re messy, your segments drift and your triggers misfire—especially for cart recovery and winback.
Make the migration decision based on whether you can confidently map identifiers, merge anonymous behavior, and validate trigger timing before you scale sends.
Implement Js Migration with Propel
When teams migrate into Customer.io, the work that actually moves revenue is the event map, identity resolution, and validation plan—not the final email build. If you want help pressure-testing your tracking plan (especially anonymous merge for cart recovery and purchase parity for repeat flows), book a strategy call and we’ll walk through what to send, when to send it, and how to confirm it’s triggering reliably before launch.
In practice, this tends to break at the handoff between frontend events and checkout identity—so that’s usually where we start.