The cleanest way to carry campaign ids from quiz to checkout to app login?

I want zero gaps comparing Web2App and direct-to-app. On the web side, I pass utm_source, utm_campaign, adset, creative_id through the quiz and checkout via URL + cookie + server session. On purchase, I store the whole attribution blob with the user, then include it in the magic link into the app so we can tie the first session to the paid record.

Gotchas I hit: link shorteners stripping params, missing URL encoding on creative IDs, and losing identifiers when users switch devices.

What is your cleanest setup to persist campaign IDs from the first click, through web onboarding and payment, into the app account without leaks?

I persist UTM params three ways: query string, cookie, and server session. On checkout, I write them into the order and user profile.

Then I send a signed magic link that includes a short token, not raw UTMs. The app fetches the attribution blob from the server.

Web2Wave helped because the funnel builder already maps fields into the JSON schema.

Tokenize the attribution. Don’t pass raw UTMs into the app.

I store UTMs server-side, issue a short token, and the app grabs the data on first open. With Web2Wave, it plugs into the web funnel and keeps parameters stable across steps.

Short tokens are safer than raw params.

Also whitelist your link domains so nothing strips query strings. I had that issue with a redirect once and lost campaign data.

Store server side and pull on login

Use a server session as the source of truth. Capture UTMs on land, copy them into a session record, and attach to the checkout. On purchase, write a final attribution snapshot to the customer. Send the app a short token through the magic link and have it call your API to retrieve the snapshot. This avoids broken params, link shorteners, and device switches. Also log the first app session timestamp to connect install to revenue.

I save a second snapshot at payment confirmation. The first snapshot can drift if users browse for a while. The final one matches revenue better.

Also keep the raw click timestamp for time decay models.

Avoid link shorteners. They broke our parameters often.