Summarize this documentation using AI
Overview
If you’re running retention in Customer.io, the SDK is where the program either becomes reliable—or quietly falls apart. The difference comes down to whether your app is sending clean identity + event data that Customer.io can actually segment on and trigger Journeys from (and if you want a second set of eyes on the data layer before you build flows, book a strategy call).
In most D2C retention programs, the highest-leverage work isn’t “more messages.” It’s getting the app to report the moments that predict repeat purchase and churn—then stitching anonymous browsing to a known customer so your cart recovery and replenishment automations don’t miss.
How It Works
Customer.io’s SDK setup is basically a contract: your app sends identity and behavior, Customer.io stores it on a person profile, and Journeys use that data to trigger, segment, and personalize messages. When the contract is loose (missing identify calls, inconsistent event names, no dedupe keys), your automations look fine in the canvas but underperform in the real world.
- Install SDK → collect device context: The mobile/web SDK captures device/app context (platform, app version, push token, etc.) so you can message the right channel and troubleshoot drops by version.
- Identify → stitch activity to a person: The critical moment is when an anonymous user becomes known (login, account create, email capture, checkout). You call
identifywith a stable customer identifier and key attributes. This is what turns “random events” into a usable customer timeline. - Track events → power triggers + segmentation: You send events like
product_viewed,add_to_cart,checkout_started,order_completedwith properties (SKU, category, price, cart value). Journeys trigger off these events and segments filter off event history. - Anonymous-to-known merge: If a shopper browses anonymously, adds to cart, then logs in, you want that pre-login activity to merge into the newly identified profile. In practice, this is where cart recovery breaks when teams only start tracking after login.
- Attributes vs events (don’t mix them): Attributes describe the person (e.g.,
lifetime_value,last_order_at,subscription_status). Events describe actions (e.g.,added_to_cart). If you dump everything into attributes, you lose sequencing and trigger logic.
Real D2C scenario: A shopper installs your app, views a cleanser, adds it to cart, then gets distracted. If the SDK tracks add_to_cart anonymously and later merges on identify when they enter email at checkout, Customer.io can still fire a push/SMS recovery with the exact items and cart value. If you only identify after purchase, you’ve already lost the recovery window.
Step-by-Step Setup
The goal here is not “send data.” It’s to send data that maps cleanly to how you’ll actually run retention: cart recovery, replenishment, cross-sell, and winback—without constant segment debugging.
- Install the appropriate Customer.io SDK
Add the SDK for your platform (iOS/Android/React Native/Flutter/Web) and confirm the app can reach Customer.io in your environment (dev first, then prod). - Define your identity strategy before writing code
Pick a stable identifier you’ll always have (typically your internalcustomer_id). Decide when you’ll callidentify(login, account creation, email capture, checkout start). Write this down—this prevents “half-identified” users and duplicate profiles. - Implement
identifywith core attributes
On the first moment the user is known, callidentifyand include attributes you’ll segment on immediately:email(if you have it)phone(if you have it and have consent for SMS)first_name(optional but useful for personalization)created_atorsignup_at(timestamp)marketing_opt_in/ channel consent flags
- Track a minimal retention event taxonomy
Start with events that directly drive revenue automations:product_viewed(properties:sku,category,price)add_to_cart(properties:sku,qty,cart_value)checkout_started(properties:cart_value,item_count)order_completed(properties:order_id,revenue,items)
- Handle anonymous activity and merging
Ensure events fire pre-login (anonymous) and that your identify flow merges that activity into the known profile. This is the difference between “we have a cart abandonment flow” and “it actually catches carts.” - Verify events in Customer.io before building Journeys
Use a test device/account. Confirm:- Person profile shows the right attributes after identify
- Events appear with expected properties
- Anonymous events attach after identify (no orphan timelines)
- Only then: build your triggers and segments
Build a Journey triggered byadd_to_cartorcheckout_started, then filter by recency and suppression rules (e.g., exclude purchasers in the last X hours).
When Should You Use This Feature
The SDK path is the right call when retention depends on in-app behavior, not just Shopify/order data. If you care about what customers browsed, considered, or abandoned inside the app, you need SDK events to drive timely messaging.
- Cart recovery that actually matches the cart: Trigger off
checkout_startedwith cart properties so messages can reference the right products and value. - Product discovery → second purchase loops: Track
product_viewedandcategory_viewedto build “interested but not bought” segments for cross-sell after order #1. - Reactivation based on app inactivity: Use last app open / last viewed product events to target “lapsed browsers” separately from “lapsed buyers.” Those are different winbacks.
- Replenishment and reorder timing: If your products have predictable cycles (supplements, skincare), track
order_completedwith item-level detail so reorder reminders are SKU-specific.
Operational Considerations
Once you’re past “events are flowing,” the real work is keeping the data usable for segmentation and orchestration. This is where most teams lose weeks—Journeys misfire because the app and Customer.io disagree on identity, timestamps, or naming.
- Segmentation depends on stable naming: If one team ships
AddedToCartand another shipsadd_to_cart, you’ll end up with two segments and half the audience in each. Lock a single taxonomy and enforce it in code review. - Identity stitching is your “single point of failure”: In practice, cart recovery tends to break when identify happens too late (post-purchase) or inconsistently (email-only sometimes, customer_id other times). Pick one primary ID and stick to it.
- Data flow latency affects send timing: If events arrive late (batching, offline mode), your “30 minutes after abandon” message might hit 6 hours later. Decide what’s acceptable and test on real devices, not just logs.
- Orchestration needs suppression logic: If you run email + push + SMS, you need shared rules (e.g., stop cart flow on purchase, cap touches per day). Otherwise you’ll over-message your best customers.
- Event properties should match how you personalize: If you want “You left X in your cart,” you need
cart_value. If you want item callouts, you need anitemsarray with SKU/title/image URL.
Implementation Checklist
Before you invest in new Journeys, run this checklist once. It’s the fastest way to avoid building retention logic on top of shaky tracking.
- SDK installed and verified in dev + prod
identifyfires at the first “known” moment (login/email capture), not just after purchase- Primary identifier is stable (prefer internal
customer_id) - Anonymous events are captured and merged after identify
- Core events implemented:
product_viewed,add_to_cart,checkout_started,order_completed - Event properties include what you’ll segment/personalize on (SKU/category/value/items)
- Consent flags captured for SMS/push where required
- Test account shows clean timeline in Customer.io (no duplicates, no missing events)
Expert Implementation Tips
These are the small choices that make your Customer.io program feel “predictable” week to week instead of constantly needing patches.
- Send a dedupe key for purchase events: If your app retries network calls,
order_completedcan double-fire. Useorder_idas a natural dedupe key in your pipeline logic and in Journey exit rules. - Track “remove_from_cart” and “cart_updated” if your catalog is complex: For bundles or multi-SKU carts, a single
add_to_cartevent isn’t enough to represent the final cart state. - Version your event schema intentionally: If you need to change properties (like moving from
pricetounit_price), add the new property without deleting the old one until all Journeys migrate. - Use app version as a debug segment: When conversion dips, being able to segment “app_version = 5.12.0” often reveals a broken checkout event or missing identify call after a release.
Common Mistakes to Avoid
Most “Customer.io isn’t working” problems are really “our SDK tracking doesn’t match our retention strategy.” These are the ones we see the most in D2C.
- Identifying users only after purchase: That guarantees you miss the highest-intent recovery moments (cart/checkout abandonment).
- Using email as the only identifier: Emails change, get mistyped, or aren’t available in-app. Use internal IDs for stitching; store email as an attribute.
- Inconsistent event naming across platforms: iOS sends
add_to_cart, Android sendsaddToCart. Your segments silently undercount and Journeys under-trigger. - Overloading attributes with behavioral data: Replacing event history with “last_action = add_to_cart” kills your ability to sequence messages and measure funnels.
- No purchase-based exit conditions: Cart flows that don’t immediately exit on
order_completedwill keep sending after someone buys—guaranteed complaint fuel.
Summary
If you want Customer.io Journeys to drive repeat purchase and recovery, the SDK has to do three things well: identify early, track the right events with useful properties, and stitch anonymous behavior into known profiles.
When that foundation is solid, segmentation becomes trustworthy and orchestration becomes a lever—not a weekly firefight.
Implement How It Works with Propel
If you’re already on Customer.io, the fastest path is usually: validate identity stitching, lock the event taxonomy, then build the 2–3 Journeys that monetize that data (cart recovery, post-purchase cross-sell, winback). That sequencing prevents the common trap of building beautiful flows on incomplete tracking.
If you want an operator to sanity-check your SDK events against the retention outcomes you care about, book a strategy call.