Viral links: any public page + ?ref=<username|code|id> sets the same last-touch sponsor cookie as /join, counts under a 'page' hook in link stats, then redirects to the clean URL; Promo tools > Viral links builder (pages list + paste any address, copy + share); blog posts show a signed-in member's own link; chatbot answer; QA walk proves redirect + cookie

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
martbost
2026-09-21 05:54:55 -05:00
parent 337d5dd556
commit e2f88dad42
8 changed files with 113 additions and 5 deletions
+29 -1
View File
@@ -1076,6 +1076,28 @@ const server = http.createServer(async (req, res) => {
// -- traffic log: public page views by referring domain (admin > Traffic)
if (req.method === 'GET' && (TRAFFIC_PAGES.has(p) || /^\/(join|from|wall|blog)\/[^/]+$/.test(p))) traffic.hit(p.startsWith('/blog/') ? '/blog/*' : p, req.headers.referer, req.headers['user-agent']);
// -- viral links (Marty, 2026-09-21): ANY public page + ?ref=<username|code|id> is that member's
// referral link. Same 30-day last-touch sponsor cookie as /join, the view counts under the
// "page" hook in link stats, then a redirect to the clean URL so canonical links stay clean
// for search engines. /join, /from and the APIs keep their own meaning of ?ref.
if ((req.method === 'GET' || req.method === 'HEAD') && u.searchParams.has('ref') && !p.startsWith('/api/') && !p.startsWith('/admin') && !/^\/(join|from)\//.test(p) && !/\.[a-z0-9]{2,5}$/i.test(p)) {
const raw = String(u.searchParams.get('ref') || '').trim().toLowerCase().slice(0, 40);
const tok = JOIN_ALIASES[raw] || raw;
u.searchParams.delete('ref');
const clean = p + (u.searchParams.toString() ? '?' + u.searchParams.toString() : '');
let known = false;
if (/^[a-z0-9_]{1,20}$/.test(tok)) { try { known = !!((await accounts.byCode(tok)) || (await accounts.byUsername(tok)) || (/^\d+$/.test(tok) && (await accounts.byMemberId(Number(tok))))); } catch (e) {} }
const set = [];
if (known) {
const cookieTail = `; Path=/; SameSite=Lax; Max-Age=${30 * 24 * 3600}${IS_PROD ? '; Secure' : ''}`;
set.push('iap.sponsor=' + tok + cookieTail); // last touch wins, exactly like /join
set.push('iap.angle=page' + cookieTail); // the join shows under the "any page" hook
if (!parseCookies(req)['iap.ref']) set.push('iap.ref=' + encodeURIComponent(coach.refHost(req.headers.referer)) + cookieTail); // first-touch source
if (req.method === 'GET') coach.recordView(tok, 'page', req.headers.referer);
}
res.writeHead(302, baseHeaders(Object.assign({ Location: clean, 'Cache-Control': 'no-store' }, set.length ? { 'Set-Cookie': set } : {})));
return res.end();
}
// -- join links: /join/<memberId or share code> — LAST-touch cookie (Marty,
// 2026-09-10): the link a visitor opened most recently is the sponsor shown
// and used, and it locks the moment the account is created (accounts.ensure
@@ -1129,6 +1151,12 @@ const server = http.createServer(async (req, res) => {
// -- public API
if (p === '/api/friday' && req.method === 'GET') return json(res, 200, friday.view(), { 'Cache-Control': 'public, max-age=60' });
// -- the pages a member can turn into a viral link (promo tools > Viral links)
if (p === '/api/pages' && req.method === 'GET') {
const pages = [{ path: '/', title: 'Home page' }, { path: '/blog', title: 'Blog' }, { path: '/earning', title: 'How earning works' }, { path: '/ledger', title: 'Live ledger' }, { path: '/leaderboard', title: 'Leaderboard' }, { path: '/contract', title: 'The contract' }, { path: '/plays', title: 'Team-building plays' }, { path: '/wallets', title: 'Wallet guide' }, { path: '/whats-new', title: "What's new" }, { path: '/shorts', title: 'Shorts' }];
try { for (const b of (await blog.listPublished()).slice(0, 40)) pages.push({ path: '/blog/' + b.slug, title: 'Article: ' + b.title, cover: b.cover || null }); } catch (e) {}
return json(res, 200, { pages });
}
if (p === '/api/config' && req.method === 'GET') {
const c = chain.getConfig();
// public copy of the site settings: never anything that looks like a credential
@@ -3144,7 +3172,7 @@ const server = http.createServer(async (req, res) => {
+ '<style>.bp{max-width:560px;text-align:center;padding:40px 16px 60px}.bp img{width:100%;max-width:520px;border-radius:18px;border:1px solid var(--line);box-shadow:0 20px 60px rgba(0,0,0,.45)}.bp h1{font-size:clamp(24px,5vw,34px);margin:22px 0 8px}.bp p{color:var(--muted);max-width:44ch;margin:0 auto 20px}</style></head>'
+ '<body><div class="wrap bp"><img src="' + img + '" alt="' + esc(label) + ' badge for @' + esc(un) + '"><h1>@' + esc(un) + ' unlocked <em>' + label + '</em></h1><p>' + esc(sub.charAt(0).toUpperCase() + sub.slice(1)) + '. On InstantAdPay every ad package that sells pays the sponsor in the same transaction, straight to their wallet, on-chain.</p>'
+ '<a class="btn" href="/join/' + esc(un) + '">Join @' + esc(un) + '\u2019s line free</a><p class="small" style="margin-top:26px">Advertising with a performance referral program. Not an investment; no income is guaranteed.</p></div>'
+ '<script src="/assets/common.js?v=20260913a"></script><script src="/assets/blog-page.js?v=20260912a"></script></body></html>';
+ '<script src="/assets/common.js?v=20260913a"></script><script src="/assets/blog-page.js?v=20260921a"></script></body></html>';
res.writeHead(200, baseHeaders({ 'Content-Type': 'text/html; charset=utf-8', 'Cache-Control': 'public, max-age=300' }));
return res.end(html);
}