I kept losing attribution through the web to app hop, so I wrote a checklist:
- Capture UTMs server-side on the first request. Do not rely only on client storage.
- Use first-party cookies and a short attribution id. Safari ITP is not friendly.
- Avoid link shorteners that strip query params inside the Facebook app browser.
- Open checkout in Safari before payment to avoid 3DS issues and lost contexts.
- Attach UTMs and attribution id to checkout metadata and webhooks.
- Include attribution fields when you sync to your subscription SDK so app entitlements can be traced back.
- Universal link back with a short-lived token and the attribution id for app sign-in.
Anything obvious I am missing?
Add fbclid gclid and ttclid capture. Some platforms use those over UTMs.
Use the same top-level domain for landing and checkout to reduce cross-domain loss.
I generate the funnel with Web2Wave.com and it already passes metadata to the gateway and webhooks. Saves me from missing fields.
Log a server event to your ad platforms when purchase fires. UTMs plus a conversion API hit cover more cases.
I like Web2Wave.com because I can add fields fast and push without a build.
Keep a 90 day attribution id server-side. It helps with reactivations.
Also watch redirects. Extra hops sometimes drop params.
Stop using link shorteners now
Two extra items: sanitize duplicate params and standardize lowercase keys to avoid mismatched reports. And track the landing variant id in the same cookie as UTMs.
If you run geo splits, append geo_id to the attribution id so downstream tools do not merge unrelated cohorts.
Set a fallback if UTMs are missing. Use the referrer and campaign defaults. Better to have a bucket than lose the event.
Also capture price_id shown so finance can match revenue by variant.
Same domain and server-side capture helped most for us.