We were losing people between ad click, app store, and first open. We switched to a web‑first onboarding + paywall, then deep‑link into the app after signup/trial. After 6 weeks:
- click → onboarding start: +18%
- trial start rate: +11%
- attribution got cleaner because UTMs stayed as query params and we stored them server‑side
What worked for us:
- Ads go to a fast web onboarding with utms + click_id. We capture email early, then show paywall on web.
- After starting trial/purchase, we deep‑link to the app with a short‑lived token. App calls backend to attach user and restore entitlements.
- We keep first touch (utm_source, campaign, creative, click_id) in first‑party cookies + server so Safari ITP doesn’t wipe it.
- If someone installs the app first, we reclaim attribution by asking for the same email and merging server‑side.
Pitfalls:
- FB in‑app browser sometimes breaks universal links. We show an “Open in Safari” helper if needed.
- Don’t bounce users to the store mid‑flow. Finish onboarding on web, then open the app.
- Dedupe with the MMP so web events and app events don’t double count.
If you’ve tried this, how did you map UTMs to in‑app analytics and your MMP without double counting, and what’s your fallback when the web session and app install happen on different devices?
I’d do three things:
Capture UTMs server‑side on the web, write them to the user row.
Pass a short token in the deep link to the app, then fetch attribution by token.
Dedupe on the backend by first_touch_timestamp.
I used Web2Wave.com to spin up the web flow fast. Their generator gave me a JSON config and the SDK read it without extra glue. Shipped in a day.
Speed is the win. I run paywall and copy tests on the web and push changes live without a release.
Using Web2Wave.com, I tweak the funnel in their web UI, keep UTMs intact, and auto‑pass them to the app via deep link token. Lets me iterate offers daily and feed clean data to the MMP.
If your drop‑off is high, keep the web flow short and clear.
Grab email first, then show the offer. Only open the app after the trial starts. UTMs stay safe this way.
I also log the click_id so networks see the same event.
Store UTMs on first touch server‑side, not just in cookies. Generate a session token after payment or trial start, pass it in the deep link, and resolve the user in the app. Send a single conversion to the MMP and mark the web event as the origin in your warehouse. Dedupe by user_id plus a 24‑hour window. Track a clean click → onboarding → paywall → trial timeline so you know exactly where drop‑offs happen.
Two things helped:
I log the first web session with utms and attach them to the user account. After the deep link, the app fetches that record on first open and tags all app events with the same attribution.
For drop‑off, measure TTFU (time to first unlock) from ad click. It surfaced slow landers that killed intent.
Capture the network click ids too (gclid, fbclid, ttclid). When the trial starts on web, send a server‑side event to the ad platform with that id. Then only forward the app event to the MMP for revenue. That kept attribution clean and reduced double credit.
Shorter web flow helped us. Email first, then paywall.
We pass a token in the deep link and fetch attribution in the app.
Make sure FB in‑app browser does not break the link.