decentraland / decentraland/auth
Referrals from invite links are never recorded on mobile (skipSetup bypasses the only POST /referral-progress call site)
- Dominant language
- TypeScript
- Stars
- 0
- Forks
- 3
- Avg merge
- 8h 13m
- Merged PRs (30d)
- 37
Description
## Problem
The referral POST only happens on `QuickSetupPage`, and mobile never reaches that page, so referrals from invite links are never recorded for mobile visitors.
Chain as it stands:
1. `decentraland.org/invite/:name` resolves the name to a wallet and sends the visitor to `/auth/login?referrer=0x…&redirectTo=…`.
2. `QuickSetupPage` posts `POST /referral-progress { referrer }` on mount when the profile is missing or incomplete, then `PATCH /referral-progress` after the profile deploy.
3. Getting to QuickSetup depends on `ensureProfile`, which callers skip when `useSkipSetup()` is true.
4. `useSkipSetup()` returns true whenever `targetConfig.skipSetup` is set, and `getTargetConfigId` returns `ios` / `android` for any mobile user agent. Both mobile configs set `skipSetup: true`.
So on mobile, `ensureProfile` never runs, QuickSetup never mounts, and neither the POST nor the PATCH ever fires. Same applies to the `alternative` and `creator-hub` target configs.
This matters because the invite links are being handed out mainly through Twitch streams, where the audience is largely on phones.
## Evidence
`PROD.FCT_REFERRAL_PROGRESS` all-time status distribution: `tier_granted=882`, `signed_up=500`, `pending=124`, `rejected_ip_match=27`. Referrals do get created, but the model carries no signal that separates the mobile drop-off from ordinary abandonment, because no row is ever written for those visitors.
Concrete case: `/invite/miyuki` (a Twitch DJ link shared on 2026-07-28) has 7 pageviews in `PROD.FCT_PAGEVIEWS` between 17:51 and 20:26 UTC that day, and zero rows anywhere in `FCT_REFERRAL_PROGRESS`. The name resolves correctly (`peer/lambdas/names/miyuki/owner` → `0xc5af27b8…3986`, claimed name), so the loss is downstream of `sites`.
## Why this is not a one-line fix
Moving the POST out of QuickSetup means calling it from the post-login paths (`CallbackPage`, `AutoLoginRedirect`) where the skip happens. But the POST today is gated on the profile being missing or incomplete, i.e. "this is a new user" — and skipping setup is precisely skipping that profile check. Firing it unconditionally would create referral records for accounts that already existed.
Needs a decision before implementing:
1. Does the referral service reject a `POST /referral-progress` when the invited user already has an account? If it does, the POST can be fired unconditionally on the skip path and the server stays the source of truth.
2. If it does not, the skip path needs a cheap new-user signal. `markReturningUser` is localStorage-based, so it reads as "new" on any fresh device and is not usable for this.
3. What replaces the `PATCH` on mobile, given there is no profile-deploy step in that flow?
Happy to implement whichever direction is preferred once (1) is answered.
## Related
- decentraland/auth#446 fixes the adjacent case where the wallet auto-login path dropped the referrer via a hardcoded `referrer: null`.
- decentraland/sites#705 fixes the invite page discarding the resolved referrer address when the Catalyst profile lookup failed.
Contributor guide
Research direction
Start with QuickSetupPage, useSkipSetup(), ensureProfile, CallbackPage, and AutoLoginRedirect to trace where the referral POST and PATCH currently occur and where mobile bypasses them. Check the referral service behavior for existing accounts and determine what can replace the profile-deploy step on mobile. Done means an agreed flow records valid mobile invite referrals without creating incorrect records for existing users.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- authentication, mobile
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Needs clarification
- Newbie friendliness
- 35/100