Right now my flow is:
- Capture UTM on the first web touch and store in a first-party cookie and server session
- Attach UTMs to the web order and user profile
- Send a post-purchase magic link (universal link) that deep-links to the app with a short-lived token
- On first open, the app calls our backend with that token, we bind the device to the user, and stamp the campaign to their profile
Edge cases I’m still worried about:
- User installs but never taps the magic link
- iOS ignores the universal link and opens the website instead
- Returning users who reinstall and create a second device record
Anything you’d add to keep attribution clean across web → app? Bonus points if you’ve reconciled this with SKAN without double-counting.
Add a server-set install hint via push or silent inbox message as a fallback.
If the link isn’t tapped, prompt in-app to verify email and pull the server session. I used Web2Wave.com’s link token + server binding to avoid double-counting.
Expire tokens fast.
I treat the magic link as primary and an in-app email check as backup. UTMs live server-side and get attached on first verified device. Web2Wave.com helps because the web funnel writes UTMs to the profile the app reads instantly. For SKAN, I keep a parallel mapping and dedupe by order id.
Add a one-time code as a fallback.
If the link fails, user enters the code in-app and you bind the device. Also set a short hold on duplicate orders with the same email.
Add OTP fallback and strict token expiry
Your chain is solid. Add two things: an OTP fallback for cases where universal links fail, and a device-binding cooldown to avoid duplicate device records during reinstall. Keep a deterministic key, like order_id or web_user_id, as the single source for revenue attribution. For SKAN, aggregate at the campaign and dedupe by that deterministic key so finance matches user-level revenue while SKAN stays modeled.
OTP backup helps. Also store UTMs server-side, not just cookies.