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:
martbost
2026-09-18 11:18:23 -05:00
parent 25b3636352
commit 2b36a29a68
3 changed files with 63 additions and 5 deletions
+4
View File
@@ -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
View File
@@ -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&&currentSponsor.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){