Summarize this documentation using AI
Overview
If you want in-app to pull its weight in retention (not just “nice UI banners”), you need clean app-side tracking and consistent identity stitching into Customer.io. When teams struggle with in-app performance, it’s usually not the creative—it’s that the SDK isn’t identifying users at the right moment, events are missing key properties, or anonymous activity never gets merged.
If you want a second set of eyes on your tracking plan before you ship it, you can book a strategy call. In most retention programs, a 30-minute review catches the issues that would otherwise take weeks to diagnose in reporting.
How It Works
Customer.io in-app messaging is only as good as what your app tells it. The SDK collects device context, listens for your identify calls, and records events you track (like Viewed Product or Started Checkout). Customer.io then uses those people profiles + event history to decide who qualifies for an in-app message, when it should show, and how often.
- SDK initialization: your app boots the Customer.io SDK with your workspace/site credentials so it can receive message definitions and report interaction.
- Identity stitching: anonymous users can generate activity before login; once you call
identify(userId), Customer.io can merge that anonymous activity into the known profile (assuming you’ve implemented it correctly and consistently). - Event tracking drives targeting: in-app eligibility usually depends on a recent event plus properties (e.g.,
Added to Cartwithcart_valueandsku). - Display logic happens in-app: Customer.io decides the audience and sends the payload; the SDK is responsible for rendering and tracking impressions/clicks/dismissals.
Real D2C scenario: A shopper adds a moisturizer to cart on mobile, gets distracted, then reopens the app later. If you track Added to Cart and App Opened, and you identify them as soon as they authenticate (or stitch anonymous-to-known correctly), you can show a targeted in-app message on next open: “Your cart’s waiting—free shipping ends tonight.” Without identity stitching, that message often never shows to the right person, or worse, shows to everyone.
Step-by-Step Setup
Before you build messages, lock down the data contract your app will send. In practice, teams move faster when engineering and retention agree on a small set of canonical events and properties first—then you wire the SDK once and reuse it across cart recovery, replenishment, and winback.
- Install the Customer.io SDK for your app platform
Add the official Customer.io SDK for iOS/Android/React Native/Flutter/Web and initialize it at app start. Keep initialization early so the SDK can receive in-app definitions and attribute device context. - Implement
identifyimmediately after you know who the user is
Callidentify(userId)right after sign-in/sign-up (and after you refresh auth if your app supports silent login). Also send core attributes you’ll segment on:email(if available),phone(if available),country,language,marketing_opt_in,loyalty_tier. - Handle anonymous users deliberately
If your app allows browsing before login, track events anonymously and make sure you merge that activity once the user identifies. This is the difference between “cart recovery works” and “we only recover logged-in carts.” - Track the retention events that actually drive in-app
At minimum for D2C retention:App Opened(orSession Started)Viewed Productwithsku,product_id,category,priceAdded to Cartwithsku,quantity,cart_valueStarted Checkoutwithcart_value,num_itemsOrder Completedwithorder_id,revenue,items
- Confirm events and identities in Customer.io before launching messages
Use Customer.io’s activity/event views to verify:- events arrive with the expected properties
- anonymous activity merges into the identified profile
- device records exist for the user (important for mobile in-app delivery)
- Create your in-app message and target it with real conditions
Start with one high-intent use case (cart recovery on app open). Target based onAdded to Cartwithin X hours AND noOrder Completedsince that event. Add frequency caps so you don’t burn users. - Instrument message interactions
Make sure impressions, clicks, and dismissals are recorded. These become your suppression logic (e.g., don’t show again if dismissed) and your optimization loop.
When Should You Use This Feature
In-app works best when the user is already “in the buying environment” and you need to remove friction or increase intent. If you’re trying to resurrect someone who hasn’t opened the app in 45 days, email/SMS/push usually does the heavy lifting—and in-app becomes the landing experience once they return.
- Cart recovery on next app open: show a reminder only if the cart is still active and the user hasn’t purchased.
- Browse-to-buy nudges: if someone viewed the same product twice in 24 hours, show a message with social proof or a bundle option.
- Post-purchase cross-sell: after
Order Completed, show a “complete your routine” message on the next session (not immediately after checkout when they’re trying to leave). - Replenishment for consumables: use
Order Completed+ SKU-level expected replenishment window; show in-app when they open near day 25–35. - Reactivate lapsed app users once they return: if last order > 90 days and they open the app, show a “welcome back” offer—but only once, and only to high-LTV segments.
Operational Considerations
Most in-app programs break because the data looks “mostly right” but isn’t reliable enough to automate against. Treat SDK tracking like revenue infrastructure: define the contract, validate it, then build orchestration on top.
- Segmentation depends on property hygiene: if
cart_valueis sometimes a string, sometimes a number, your “cart > $75” segment will be wrong. Normalize types and required fields. - Identity stitching is the unlock: if a user adds to cart anonymously then logs in, you need that cart event on the known profile or your cart recovery audience shrinks dramatically.
- Event ordering matters: mobile networks are messy. If
Order Completedarrives late, you can accidentally show a cart reminder after purchase. Mitigate with short delays, “has not purchased since…” logic, and server-side confirmation where possible. - Orchestration across channels: avoid double-tapping users with push + in-app + email for the same intent. In most retention programs, we’ve seen better results when in-app is the “on-site closer” and push/email are the “bring them back” layer.
- Frequency and suppression rules: implement caps per message and global caps per day/session. Also suppress after dismissal or after the user completes the goal action.
Implementation Checklist
If you run through this list before launch, you’ll avoid the classic “it works on my phone” rollout. The goal is predictable targeting and clean measurement, not just messages rendering.
- SDK initialized at app start on all platforms you support
identify(userId)fires on login/signup and after token refresh/silent login- Anonymous browsing events tracked and merged into the identified profile
- Canonical event names standardized across iOS/Android/web
- Required properties present and typed consistently (numbers as numbers, timestamps as timestamps)
- Core commerce events implemented: view, add-to-cart, checkout, purchase
- Message impression/click/dismiss tracked and visible in reporting
- Segments validated with real users (not just test profiles)
- Frequency caps + suppression rules defined (dismissed, purchased, converted)
- Cross-channel rules documented (so push/email don’t collide with in-app)
Expert Implementation Tips
Once the basics are live, the biggest lift comes from tightening your identity and event schema so you can safely personalize and suppress. This is where in-app stops being “a banner tool” and starts being a conversion lever.
- Send SKU-level context, not just totals: cart recovery performs better when you can reference the exact item and deep link back to the cart or PDP.
- Delay slightly to avoid race conditions: for cart reminders on app open, a 5–30 second delay often prevents showing a message while the cart is still loading or right after a purchase event is about to arrive.
- Use dismissals as intent signals: if a user dismisses twice, stop showing that message for 7–14 days and switch to a different angle (bundle, reviews, or replenishment timing).
- Stitch identities with a single source of truth: pick one stable
customer_idacross app, web, and backend. If you bounce between email-based IDs and internal IDs, you’ll create duplicates and your targeting will drift. - QA with production-like behavior: test anonymous browse → add to cart → login → app reopen. That’s the path that exposes stitching failures.
Common Mistakes to Avoid
These are the issues that cause “in-app isn’t working” tickets—when the real problem is tracking, identity, or orchestration.
- Identifying too late: if you only call
identifyafter checkout, you lose most behavioral targeting opportunities. - Inconsistent event names across platforms:
Added to Cartvsadd_to_cartsplits your audiences and wrecks reporting. - Missing properties needed for segmentation: if you don’t send
cart_valueorsku, you can’t prioritize high-value carts or personalize the message. - No suppression after purchase: nothing kills trust faster than “complete your purchase” after someone already paid.
- Over-messaging: showing an in-app message every session trains users to ignore it. Cap aggressively and earn the impression.
- Testing only with internal accounts: employee behavior doesn’t match real shoppers; validate with a small live cohort and watch event timelines.
Summary
If your SDK identity and events are clean, Customer.io in-app becomes a reliable conversion layer for cart recovery and repeat purchase. If identity stitching is shaky, you’ll spend your time chasing ghosts in segments and wondering why performance is inconsistent.
Prioritize: initialize early, identify immediately, track a tight commerce schema, and orchestrate with suppression across channels.
Implement Set Up In App with Propel
If you’re rolling out in-app as part of a broader retention program, the fastest path is usually: lock the event schema, validate identity stitching, then build 2–3 high-intent in-app plays (cart, replenishment, post-purchase cross-sell) on top of Customer.io. That sequencing avoids the common trap where messages ship before the data is trustworthy.
If you want help pressure-testing your SDK plan and the suppression/orchestration rules before launch, you can book a strategy call and we’ll review your identify timing, anonymous merge behavior, and the exact events/properties needed to hit your retention goals.