Stop the invite being lost when a prospect clicks through the nav
Terry hit this: he shares /join/840, his prospect taps "Training" in the nav, and by the time they reach /start the site has forgotten him and offers the COMPANY rotation position — #148. His referral, handed to a stranger, because the prospect read the training first. The invite now outlives the page it landed on: - Serving /join/<id> sets an rmc_ref cookie (30 days, Lax). - /start reads it (or an explicit ?ref=) and shows the INVITER instead of the company rotation, routed by exactly the same rules the inviter's own page uses — direct placement if their position is set that way, else the next open spot in their leg. The two pages can no longer disagree. - The Join button carries ?ref through to /join-now, which already knew how to place a ref correctly but was never being given one from here. - /join-now also falls back to the cookie when it arrives with no ?ref. The page now says whose team it is ("Invited by Member #840") rather than an anonymous "current placement", and when the inviter is already qualified it says plainly that the entry fills the next open spot in their team. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -55,6 +55,10 @@ fetch('/api/public/config').then(function(r){return r.json()}).then(function(c){
|
||||
// personal invite: ?ref=<id> -> place in that member's leg via the site's moving-link joinTarget
|
||||
var qp=new URLSearchParams(location.search);
|
||||
var ref=qp.get('ref');
|
||||
// No ?ref on the URL? Fall back to the invite cookie set when this visitor landed on
|
||||
// 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.
|
||||
if(!ref){ try{ var ck=document.cookie.match(/(?:^|;\s*)rmc_ref=(\d{1,15})/); if(ck)ref=ck[1]; }catch(e){} }
|
||||
// Direct link (?direct=1): opt out of rotation — register straight under
|
||||
// the inviter (spillover in their team), never the next-to-qualify member.
|
||||
if(ref&&/^\d{1,15}$/.test(ref)&&qp.get('direct')==='1'){
|
||||
|
||||
+49
-4
@@ -1,10 +1,49 @@
|
||||
let currentSponsor=null;
|
||||
// Who invited this visitor, if anyone. A prospect who arrived on /join/<id> and then tapped
|
||||
// a nav link used to land here and be offered the COMPANY rotation position instead — the
|
||||
// inviter lost the referral just because the prospect clicked "Training" first. The invite
|
||||
// is remembered in the rmc_ref cookie (set when the invite page was served) and can also be
|
||||
// passed explicitly as ?ref=<id>.
|
||||
function invitedBy(){
|
||||
try{
|
||||
const q=new URLSearchParams(location.search).get('ref');
|
||||
if(q&&/^\d{1,15}$/.test(q))return q;
|
||||
const m=document.cookie.match(/(?:^|;\s*)rmc_ref=(\d{1,15})/);
|
||||
if(m)return m[1];
|
||||
}catch(e){}
|
||||
return null;
|
||||
}
|
||||
async function load(){
|
||||
try{
|
||||
const [cr,sr]=await Promise.all([fetch('/api/public/config'),fetch('/api/public/current-sponsor')]);
|
||||
const ref=invitedBy();
|
||||
const [cr,sr]=await Promise.all([
|
||||
fetch('/api/public/config'),
|
||||
fetch(ref?('/api/public/member?id='+encodeURIComponent(ref)):'/api/public/current-sponsor')
|
||||
]);
|
||||
const c=await cr.json(); const s=await sr.json();
|
||||
if(!sr.ok)throw new Error(s.error||'No sponsor assigned');
|
||||
currentSponsor=s.sponsor;
|
||||
if(ref&&s.registered){
|
||||
// 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
|
||||
// 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;
|
||||
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"
|
||||
const badge=document.querySelector('.live-badge');
|
||||
if(badge){
|
||||
const dot=badge.querySelector('.dot');
|
||||
badge.textContent=' '+(String(t.id)===String(ref)?('Invited by Member #'+ref):('Member #'+ref+"'s team"));
|
||||
if(dot)badge.insertBefore(dot,badge.firstChild);
|
||||
}
|
||||
const jb=document.getElementById('joinButton');
|
||||
if(jb)jb.textContent=(String(t.id)===String(ref)?('Join Member #'+ref+"'s Team →"):('Join '+'#'+ref+"'s Team →"));
|
||||
const note=document.getElementById('queueText');
|
||||
if(note&&String(t.id)!==String(ref)){
|
||||
note.textContent='Member #'+ref+' is already qualified, so your entry fills the next open spot in their team (#'+t.id+').';
|
||||
}
|
||||
}else{
|
||||
currentSponsor=s.sponsor;
|
||||
}
|
||||
if(c.siteName){document.title=`Get Started | ${c.siteName}`;const bn=document.getElementById('brandName');if(bn)bn.textContent=c.siteName}
|
||||
document.getElementById('sponsorId').textContent=`ID ${currentSponsor.id}`;
|
||||
document.getElementById('sponsorIdInline').textContent=currentSponsor.id;
|
||||
@@ -17,9 +56,15 @@ async function load(){
|
||||
var usd=Math.round(c.premiumEntryPol*c.polUsd);
|
||||
['entryUsd','entryUsd2'].forEach(function(id){var el=document.getElementById(id);if(el)el.textContent=' (~$'+usd+' today — POL’s price moves)';});
|
||||
}
|
||||
document.getElementById('joinButton').href='/join-now';
|
||||
// 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
|
||||
// button dropped the referral on the floor and enrolled under the company rotation.
|
||||
document.getElementById('joinButton').href='/join-now'+(ref?('?ref='+encodeURIComponent(ref)):'');
|
||||
{const dl=document.getElementById('dappJoinLink');if(dl&¤tSponsor.referralUrl){dl.href=currentSponsor.referralUrl;dl.classList.remove('hidden');}}
|
||||
document.getElementById('queueText').textContent=c.showQueueProgress?`${s.waitingCount} team placement${s.waitingCount===1?'':'s'} waiting behind the current sponsor.`:'';
|
||||
// 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
|
||||
if(!ref)document.getElementById('queueText').textContent=(c.showQueueProgress&&s.waitingCount!==undefined)
|
||||
?`${s.waitingCount} team placement${s.waitingCount===1?'':'s'} waiting behind the current sponsor.`:'';
|
||||
document.getElementById('supportBox').textContent=c.supportLabel||'Contact your team sponsor if you need help before joining.';
|
||||
if(c.telegramUrl){const w=document.getElementById('supportLinkWrap'),a=document.getElementById('supportLink');a.href=c.telegramUrl;w.classList.remove('hidden')}
|
||||
}catch(e){
|
||||
|
||||
Reference in New Issue
Block a user