My utm chain for web-first subs: cookie → server session → magic link → device id—what’s missing?

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.