Summarize this documentation using AI
Overview
Deep links are one of the highest-leverage fixes in retention because they remove friction between a message and the next purchase. If you’re sending push or SMS from Customer.io and you want customers to land on the right screen in your app (not just your homepage), deep links are the operational baseline—and if you want help pressure-testing your tracking and routing, you can book a strategy call.
In most retention programs we’ve seen, deep links don’t fail because the URL is wrong—they fail because identity and event timing are inconsistent. The SDK is where you earn reliability: correct identify calls, clean event payloads, and deterministic routing on open.
How It Works
At a practical level, a “deep link” is just a URL that your app knows how to interpret and route. Customer.io is responsible for sending the message and tracking the click/open; your app is responsible for handling the link and firing the right events so you can segment, suppress, and measure downstream revenue.
- Message contains a deep link: you place an app link (Universal Link / App Link / custom scheme) in a push, SMS, or email CTA.
- User taps the link: the OS opens your app (or falls back to web/store depending on your setup).
- Your app routes the user: you parse the URL, extract parameters (like
cart_id,product_id,discount_code), and navigate to the intended screen. - SDK stitches identity + tracks behavior: you call
identifyonce you know who the user is, and you track events likeDeep Link Opened,Checkout Started, andOrder Completed.
D2C scenario: A customer abandons checkout in your app. You send a push 2 hours later: “Your cart is waiting—checkout in 1 tap.” The deep link routes to /checkout?cart_id=123. When they open, your app logs Deep Link Opened with cart_id, then logs Checkout Started when the checkout screen renders. That’s what lets you suppress the SMS fallback for people who already resumed checkout, and it’s what makes attribution believable.
Step-by-Step Setup
Before you touch campaigns, get the app-side plumbing right. Deep links are only “done” when the app opens the correct screen for both cold starts and warm starts, and your event stream clearly shows what happened.
- Install the Customer.io SDK for your platform
- Use the official Customer.io Mobile SDK (iOS/Android/React Native/Flutter/Expo) and initialize it at app start.
- Confirm you’re sending device tokens (push) and that the SDK is active in production builds (not just debug).
- Implement identity correctly (this is where most teams leak)
- Call
identify(userId)immediately after login or account creation. - If you support guest browsing, track anonymously first, then identify on login and ensure you merge/associate pre-login activity where your architecture supports it.
- Send stable identifiers (your internal customer ID) and keep email/phone as attributes—not as the primary ID if they can change.
- Call
- Set up deep link handling in the app
- iOS: configure Associated Domains for Universal Links; handle incoming URLs in
application:continueUserActivity:(or SceneDelegate equivalent). - Android: configure App Links (intent filters + assetlinks.json); handle intents in your launcher activity and any relevant entry points.
- Support both cold start (app was closed) and warm start (app already running) paths.
- iOS: configure Associated Domains for Universal Links; handle incoming URLs in
- Define a deep link contract (keep it boring and consistent)
- Standardize paths like
/pdp,/cart,/checkout,/order,/account. - Standardize parameters:
product_id,variant_id,cart_id,campaign_id,message_id,utm_*. - Decide what happens when data is missing (ex: if
cart_idis invalid, route to cart with a toast, not a blank screen).
- Standardize paths like
- Track deep link opens and downstream conversion events
- On link open, track an event like
Deep Link Openedwith properties:url,path,campaign_id,message_id, and the business object ID (cart_id/product_id). - Track “screen rendered” events (ex:
Checkout Viewed) separately from “action” events (ex:Checkout Started), so you can debug routing vs intent. - Ensure purchase events include order identifiers and revenue so Customer.io reporting and goal logic can work cleanly.
- On link open, track an event like
- Validate end-to-end with real devices and real message clicks
- Send yourself a push/SMS from Customer.io with the deep link.
- Test on iOS + Android, and test both installed and not-installed behaviors (fallback handling).
- Confirm the event sequence in Customer.io: message click/open → deep link opened → checkout viewed → purchase (or exit).
When Should You Use This Feature
Deep links are worth the engineering time when you’re trying to reduce steps between “interest” and “transaction,” or when you need cleaner orchestration between channels. If you’re serious about cart recovery and repeat purchase in-app, you’ll feel the difference immediately.
- Cart recovery (app-first): route to
/checkout?cart_id=…so the customer lands on the exact checkout state they left. - Replenishment / repeat purchase: route to a pre-filled PDP or “buy again” flow with the right variant selected.
- Winback to a specific collection: route dormant customers to a curated collection based on their last category purchased.
- Post-purchase cross-sell: route to “complete your routine” bundles, not generic recommendations.
- Back-in-stock / price drop: route directly to the variant that triggered the alert, not the product’s default variant.
Operational Considerations
Deep links create leverage, but they also increase the number of places your program can break: segmentation depends on the right events, orchestration depends on timing, and your data flow has to reconcile anonymous and logged-in behavior.
- Segmentation depends on “resume intent” events: if you don’t track
Deep Link OpenedandCheckout Viewed, you can’t reliably suppress follow-ups. You’ll end up spamming people who already came back. - Identity stitching is the difference between “clicked” and “converted”: a customer can tap a link while logged out. If you only identify after checkout, your attribution and suppression logic will look random.
- Campaign parameters need governance: keep a consistent set of parameters across channels so you can build reusable segments (ex: all checkout links include
intent=checkout). - Orchestration reality: clicks aren’t enough: in practice, use “opened checkout screen” as the suppressor, not “clicked message.” People click accidentally; they don’t accidentally load checkout.
- Fallbacks matter for LTV: if the app isn’t installed or the link can’t be resolved, route to mobile web PDP/cart and still track the visit so you can continue the recovery flow.
Implementation Checklist
If you want deep links to actually improve revenue (not just look good in a QA test), you need a tight loop between app routing, Customer.io identity, and event semantics.
- Customer.io SDK initialized in production builds
identify()called immediately after login/account creation with a stable customer ID- Universal Links/App Links configured and verified on real devices
- Deep link handler supports cold start + warm start
- Deep link contract documented (paths + required params + fallbacks)
Deep Link Openedevent tracked withcampaign_id/message_idand business object IDs- Checkout and purchase events tracked with order/cart identifiers and revenue
- Customer.io segments built for: opened checkout, purchased, and “still abandoned”
- Suppression rules use behavior events (viewed checkout/purchased), not just clicks
Expert Implementation Tips
Once the basics work, the wins come from making deep links predictable for your team and forgiving for your customers. That’s what keeps your cart and winback programs stable as you scale message volume.
- Make deep links idempotent: opening the same link twice shouldn’t duplicate carts, re-apply discounts incorrectly, or throw the user into an error state.
- Track “route success” vs “route failure”: add a boolean like
routed=trueand aroute_errorstring when something fails. This is how you catch broken links before revenue drops. - Use a single “intent” parameter: e.g.
intent=checkout,intent=reorder. It makes segmentation and reporting dramatically easier. - Don’t rely on last-click attribution for suppression: in multi-channel recovery (push → SMS → email), suppress based on the first meaningful app event (checkout viewed/purchased), not which message they clicked.
- Keep link parsing logic centralized: one router module beats five different implementations across screens. In practice, this tends to break during app refactors unless you treat it like a core system.
Common Mistakes to Avoid
Most deep link issues show up as “campaign performance got worse” when the real problem is that routing or identity is inconsistent. These are the ones that repeatedly bite D2C teams.
- Only testing warm-start: cold-start deep links often drop parameters or route to the wrong screen.
- Calling
identify()too late: if you identify after checkout, you lose the ability to suppress messages during the recovery window. - Using mutable identifiers: using email as the primary ID creates duplicate profiles when customers change emails or use Apple Private Relay.
- No event for “opened the intended screen”: without a
Checkout Viewed-type event, you can’t distinguish curiosity clicks from real recovery. - Deep links that assume state: links that require an existing cart/session often fail for logged-out users. Always design a fallback path.
- Overstuffed parameters: if every team invents new params, your segmentation becomes impossible to maintain. Standardize.
Summary
If your app is a primary purchase surface, deep links are a retention primitive—not a nice-to-have. Get identity and event tracking right in the SDK, and you’ll recover more carts, drive more repeat purchases, and stop wasting touches on people who already came back.
Implement Deep Links with Propel
Deep links are straightforward until you’re debugging why Android cold starts don’t pass cart_id, or why your suppression segment misses half your “resumed checkout” users. If you’re building this inside Customer.io and want an operator’s second set of eyes on SDK identity stitching, event semantics, and orchestration logic, you can book a strategy call and we’ll map the cleanest implementation path for your retention program.