Summarize this documentation using AI
Overview
If you’re running Customer.io for retention, in-app messaging only works as well as your SDK identity and event tracking. If you want a second set of eyes on your tracking plan before you scale journeys, book a strategy call—most issues we see in production come down to “we can’t reliably tell who did what, on which device, and when.”
In-app is the channel you use when email/SMS is too slow or too noisy: nudging a shopper back to checkout, handling an out-of-stock substitution, or pushing a replenishment prompt the moment they reopen the app.
How It Works
In practice, Customer.io in-app messaging is a three-part system: the SDK captures device context, you stitch the user’s identity when you actually know who they are, and events/attributes determine who qualifies for a message and when it shows up.
- SDK installs a device identity: when your app loads, the SDK creates/uses a device-level identifier so Customer.io can target a device even before login.
- You “identify” the person: once a user logs in (or you otherwise know their customer ID/email), you call
identifyso Customer.io can stitch pre-login activity to the known profile. This is where most retention programs either get clean attribution—or fall apart. - You track events + attributes: events like
Product Viewed,Added to Cart,Checkout Started, andOrder Completedbecome triggers and filters. Attributes likelast_order_date,vip_tier, orpush_opt_inbecome segmentation levers. - In-app messages render inside the app: when a person qualifies for a campaign/workflow step, Customer.io delivers an in-app payload and the SDK displays it. Your job is to ensure the “qualified person” is the right person and the “right moment” is based on accurate events.
Real D2C scenario: A shopper browses products anonymously, adds a bundle to cart, then logs in at checkout. If you only identify after purchase (or you identify with a different ID than you use on web), your cart recovery in-app message will either never fire or fire on the wrong profile. Clean identity stitching is what makes that recovery message feel “smart” instead of random.
Step-by-Step Setup
Before you build any journeys, get the SDK foundation right. You’re aiming for: consistent IDs across platforms, predictable event naming, and a clear rule for when anonymous activity merges into a known profile.
- Install the Customer.io SDK for your app platform
Add the iOS/Android (or React Native/Flutter) SDK to your app, and confirm it initializes on app launch. The first success criteria: you see device activity coming into Customer.io from a test device. - Decide your canonical customer identifier
Pick one stable ID as the source of truth (e.g., your internalcustomer_id). In most retention programs, using email as the primary ID creates edge cases (email changes, aliasing, Apple Hide My Email). Use email as an attribute, not the identifier. - Call
identifyimmediately after login (and only when you’re sure)
When the user authenticates, callidentifywith the canonical ID and core attributes (email, phone if you have it, marketing opt-in flags, timezone if reliable). This is the moment where anonymous browsing and carting should stitch to the known profile. - Track the retention-critical events (not “everything”)
Start with a tight event taxonomy that maps to money:Product Viewed(includeproduct_id,category)Added to Cart(includeproduct_id,quantity,cart_value)Checkout Started(includecart_value)Order Completed(includeorder_id,order_value,items)App Opened(or rely on SDK lifecycle events if available)
- Validate identity stitching with a real test flow
Run this exact QA path on a fresh install: browse anonymously → add to cart → log in → abandon → reopen app. Confirm the same person profile shows the full timeline (anonymous + known) and qualifies for the intended segment. - Build one in-app message as an end-to-end proof
Example: trigger an in-app reminder whenCheckout Startedhappened butOrder Completeddid not within 60 minutes, and the user opens the app. This forces your tracking, timing, and identity to work together.
When Should You Use This Feature
In-app messaging shines when you need a high-intent touch at the exact moment someone is active. It’s not a replacement for email/SMS—it’s the “right now” layer that improves conversion and repeat rate when your data is tight.
- Cart recovery on app reopen: if someone starts checkout and returns later, show a message that deep-links back to the cart with the exact items they left.
- Product discovery after browsing: if they viewed 3+ products in a category but didn’t add to cart, show a curated best-sellers module the next time they open the app.
- Replenishment and repeat purchase: if
Order Completedwas 25–35 days ago for a consumable SKU, prompt a reorder when the app opens (and suppress if they already repurchased on web). - Reactivation for lapsed app users: if they haven’t opened the app in 30+ days but are still buying via email, use in-app to push them into app-exclusive bundles when they finally return.
Operational Considerations
Most “in-app doesn’t work” complaints are really segmentation and data-flow problems. Treat in-app as orchestration across devices and channels, not a standalone pop-up tool.
- Segmentation depends on event freshness: if your app queues events offline and flushes later, “within the last 30 minutes” logic will misfire. Use windows that match your real delivery latency, or send server-side confirmation events when possible.
- Identity stitching across web + app: if web uses email as identifier and app uses customer_id, you’ll split profiles and double-message. Align identifiers across all sources before scaling journeys.
- Suppressions prevent channel pile-ups: if someone is in an SMS cart recovery flow, don’t also hit them with an in-app cart modal the moment they open the app unless you intentionally designed a sequence.
- Deep links are the difference between “nice” and “profitable”: every in-app should land the user exactly where they need to act (cart, PDP, reorder page), not the home screen.
- Frequency control is retention protection: in-app is easy to overuse. Cap exposures per user per day/week, especially for browse-based triggers.
Implementation Checklist
Use this as your pre-flight before you let in-app messages touch real revenue flows like checkout recovery or replenishment.
- SDK initializes reliably on app launch (verified on real devices, not just simulators)
- One canonical identifier chosen and used consistently across app + other sources
identifycalled immediately after login with stable ID + core attributes- Key commerce events tracked with consistent names and required properties
- Anonymous-to-known stitching validated with a real browse → login → purchase/abandon flow
- Segments built off events are QA’d for timing (event delay, timezone, offline behavior)
- At least one end-to-end in-app campaign tested with deep link + suppression rules
- Frequency caps and channel conflict rules defined (email/SMS/push vs in-app)
Expert Implementation Tips
Once the basics are live, the wins come from tightening identity, making triggers more “intent-aware,” and designing messages that respect the rest of your retention system.
- Identify earlier than you think: if you have a “continue as guest” flow but collect email for receipts or loyalty, identify as soon as you have a stable key. Waiting until full account creation leaves a lot of high-intent activity stranded as anonymous.
- Use a two-event pattern for cart recovery: trigger off
Checkout Started, but gate the message onApp Openedafter X minutes. That keeps the message from showing mid-checkout and focuses on true abandonment. - Normalize product IDs and categories: in practice, teams break personalization by sending different IDs from different app screens. Pick one catalog ID format and enforce it in tracking.
- Build “stop” events: for every nudge, define what cancels it (e.g.,
Order Completed,Cart Emptied,Subscription Started). This prevents stale in-app prompts that feel spammy.
Common Mistakes to Avoid
These are the issues that create ghost segments, duplicated users, and in-app messages that look fine in QA but miss in production.
- Using different identifiers per platform: app uses
customer_id, web uses email, support tool uses another key—now you have three “people” and none of your suppression logic works. - Calling
identifywith unstable values: using a session ID, device ID, or temporary checkout token as the person ID guarantees profile fragmentation. - Tracking events without the properties you need to segment: “Added to Cart” without
cart_valueorproduct_idlimits you to generic messaging and weak prioritization. - Not accounting for offline event flush: your “within 1 hour” cart recovery becomes “within 1 hour of when the phone came back online.”
- No deep link, no conversion: sending users to the home screen is the fastest way to make in-app look like it ‘doesn’t work.’
Summary
If you want in-app messaging to drive revenue, treat SDK identity and event tracking as the product—not the message design. Get identify right, track a small set of high-signal commerce events, and only then scale cart recovery, replenishment, and reactivation.
Implement Set Up In App with Propel
When teams implement in-app inside Customer.io, the work is rarely the UI setup—it’s getting clean identity stitching across app/web and making sure events arrive in time to orchestrate the right nudge. If you want an operator to pressure-test your SDK plan (IDs, event taxonomy, suppression rules, and QA flows), book a strategy call and we’ll map it to the retention programs you’re actually trying to run.