Summarize this documentation using AI
Overview
If you’re running Customer.io for a D2C brand, in-app event listeners are how you capture the high-intent moments that email alone never sees—add-to-cart taps, checkout friction, product views, and post-purchase behaviors. If you want a second set of eyes on your tracking plan (and how it ties back to revenue), book a strategy call and we’ll pressure-test it like an operator would.
The win here isn’t “more events.” It’s clean, reliable signals you can trust for cart recovery, replenishment, upsell, and reactivation—without broken identity or double-counted purchases.
How It Works
In practice, “in-app event listeners” means your app (iOS/Android/web) listens for user actions and sends them into Customer.io as events tied to the right person. The retention unlock comes from two things: (1) sending the right events with the right properties, and (2) stitching anonymous activity to a known customer the moment they identify.
- Install the SDK in your app so it can collect device/app context and send events reliably.
- Track anonymous behavior early (e.g., product viewed, add to cart) before a shopper logs in or enters email.
- Identify the user when you have a stable identifier (email, customer_id). This is where identity stitching either works—or quietly breaks your program.
- Send events with properties that make them usable for segmentation and orchestration (SKU, category, price, cart_value, currency, quantity, variant, order_id).
- Use those events in Journeys to trigger messages, apply filters, set goals, and exit people when they convert.
A realistic D2C scenario: a shopper browses on mobile, adds a moisturizer to cart, then gets distracted. If your app tracks product_viewed and add_to_cart anonymously, then calls identify when they enter email at checkout (even if they don’t complete), you can trigger a push or email within 30–60 minutes with the exact item and price—without guessing.
Step-by-Step Setup
The setup is straightforward, but the order matters. Most retention programs get noisy data because they identify too late, reuse unstable IDs, or ship events without the properties needed to build segments and exclusions.
- Pick your canonical user ID strategy
- Decide what Customer.io should treat as the primary identifier (typically a stable
customer_idfrom your backend; email can change). - Document when that ID becomes available in-app (account creation, login, checkout email capture).
- Decide what Customer.io should treat as the primary identifier (typically a stable
- Install the Customer.io SDK for your platform
- Implement the official SDK for iOS/Android/React Native/Flutter/web as appropriate.
- Confirm the environment setup (dev vs prod) so test events don’t pollute production segments.
- Send anonymous events as soon as intent exists
- Track events like
product_viewed,collection_viewed,add_to_cart,checkout_startedeven before login. - Include properties you’ll actually use later (see checklist below).
- Track events like
- Call identify immediately when you have a real identifier
- On login/account creation: call
identifywithcustomer_idand key attributes (email, phone, first_name, opt-in flags). - On “email captured” at checkout: identify there too—this is where cart recovery is won or lost.
- On login/account creation: call
- Track purchase events server-truthfully (or reconcile carefully)
- In most D2C stacks, purchases are safest from the backend (order paid) to avoid duplicates from app retries.
- If you must track client-side, pass an
order_idand enforce deduplication rules in your pipeline.
- Validate in Customer.io Activity Logs
- Check that events show up on the right profile after identify (anonymous history should be merged, not stranded).
- Spot-check properties (SKU, value, currency) for consistency and correct types.
- Wire events into Journeys with exits and goals
- Trigger cart recovery on
add_to_cartorcheckout_started. - Exit immediately on
order_completedto prevent embarrassing “still thinking?” messages.
- Trigger cart recovery on
When Should You Use This Feature
You’ll feel the impact of in-app listeners any time the customer’s intent happens inside the app (or SPA) and you need to react quickly and accurately. This is especially true when email capture happens late, and you need anonymous-to-known stitching to make recovery work.
- Cart recovery that actually matches the cart: trigger from
add_to_cart/checkout_startedwith item-level properties, then suppress iforder_completedarrives. - Product discovery → repeat purchase loops: track
product_viewedandcategory_viewedto build “high intent” segments for browse follow-ups and replenishment education. - Reactivation based on app disengagement: use a “no app_open in 21 days” segment, but only if
app_openis consistently tracked across versions. - Post-purchase upsell timing: trigger education or cross-sell after
order_completed, then branch based onproduct_usedorsubscription_startedevents (if you track them).
Operational Considerations
This is where teams either build a durable retention engine—or ship a bunch of events that nobody trusts. Treat tracking like production infrastructure: stable naming, consistent properties, and clear rules about what’s source-of-truth.
- Segmentation depends on property hygiene
- Pick one naming convention and stick to it (e.g.,
add_to_cartnotAddToCartin one place andcart_addin another). - Standardize types:
priceas number,currencyas string, timestamps as ISO-8601.
- Pick one naming convention and stick to it (e.g.,
- Identity stitching is the retention multiplier
- Identify as early as you can without being wrong. Late identify = anonymous activity you can’t use for targeting.
- Don’t identify with unstable values (temporary guest IDs that later change). That’s how you create duplicates and mis-attribution.
- Data flow realities: client vs server
- Client-side is great for intent (views, taps). Server-side is safer for revenue events (paid, fulfilled).
- If both send the same “purchase” event, you’ll double-trigger journeys unless you dedupe by
order_id.
- Orchestration needs suppression and exits
- Cart flows need hard exits on purchase and often a “cooldown” if they keep adding/removing items.
- In most retention programs, we’ve seen the best results when you cap recovery touches and shift to browse/education once intent cools.
Implementation Checklist
Before you build journeys off these events, make sure the tracking is dependable. A week spent here saves months of “why did this segment spike?” debugging.
- SDK installed in each app target (prod + staging) with correct credentials
- Identify points defined: login, account creation, checkout email capture
- Core intent events tracked:
product_viewed,add_to_cart,checkout_started,app_open - Revenue event strategy set: server-truthy
order_completedpreferred; dedupe withorder_id - Event properties standardized:
sku,product_id,variant,quantity,price,cart_value,currency,category - Consent/opt-in attributes captured (email, SMS, push permissions) and kept current
- QA in Activity Logs: anonymous events merge into known profile after identify
- Journey exits + suppression rules mapped before launch
Expert Implementation Tips
The difference between “events are flowing” and “events drive revenue” is usually a few operator-level decisions that keep your data usable at scale.
- Track at the decision points, not every tap: one clean
checkout_startedbeats five noisy “button_clicked” events when you’re trying to recover carts. - Always include an idempotency key for conversion events: for orders, that’s
order_id. For subscriptions, usesubscription_id. This prevents duplicate triggers when apps retry. - Send “cart updated” snapshots sparingly: if you send full cart payloads on every quantity change, you’ll inflate event volume and complicate segmentation. Instead, track
add_to_cartitem-level plus a periodiccart_updatedwithcart_value. - Use identify to attach lifecycle attributes: first_purchase_date, last_purchase_date, LTV-to-date—these make your reactivation and VIP logic much more stable than event-only rules.
- Version your event schema when you change properties: add
schema_versionso you can filter out older payloads during migration.
Common Mistakes to Avoid
Most failures here don’t look like “broken tracking.” They look like campaigns underperforming because the audience is wrong, the timing is off, or conversions are misattributed.
- Identifying too late: capturing email after checkout means you miss the highest-intent recovery window.
- Using email as the only identifier: emails change; customer IDs don’t. This creates duplicate profiles and fractured history.
- Tracking purchases client-side without dedupe: you’ll double-trigger post-purchase flows and inflate revenue reporting.
- Inconsistent event names across platforms: iOS sends
add_to_cart, Android sendsaddToCart—now your segment is silently incomplete. - Missing properties that matter operationally: if
currencyorpriceis absent, you can’t reliably personalize or branch by cart value. - No suppression rules: cart recovery that doesn’t exit on purchase is the fastest way to annoy customers and burn trust.
Summary
If your D2C retention relies on cart recovery, replenishment, or reactivation, in-app event listeners are the cleanest way to capture intent in real time.
Implement the SDK, identify early, standardize your event schema, and treat purchase events as dedupe-safe. Then build journeys that exit fast when the customer converts.
Implement In App Event Listeners with Propel
When teams want to move fast without breaking identity or data quality, we usually start by mapping the exact events that drive revenue (not vanity tracking), then validating they land correctly in Customer.io before we scale journeys. If you want us to review your SDK identify points, event schema, and dedupe plan against your cart + repeat purchase goals, book a strategy call and we’ll walk through it end-to-end.
The goal is simple: fewer events, better signals, and flows you can trust when you’re spending on acquisition and need conversion + LTV to follow.