Summarize this documentation using AI
Overview
If you’re using Customer.io for retention, in-app messages are one of the fastest ways to recover revenue without waiting for inbox placement—especially when the user is already active in your app or site. If you want a second set of eyes on identity stitching or event design before you roll this out, book a strategy call and we’ll pressure-test the tracking plan like an operator would.
In practice, in-app works best when your SDK events are clean enough to target intent (browse/cart/checkout) and your identity is stitched well enough that a logged-out session still becomes usable once the shopper logs in.
How It Works
In-app messaging lives and dies by app-side instrumentation. Customer.io decides who qualifies based on person attributes + event activity, but your SDK decides whether the platform even has trustworthy signals to target and suppress messages.
- SDK collects identity + events: Your mobile/web SDK sends an
identifycall (person id + traits) andtrackcalls (events likeProduct Viewed,Added to Cart,Checkout Started). - Anonymous-to-known stitching: A shopper might browse anonymously, add to cart, then log in at checkout. If you handle aliasing/merging correctly, those “anonymous” events become targeting fuel for in-app recovery the moment they authenticate.
- Eligibility + frequency control: Customer.io evaluates segments/conditions (e.g., “Added to Cart in last 2 hours AND no Order Placed”) and your orchestration decides when to show an in-app message versus falling back to push/email.
- Display happens in the client: The app/web client renders the in-app message. That means versioning matters—older app versions can break layouts, triggers, or dismissal tracking if you don’t plan for it.
Step-by-Step Setup
Before you touch message design, lock the data layer. Most retention programs stall here because the team designs “cart recovery in-app” before they can reliably detect cart state, login state, and purchase suppression.
- Install the right Customer.io SDK for your client
- Mobile: iOS/Android (or React Native/Flutter/Expo wrappers if applicable).
- Web: initialize the web SDK early enough to capture pre-login behavior.
- Decide upfront whether you need both app + web stitched into one person (common in D2C where shoppers browse on mobile web then buy in-app).
- Implement
identifyat the moment you can trust identity- Call
identify(userId, traits)immediately after login/signup and whenever key traits change (email, phone, loyalty tier). - Keep
userIdstable (your internal customer id). Don’t use email as the primary id if it can change. - Send traits you’ll actually segment on:
first_order_date,orders_count,last_order_date,sms_opt_in,push_opt_in,preferred_category.
- Call
- Stitch anonymous activity to the known profile
- Capture events pre-login with an anonymous identifier.
- When the shopper authenticates, merge/alias the anonymous profile into the known
userIdso browse/cart intent doesn’t get stranded. - Test this explicitly: add to cart while logged out → log in → confirm the known profile shows the cart event history.
- Track the retention-critical events (with consistent properties)
Product Viewed:product_id,category,price,variant_id.Added to Cart:cart_id,items(array),cart_value,currency.Checkout Started:cart_id,cart_value.Order Placed:order_id,revenue,items,is_subscription.App Opened/Session Started: needed for “show when active” logic and reactivation timing.
- Confirm device registration for mobile (push + in-app coordination)
- Make sure devices are attached to the right person after login.
- If your push token updates, update it—stale device tokens cause “why didn’t they get the push?” confusion and can distort how you judge in-app performance.
- Build one retention workflow that proves the plumbing
- Start with a simple cart recovery in-app message: trigger on
Added to Cart, delay 10–30 minutes, show in-app on next session if noOrder Placed. - Instrument message interactions as events (e.g.,
InApp Viewed,InApp Dismissed,InApp Clicked) so you can suppress repeat impressions and measure lift.
- Start with a simple cart recovery in-app message: trigger on
When Should You Use This Feature
In-app messages are best when you want to intercept intent while the shopper is already present, or when email/SMS would be too slow or too expensive to use as the first touch.
- Cart recovery inside the session: Shopper adds to cart, continues browsing, then hesitates. Show “Still thinking? Free shipping unlocks at $50” while they’re active instead of waiting for an email 2 hours later.
- Checkout rescue after failed attempt: If you track a
Payment Failedor detect repeatedCheckout StartedwithoutOrder Placed, an in-app message can route them to alternative payment methods or support. - Second purchase acceleration: After
Order Placed, wait for delivery window + trackOrder Delivered(if you have it). Then show replenishment or complementary SKUs the next time they open the app. - Reactivation when they return: For lapsed buyers, in-app is the cleanest “welcome back” moment because it doesn’t rely on deliverability and it’s naturally timed to their return session.
Operational Considerations
Most teams don’t fail on message creative—they fail on data consistency and orchestration collisions. Treat in-app as part of a system: segments decide eligibility, events decide timing, and other channels decide whether you should even show it.
- Segmentation needs stable definitions: Define “cart abandoner” using events + suppression, not vibes. Example:
Added to Cartin last 4 hours AND NOTOrder Placedsince that event ANDcart_value≥ threshold. - Data flow latency matters: If events arrive late, “show on next session” becomes “show two sessions later,” which feels spammy. Validate event ingestion timing from client → Customer.io.
- Identity stitching impacts suppression: If a user buys on web while logged in, but your app profile is a different id, they’ll still see cart recovery in-app. This is the #1 reason in-app feels “dumb.”
- Orchestration with push/email: Decide priority rules. Common pattern: in-app first while active, push second if they churn out of session, email last as a longer-tail backstop.
- Frequency and fatigue: Add global caps (per day/per session) and per-campaign caps. In most retention programs, fatigue shows up faster in-app because it interrupts the experience.
Implementation Checklist
If you want this to drive revenue (not just impressions), treat this like a tracking project first and a messaging project second.
- SDK installed and initialized on every surface where you want to show messages (app + web as needed)
identifyimplemented post-login with stableuserIdand meaningful traits- Anonymous browsing/cart events captured and merged into known profiles on login
- Standardized event taxonomy for
Product Viewed,Added to Cart,Checkout Started,Order Placed - Event properties are consistent (same key names, same types) across platforms
- Message interaction events tracked for measurement + suppression
- Clear orchestration rules with push/email to avoid double-tapping the same user
- QA plan: test logged-out → logged-in flows, cross-device purchase suppression, and timing
Expert Implementation Tips
These are the small choices that usually separate “in-app looks cool” from “in-app prints money.”
- Track cart state as both events and a current attribute: Events tell you what happened; an attribute like
cart_value_currenthelps you target instantly on session start without reconstructing state from event history. - Use a cart_id everywhere: If you don’t pass
cart_idthroughAdded to Cart→Checkout Started→Order Placed, suppression logic gets fuzzy and you’ll mis-fire messages. - Design for “next session” delivery: A lot of cart recovery in-app works when it triggers on the next app open. Build the workflow so it waits until
Session Startedafter the abandonment window. - Make dismissals meaningful: If someone dismisses a cart message, suppress that campaign for 3–7 days or until the cart meaningfully changes (new item, higher value).
- QA with real user journeys, not single events: Run the full D2C loop: browse → add to cart → background app → reopen → purchase → ensure no more recovery messages.
Common Mistakes to Avoid
These are the problems we see repeatedly when D2C teams roll out in-app fast and then spend weeks debugging “random” behavior.
- Using email as the primary identifier: People change emails. Identity breaks, suppression breaks, and your reporting gets messy.
- Not merging anonymous activity: You lose the highest-intent signals (browse/cart) because they happened pre-login, so your in-app targeting becomes generic.
- Inconsistent event property naming: iOS sends
productId, Android sendsproduct_id, web sendsid. Segments silently miss users. - No purchase suppression window: If
Order Placedarrives late or isn’t stitched, users see “complete your order” after they already paid. - Over-messaging active shoppers: If you show an in-app message every session, your best customers feel interrupted and you train them to dismiss everything.
Summary
In-app messages work when your SDK tracking is precise: clean identity, consistent events, and real suppression. If you already have strong cart and purchase signals in Customer.io, in-app becomes a high-control lever for recovery and repeat purchase. If you don’t, fix the instrumentation first—everything else is noise.
Implement In App with Propel
If you’re rolling this out across mobile and web, the hard part usually isn’t the message—it’s getting identity stitching, event design, and suppression to behave under real shopper behavior. That’s the layer we help teams operationalize alongside Customer.io. If you want to sanity-check your SDK plan and the first 1–2 revenue flows (cart recovery + second purchase is the usual start), book a strategy call and we’ll map it to your actual app journeys.