Summarize this documentation using AI
Overview
If you want retention automations that actually reflect what customers did in your app, you need clean, reliable in-app events flowing into Customer.io—not “best guess” pageviews or delayed backend exports. When teams get this right, cart recovery and repeat purchase flows stop misfiring, and you can build segments off real intent (viewed product, started checkout, dismissed offer, etc.). If you want a second set of eyes on your tracking plan and identity stitching, book a strategy call.
In-app event listeners are the practical layer where your SDK watches for user actions (taps, screens, modal interactions) and immediately emits normalized events to Customer.io. The win is speed and accuracy: you can trigger nudges while intent is still fresh, and you can suppress messages the moment someone completes the action.
How It Works
In practice, SDK-driven retention lives or dies on two things: (1) the app emits the right events at the right moment, and (2) Customer.io can stitch those events to the right person profile across anonymous and logged-in sessions. Event listeners are simply the places in your app code where you subscribe to user interaction/state changes and call the Customer.io SDK to track them.
- Install the Customer.io SDK for your platform (iOS/Android/React Native/Flutter/Web) and initialize it as early as possible in the app lifecycle so you don’t miss first-session intent.
- Track anonymously first, then identify once you have a stable user identifier (login, account created, email captured). The SDK will send pre-login events under an anonymous profile.
- Stitch identity on identify() so anonymous activity merges into the known profile. This is the difference between “cart abandoner” being reachable vs. lost in an anonymous bucket.
- Emit high-signal events from event listeners (e.g.,
product_viewed,add_to_cart,checkout_started,payment_failed,offer_dismissed) with consistent properties (SKU, price, currency, cart_id). - Use those events in Customer.io to trigger campaigns, build segments, and suppress/exit users when they convert.
Real D2C scenario: A shopper on mobile views a product, adds it to cart, then closes the app at the shipping step. If your SDK listens for checkout_started and checkout_step_viewed and you identify the user when they enter email at checkout, Customer.io can send a push within 30 minutes referencing the exact item and suppress the message instantly if order_completed arrives later.
Step-by-Step Setup
The fastest path is to instrument a small set of “money events” first (cart + checkout + purchase), verify identity stitching, then expand into discovery and post-purchase behaviors. Don’t start by tracking everything—start by tracking what you’ll actually automate against.
- Install and initialize the Customer.io SDK in your app entry point (AppDelegate/Application/Root component). Initialize early so first-session events don’t drop.
- Define your identity strategy:
- Pick a stable
customer_id(internal user ID is best). - Decide when you’ll call
identify()(login, account creation, email capture at checkout). - Decide what attributes you’ll attach on identify (email, phone, timezone, marketing opt-in).
- Pick a stable
- Implement identify() correctly:
- Call
identify(customer_id)immediately after you know who the user is. - Set/update key attributes in the same moment so segmentation works on first message send.
- If your app supports logout, call the SDK’s reset/clear method so the next user doesn’t inherit the prior identity.
- Call
- Add event listeners for retention-critical actions:
- Product discovery:
product_viewed,collection_viewed,search_performed. - Cart intent:
add_to_cart,remove_from_cart,cart_viewed. - Checkout intent:
checkout_started,checkout_step_viewed,payment_failed. - Post-purchase:
order_completed(often backend), plus app-sideorder_status_viewed,reorder_clicked.
- Product discovery:
- Standardize event properties so Customer.io messages can personalize reliably:
product_id,variant_id,sku,price,currencycart_id,cart_value,quantitycheckout_step(e.g., shipping/payment/review)
- Validate in Customer.io:
- Confirm events arrive on the right profile (anonymous first, then merged after identify).
- Confirm event property names match what your campaign Liquid references.
- Confirm event timing is real-time enough for your use case (push/in-app typically needs minutes, not hours).
- Wire events into orchestration:
- Triggers: start campaigns on
checkout_startedoradd_to_cart. - Exit conditions: remove users when
order_completedfires. - Frequency controls: prevent “every tap” from spamming by adding guards (e.g., only once per cart_id per 24h).
- Triggers: start campaigns on
When Should You Use This Feature
SDK event listeners matter most when you need immediacy, accuracy, or both. If you’re relying on batchy ecommerce exports, you’ll always be late to the moment that drives recovery and repeat purchase.
- Cart recovery in mobile-first funnels where the highest-intent actions happen inside the app (add to cart, checkout steps, payment errors).
- Browse-to-buy conversion when you want to retarget based on what someone actually looked at (and what they dismissed).
- Offer suppression so you stop discounting people who already converted or who saw (and closed) the offer.
- Reactivation based on in-app inactivity (e.g., installed but never reached checkout; returned but didn’t view products this week).
- Cross-device continuity when users start anonymous on mobile, then log in later—identity stitching turns “lost intent” into usable triggers.
Operational Considerations
This is where most retention programs get messy: teams ship events, but they aren’t consistent enough to segment on, and orchestration becomes a patchwork of exceptions. Treat your tracking like a product—version it, QA it, and keep it boring.
- Segmentation depends on naming discipline: one team sends
Product Viewed, another sendsproduct_view, and now your segments miss half the audience. Lock a single event taxonomy. - Data flow latency changes channel choice: if purchase confirmation comes from backend hours later, don’t rely on it to suppress a 15-minute push. In practice, you’ll want an app-side “thank you screen viewed” event as a fast proxy, then reconcile with backend order events.
- Identity stitching is not optional: if you only identify on account creation but most shoppers enter email at checkout, you’ll undercount abandoners. Align identify() with the earliest moment you can reliably capture identity.
- Orchestration needs guardrails: high-frequency events (scrolls, screen views) will create noisy triggers. Only track what you can act on, and add dedupe keys like
cart_idorsession_id. - Multi-SDK environments break silently: if you also use Segment/Mixpanel, decide which system is source-of-truth for Customer.io. Double-sending the same event creates duplicate entries and weird campaign re-entries.
Implementation Checklist
If you run through this list before you build automations, you’ll avoid the classic “campaign is live but targeting is wrong” week.
- SDK installed and initialized early enough to capture first-session events
identify()implemented at the earliest reliable identity moment (login/email capture)- Logout/reset behavior implemented to prevent identity bleed
- Money events instrumented:
product_viewed,add_to_cart,checkout_started,order_completed - Event properties standardized (SKU/variant, cart_id, currency, value)
- Anonymous-to-known merge verified in Customer.io profile activity
- Dedupe strategy defined (once per cart_id, once per session, etc.)
- Suppression/exit events available quickly enough for push/in-app timing
Expert Implementation Tips
The difference between “we track events” and “events drive revenue” is usually a handful of operator decisions that keep the system clean and actionable.
- Track dismissals on purpose: add an
offer_dismissedorin_app_closedevent withmessage_id. Then suppress the same offer for 7–14 days so you don’t train customers to ignore you. - Use step-level checkout events:
checkout_step_viewedwithcheckout_step=shippingis gold for diagnosing drop-off and tailoring recovery copy (“Still need a delivery date?” vs “Payment didn’t go through”). - Prefer stable IDs over emails for identify: emails change; internal IDs don’t. Set email as an attribute you update, not the primary identifier.
- Ship a tracking QA screen in debug builds: a simple internal overlay showing “last event sent + payload” saves days when a release breaks recovery flows.
- Instrument ‘reorder intent’: a
reorder_clickedevent is often a better repeat-purchase trigger than “30 days since purchase,” especially for replenishment categories.
Common Mistakes to Avoid
Most issues aren’t “Customer.io problems”—they’re instrumentation and identity problems that show up as broken segments and noisy campaigns.
- Identifying too late (only after purchase), which makes cart recovery impossible for most users.
- Sending events without required properties (no SKU, no cart_id), then wondering why messages can’t personalize or dedupe.
- Over-tracking UI noise (every screen view) and under-tracking intent (checkout step, payment failure).
- No reset on logout, leading to one customer receiving another customer’s recovery messages on shared devices.
- Duplicate events from multiple sources (SDK + server + CDP) causing double entries into campaigns.
- Relying on backend purchase events for immediate suppression when those events arrive too late for push/in-app timing.
Summary
If your retention program depends on real-time intent, in-app event listeners via the SDK are the foundation. Get identify + stitching right, instrument a tight set of money events with clean properties, then build recovery and repeat flows with strong suppression.
Implement Handling And Dismissing Actions with Propel
Once you’re tracking in-app actions cleanly, the next unlock is treating “handling” and “dismissing” as first-class signals—so your automations stop nagging and start adapting. In most retention programs, we’ve seen the biggest lift when teams use dismissal events to suppress repeats, branch journeys, and time the next touch based on what the customer actually did in the app, all orchestrated cleanly inside Customer.io.
If you want help pressure-testing your event taxonomy, identity stitching, and the exact suppression logic that keeps cart recovery aggressive without being annoying, book a strategy call.