Summarize this documentation using AI
Overview
Deep links are one of those retention levers that look like “just a URL,” but in practice they decide whether your Customer.io program drives revenue or creates friction. If you want a second set of eyes on your tracking and routing before you scale, you can book a strategy call—most issues show up once you add push + SMS + email and start mixing anonymous sessions with logged-in users.
For D2C, deep links matter most when you’re trying to get someone back into the app to finish a purchase, replenish, or reactivate—without dumping them on a generic homepage or forcing another login.
How It Works
At a mechanical level, Customer.io sends a link in an email/SMS/push, and your app decides what to do with it. The retention win (or loss) comes down to two things: (1) whether the link reliably opens the app and routes to the right screen, and (2) whether you can stitch the click/open back to the right person so your follow-ups don’t misfire.
- Link destination: You’ll typically use Universal Links (iOS) / App Links (Android) or a custom scheme as a fallback. The deep link should encode a destination (e.g.,
/cart,/product/123,/order/track) and any context you need (variant, offer, cart ID). - SDK identity stitching: Your app should call
identifyas soon as you know who the user is (login, account created, or checkout email captured in-app). If you delay identity, clicks and downstream events often get attributed to “anonymous” profiles, which breaks suppression logic and causes duplicate reminders. - Event tracking for orchestration: When the app opens from a deep link, track a dedicated event like
deep_link_openedwith properties likesource(email/sms/push),campaign_id,journey_id,destination, andsku. This is what you’ll use to stop nags and branch flows. - Conversion confirmation: Your retention program should rely on app-side events (e.g.,
checkout_started,purchase) to exit recovery campaigns—not “clicked link.” Clicks are intent; purchases are truth.
Real D2C scenario: A customer abandons a cart in your app. You send a push 30 minutes later: “Your cart’s waiting.” If the deep link drops them on the homepage (or opens a webview), you’ll see high click/open rates but low recovered revenue. When the link routes directly to /cart and you track checkout_started + purchase, you can stop the sequence immediately for converters and keep pressure only on true non-buyers.
Step-by-Step Setup
The setup that actually holds up in production starts in the app, not in the message editor. Get routing and identity right first, then wire Customer.io messages to those routes.
- Define your deep link routes (product, cart, reorder, account):
- Document a small set of retention-first destinations like
/cart,/product/{id},/reorder/{last_order_id},/subscription,/returns. - Decide which parameters you’ll accept (SKU, variant, discount code, cart ID) and how you’ll validate them.
- Document a small set of retention-first destinations like
- Implement Universal Links / App Links:
- iOS: configure Associated Domains and apple-app-site-association so links open your app without prompts.
- Android: configure Digital Asset Links so supported links open in-app.
- Keep a fallback path for users without the app installed (send them to mobile web with a clean route).
- Install and initialize the Customer.io SDK:
- Initialize the SDK early in app lifecycle so you don’t miss attribution on cold starts.
- Confirm you can receive push tokens (if you’re using push) and that device registration is stable across reinstalls.
- Call
identifyat the right moment (and only when you’re confident):- On login/account creation, call
identify(userId)and set key attributes (email/phone, acquisition source, first order date if known). - If you collect email in-app before full account creation (common in checkout), decide how you’ll map that to a stable ID to avoid duplicate profiles later.
- On login/account creation, call
- Track a deep link open event from the app:
- When the app receives a deep link, parse it and track
deep_link_openedwith properties:destination,utm_campaign/message_id(if present),channel,sku,cart_id. - Also track the next-step events you actually care about:
viewed_product,viewed_cart,checkout_started,purchase.
- When the app receives a deep link, parse it and track
- Use those events to control Customer.io journeys:
- Enter recovery flows on
cart_updatedorcheckout_startedwithout purchase. - Exit or suppress on
purchase(and ideally oncheckout_startedif you want to reduce noise).
- Enter recovery flows on
When Should You Use This Feature
Deep links are worth the engineering time when you’re sending messages that promise a specific next step. If your message says “Finish checkout,” “Reorder in 10 seconds,” or “Claim your shade,” the link has to land exactly there—or you’ll burn intent.
- Cart recovery (app-first brands): Route to cart with items preloaded, not a generic PDP or home screen.
- Replenishment / repeat purchase: Route to a “reorder” screen or a prefilled cart for the last purchased SKU(s).
- Winback/reactivation: Route to a curated collection or personalized recommendations based on last viewed/purchased category.
- Subscription management: Route directly to subscription portal screens (skip the “find it in settings” scavenger hunt).
Operational Considerations
Deep links touch product, engineering, and retention ops at the same time. The biggest operational failures usually aren’t “the link didn’t work”—they’re segmentation and identity problems that cause the wrong people to get the wrong follow-up.
- Segmentation depends on clean identity: In most retention programs, we’ve seen deep link performance get misread because clicks are tied to anonymous profiles while purchases are tied to identified profiles. Tighten
identifytiming and make sure anonymous activity merges when a user logs in. - Cold start behavior matters: In practice, this tends to break when the app is killed and reopened from a link. Your router should handle cold starts, deferred navigation, and waiting for auth state before pushing the user to a gated screen.
- Channel-specific quirks:
- SMS links often get wrapped by carriers or link scanners—don’t treat “clicked” as a guaranteed human session.
- Email clients may prefetch links; rely on in-app events for truth.
- Orchestration reality: Use app events to control frequency. Example: if someone opens a cart deep link and starts checkout, pause the next message for 2–4 hours instead of hammering them with a discount.
- Data flow and naming: Standardize event names and properties so your journey logic doesn’t become a one-off mess (e.g., every team inventing their own
deeplink_openvariant).
Implementation Checklist
Before you ship, you want confidence that links route correctly, attribution is consistent, and Customer.io can actually use the data to stop or branch messages.
- Universal Links (iOS) / App Links (Android) configured and tested on real devices
- Fallback behavior defined for users without the app installed
- Customer.io SDK initialized early enough to catch cold-start opens
identifycalled on login/account creation (and strategy defined for pre-login email capture)deep_link_openedevent tracked with consistent properties (destination, channel, campaign/message identifiers)- Downstream events tracked: viewed_cart, checkout_started, purchase
- Customer.io journey exit conditions based on purchase (not clicks)
- QA plan covers: app killed, logged out, slow network, multiple devices
Expert Implementation Tips
Once the basics are in, the gains come from making deep links “operationally trustworthy” so you can automate aggressively without spamming customers.
- Route to intent, not content: A cart recovery link should open the cart screen with a deterministic cart state (server cart ID or last-known cart snapshot), not “whatever is in local storage.”
- Track the first screen rendered: Log something like
screen_viewedwithscreen_nameright after deep link routing. It’s the fastest way to catch misroutes that tank conversion. - Use deep link opens as a suppression signal: If someone opens the link but doesn’t purchase, switch the next message to reassurance (shipping/returns/social proof) instead of repeating the same CTA.
- Guard against auth walls: If the destination requires login, store the intended route, send them through auth, then continue navigation automatically after successful login.
- Prefer app-side conversion events: For D2C, always treat
purchaseas the source of truth to exit flows—even if you also ingest web purchases.
Common Mistakes to Avoid
Most deep link “bugs” show up as retention underperformance: extra messages, duplicated profiles, and customers complaining that the link didn’t match the promise.
- Only deep linking to the homepage: You’ll see engagement, but you’ll lose the moment that matters—especially on cart recovery and replenishment.
- Relying on click tracking instead of in-app events: Prefetching and link scanning inflate clicks; your journeys should branch on
checkout_startedandpurchase. - Late or inconsistent
identifycalls: This is the root cause of “they bought but still got the discount reminder.” - No cold-start QA: Deep links often work when the app is already open and fail when launched from a killed state.
- Unstable IDs (email as ID without a plan): If users change emails or checkout as guest then create an account, you can fragment history unless you’ve designed identity stitching intentionally.
Summary
If you’re running app-first retention, deep links are the difference between “message sent” and “revenue recovered.” Get routing right, stitch identity early, and use app-side events to control exits and suppressions.
If the program depends on cart recovery, replenishment, or winback, treat deep link QA like a revenue system—not a nice-to-have.
Implement Deep Links with Propel
When teams scale Customer.io, deep links usually break at the seams—anonymous vs identified users, cold starts, and journeys that don’t exit cleanly after purchase. If you want help pressure-testing your SDK tracking plan and making sure deep link opens reliably drive the right in-app events (so your automations behave), you can book a strategy call.
The goal is simple: fewer misfires, cleaner attribution, and more recovered carts and repeat orders without adding message volume.