How Customer.io Works (SDK): Track the Right App Behavior to Drive Retention

Customer.io partner logo

Table of Contents

Summarize this documentation using AI

This banner was added using fs-inject

Lorem ipsum dolor sit amet, consectetur adipiscing elit.

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 identify with 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_completed with 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.

  1. 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).
  2. Define your identity strategy before writing code
    Pick a stable identifier you’ll always have (typically your internal customer_id). Decide when you’ll call identify (login, account creation, email capture, checkout start). Write this down—this prevents “half-identified” users and duplicate profiles.
  3. Implement identify with core attributes
    On the first moment the user is known, call identify and 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_at or signup_at (timestamp)
    • marketing_opt_in / channel consent flags
  4. 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)
    Keep names consistent and lower_snake_case. Consistency matters more than elegance.
  5. 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.”
  6. 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)
  7. Only then: build your triggers and segments
    Build a Journey triggered by add_to_cart or checkout_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_started with cart properties so messages can reference the right products and value.
  • Product discovery → second purchase loops: Track product_viewed and category_viewed to 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_completed with 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 AddedToCart and another ships add_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 an items array 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
  • identify fires 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_completed can double-fire. Use order_id as 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_cart event isn’t enough to represent the final cart state.
  • Version your event schema intentionally: If you need to change properties (like moving from price to unit_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 sends addToCart. 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_completed will 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.

Contact us

Get in touch

Our friendly team is always here to chat.

Here’s what we’ll dig into:

Where your lifecycle flows are underperforming and the revenue you’re missing

How AI-driven personalisation can move the needle on retention and LTV

Quick wins your team can action this quarter

Whether Propel AI is the right fit for your brand, stage, and stack