Carry the placement choice with the referral too
Auditing the rest of the prospect paths after Terry's leak. Every entry point funnels through /join/<id> — the Telegram Mini App redirects there, member page-builder pages link there, the public /my/<id> share panel links there — so the cookie covers all of them. One gap left: ?direct=1 is the inviter's explicit decision to take the join under themselves rather than route it down their leg, and only the id was being remembered. A prospect who opened a direct link and then wandered through the nav came back through the moving link instead — the opposite of what the shared link asked for. The flag now rides along in its own cookie, and both /start and /join-now prefer an explicit choice over the position's default. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
+4
-1
@@ -59,9 +59,12 @@ fetch('/api/public/config').then(function(r){return r.json()}).then(function(c){
|
|||||||
// someone's /join/<id> page. Without this a prospect who wandered through the nav
|
// someone's /join/<id> page. Without this a prospect who wandered through the nav
|
||||||
// enrolled under the company rotation and the inviter lost the referral.
|
// enrolled under the company rotation and the inviter lost the referral.
|
||||||
if(!ref){ try{ var ck=document.cookie.match(/(?:^|;\s*)rmc_ref=(\d{1,15})/); if(ck)ref=ck[1]; }catch(e){} }
|
if(!ref){ try{ var ck=document.cookie.match(/(?:^|;\s*)rmc_ref=(\d{1,15})/); if(ck)ref=ck[1]; }catch(e){} }
|
||||||
|
// ...and the placement choice the invite link carried, for the same reason.
|
||||||
|
var directFlag=qp.get('direct');
|
||||||
|
if(directFlag!=='1'&&directFlag!=='0'){ try{ var cd=document.cookie.match(/(?:^|;\s*)rmc_direct=([01])/); if(cd)directFlag=cd[1]; }catch(e){} }
|
||||||
// Direct link (?direct=1): opt out of rotation — register straight under
|
// Direct link (?direct=1): opt out of rotation — register straight under
|
||||||
// the inviter (spillover in their team), never the next-to-qualify member.
|
// the inviter (spillover in their team), never the next-to-qualify member.
|
||||||
if(ref&&/^\d{1,15}$/.test(ref)&&qp.get('direct')==='1'){
|
if(ref&&/^\d{1,15}$/.test(ref)&&directFlag==='1'){
|
||||||
sponsorId=String(ref); $('sponsorLine').innerHTML='You’ll join <strong>directly under #'+ref+'</strong> — a spillover placement in their team.'; return;
|
sponsorId=String(ref); $('sponsorLine').innerHTML='You’ll join <strong>directly under #'+ref+'</strong> — a spillover placement in their team.'; return;
|
||||||
}
|
}
|
||||||
if(ref&&/^\d{1,15}$/.test(ref)){
|
if(ref&&/^\d{1,15}$/.test(ref)){
|
||||||
|
|||||||
+7
-2
@@ -26,7 +26,12 @@ async function load(){
|
|||||||
// Route exactly the way that member's own invite page would: their moving link sends
|
// Route exactly the way that member's own invite page would: their moving link sends
|
||||||
// the join to the next position in their leg, unless their position is set to take
|
// the join to the next position in their leg, unless their position is set to take
|
||||||
// direct placements. Same rules, so the two pages can never disagree.
|
// direct placements. Same rules, so the two pages can never disagree.
|
||||||
const t=(s.directDefault||!s.joinTarget)?{id:s.id,referralUrl:s.referralUrl,directCount:s.directCount}:s.joinTarget;
|
// an explicit ?direct=1/0 from the invite link wins over the position's default
|
||||||
|
const dq=(function(){try{const q=new URLSearchParams(location.search).get('direct');
|
||||||
|
if(q==='1'||q==='0')return q;
|
||||||
|
const m=document.cookie.match(/(?:^|;\s*)rmc_direct=([01])/);return m?m[1]:null;}catch(e){return null}})();
|
||||||
|
const goDirect=dq==='1'||(dq!=='0'&&(s.directDefault||!s.joinTarget));
|
||||||
|
const t=goDirect?{id:s.id,referralUrl:s.referralUrl,directCount:s.directCount}:s.joinTarget;
|
||||||
currentSponsor={id:t.id,name:null,directs:(t.directCount!==undefined?t.directCount:0),goal:2,referralUrl:t.referralUrl};
|
currentSponsor={id:t.id,name:null,directs:(t.directCount!==undefined?t.directCount:0),goal:2,referralUrl:t.referralUrl};
|
||||||
// say whose team this is, so it never reads as an anonymous "current placement"
|
// say whose team this is, so it never reads as an anonymous "current placement"
|
||||||
const badge=document.querySelector('.live-badge');
|
const badge=document.querySelector('.live-badge');
|
||||||
@@ -59,7 +64,7 @@ async function load(){
|
|||||||
// carry the inviter through to enrolment — /join-now already knows how to place a
|
// carry the inviter through to enrolment — /join-now already knows how to place a
|
||||||
// ?ref properly (direct placement or next open spot in their leg). Without this the
|
// ?ref properly (direct placement or next open spot in their leg). Without this the
|
||||||
// button dropped the referral on the floor and enrolled under the company rotation.
|
// button dropped the referral on the floor and enrolled under the company rotation.
|
||||||
document.getElementById('joinButton').href='/join-now'+(ref?('?ref='+encodeURIComponent(ref)):'');
|
document.getElementById('joinButton').href='/join-now'+(ref?('?ref='+encodeURIComponent(ref)+(dq?('&direct='+dq):'')):'');
|
||||||
{const dl=document.getElementById('dappJoinLink');if(dl&¤tSponsor.referralUrl){dl.href=currentSponsor.referralUrl;dl.classList.remove('hidden');}}
|
{const dl=document.getElementById('dappJoinLink');if(dl&¤tSponsor.referralUrl){dl.href=currentSponsor.referralUrl;dl.classList.remove('hidden');}}
|
||||||
// the company-queue line only means anything on the company-rotation path
|
// the company-queue line only means anything on the company-rotation path
|
||||||
// only on the company-rotation path — the invited path already wrote its own line here
|
// only on the company-rotation path — the invited path already wrote its own line here
|
||||||
|
|||||||
@@ -1793,7 +1793,14 @@ function serveMemberPage(req,res,file,kind,id){
|
|||||||
// to a stranger. The invite is the referral, so it has to outlive the one page it landed
|
// to a stranger. The invite is the referral, so it has to outlive the one page it landed
|
||||||
// on. 30 days, Lax so it survives a normal click-through from anywhere.
|
// on. 30 days, Lax so it survives a normal click-through from anywhere.
|
||||||
if(kind==='join'&&/^\d{1,15}$/.test(String(id))){
|
if(kind==='join'&&/^\d{1,15}$/.test(String(id))){
|
||||||
head['Set-Cookie']='rmc_ref='+id+'; Path=/; Max-Age=2592000; SameSite=Lax'+(IS_PROD?'; Secure':'');
|
const attrs='; Path=/; Max-Age=2592000; SameSite=Lax'+(IS_PROD?'; Secure':'');
|
||||||
|
const ck=['rmc_ref='+id+attrs];
|
||||||
|
// ?direct=1/0 is the inviter's explicit choice about placement, so it has to travel with
|
||||||
|
// the referral. Without it a prospect who wandered off the invite page would come back
|
||||||
|
// through the moving link instead — the opposite of what the shared link asked for.
|
||||||
|
const dq=new URL(req.url,'http://x').searchParams.get('direct');
|
||||||
|
if(dq==='1'||dq==='0')ck.push('rmc_direct='+dq+attrs);
|
||||||
|
head['Set-Cookie']=ck;
|
||||||
}
|
}
|
||||||
res.writeHead(200,securityHeaders(head));
|
res.writeHead(200,securityHeaders(head));
|
||||||
res.end(html);
|
res.end(html);
|
||||||
|
|||||||
Reference in New Issue
Block a user