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
+17
View File
@@ -1,2 +1,19 @@
// public blog pages: the shared nav (with wallet status) and footer, nothing else
(function () { try { IAP.renderNav(location.pathname.indexOf('/leaderboard') === 0 ? 'leaderboard' : 'blog'); } catch (e) {} })();
// Viral links (2026-09-21): a signed-in member sees this article's address with their own ?ref= on the
// end, and the share buttons carry it too. Whoever opens it is tagged to them like an invite link.
(async function () {
try {
const share = document.querySelector('p.share'); if (!share) return;
const me = await (await fetch('/api/me')).json();
const tok = me && me.signedIn && (me.username || me.refCode); if (!tok) return;
const link = 'https://instantadpay.com' + location.pathname + '?ref=' + encodeURIComponent(tok);
share.querySelectorAll('a').forEach(a => { a.href = a.href.replace(encodeURIComponent('https://instantadpay.com' + location.pathname), encodeURIComponent(link)); });
const bar = document.createElement('div');
bar.id = 'viralBar';
bar.style.cssText = 'margin-top:18px;padding:12px 14px;border:1px solid var(--line);border-radius:12px;background:var(--card, rgba(255,255,255,.03));display:flex;gap:10px;align-items:center;flex-wrap:wrap';
bar.innerHTML = '<div style="flex:1;min-width:220px"><div class="eyebrow" style="margin:0 0 4px">Your link for this article</div><div class="mono small" style="overflow-wrap:anywhere">' + link.replace(/[&<>]/g, '') + '</div><div class="muted small" style="margin-top:4px">Share this and anyone who joins from it is yours, same as your invite link.</div></div><button class="btn small" type="button">Copy link</button>';
bar.querySelector('button').onclick = async () => { try { await navigator.clipboard.writeText(link); IAP.status('Link copied.', 'ok'); } catch (e) { IAP.status('Copy failed.', 'bad'); } };
share.parentNode.insertBefore(bar, share);
} catch (e) {}
})();
+2 -2
View File
@@ -1523,7 +1523,7 @@
const rows = (r.angles || []).filter(a => a.views || a.joins || a.buyers);
if (!rows.length) { t.innerHTML = '<tr><td class="muted small">No views yet. Share your link and the numbers start here.</td></tr>'; return; }
t.innerHTML = '<tr><th>Hook</th><th>Views (30d)</th><th>Views (all)</th><th>Joined</th><th>Qualifying buyers</th></tr>'
+ rows.map(a => '<tr><td>' + esc(a.angle === 'plain' ? 'plain link' : '?v=' + a.angle) + '</td><td class="mono">' + a.views30 + '</td><td class="mono">' + a.views + '</td><td class="mono">' + a.joins + '</td><td class="mono">' + a.buyers + '</td></tr>').join('');
+ rows.map(a => '<tr><td>' + esc(a.angle === 'plain' ? 'plain link' : a.angle === 'page' ? 'any page (viral link)' : '?v=' + a.angle) + '</td><td class="mono">' + a.views30 + '</td><td class="mono">' + a.views + '</td><td class="mono">' + a.joins + '</td><td class="mono">' + a.buyers + '</td></tr>').join('');
const st = $('linkSrcTable');
if (st) {
const src = (r.sources || []).filter(x => x.views || x.joins);
@@ -1887,7 +1887,7 @@
if ($('tkGo')) { $('tkGo').addEventListener('click', tkGenerate); $('tkAgain').addEventListener('click', tkGenerate); $('tkCopy').addEventListener('click', async () => { try { await navigator.clipboard.writeText($('tkText').value); IAP.status('Copied.', 'ok'); } catch (e) { $('tkText').select(); } }); $('tkSendBc').addEventListener('click', tkSendBroadcast); }
// promo tools: pill menu switches between posts / swipes / banners / wall / videos
function setPromoSub(name) {
const ids = ['toolkit', 'posts', 'text', 'swipe', 'banners', 'wall', 'objections', 'videos'];
const ids = ['toolkit', 'posts', 'text', 'swipe', 'banners', 'wall', 'objections', 'videos', 'viral'];
if (name === 'toolkit') loadToolkit();
if (!ids.includes(name)) name = 'posts';
ids.forEach(id => { const el = $('promo-' + id); if (el) el.hidden = id !== name; });
+33
View File
@@ -198,6 +198,39 @@ window.IAPPromo = (function () {
vw.appendChild(card);
}
}
// viral link builder: any page on the site + ?ref=<you> (same cookie as the invite link)
const vp = $('viralPage');
if (vp && token && vp.dataset.filled !== token) {
vp.dataset.filled = token;
const origin = 'https://instantadpay.com', enc = encodeURIComponent;
const build = raw => {
let s = String(raw || '').trim(); if (!s) return '';
if (!/^https?:\/\//i.test(s)) s = origin + (s.charAt(0) === '/' ? '' : '/') + s;
let x; try { x = new URL(s); } catch (e) { return ''; }
if (!/(^|\.)instantadpay\.com$/i.test(x.hostname) || /^\/(join|from|api|admin)(\/|$)/.test(x.pathname)) return '';
x.searchParams.delete('ref'); x.searchParams.set('ref', token);
return origin + x.pathname + x.search;
};
const render = () => {
const typed = $('viralUrl').value.trim();
const l = build(typed || vp.value);
$('viralLink').textContent = l || (typed ? 'That is not a page on instantadpay.com.' : '…');
const sh = $('viralShare'); sh.innerHTML = '';
if (!l) return;
const title = (!typed && vp.selectedOptions[0]) ? vp.selectedOptions[0].textContent.replace(/^Article: /, '') : 'InstantAdPay';
[linkBtn('https://x.com/intent/tweet?url=' + enc(l) + '&text=' + enc(title), 'X'),
linkBtn('https://www.facebook.com/sharer/sharer.php?u=' + enc(l), 'Facebook'),
linkBtn('https://t.me/share/url?url=' + enc(l) + '&text=' + enc(title), 'Telegram'),
linkBtn('https://wa.me/?text=' + enc(title + ' ' + l), 'WhatsApp'),
linkBtn('https://www.linkedin.com/sharing/share-offsite/?url=' + enc(l), 'LinkedIn'),
linkBtn('mailto:?subject=' + enc(title) + '&body=' + enc(l), 'Email')].forEach(b => sh.appendChild(b));
if (navigator.share) { const b = document.createElement('button'); b.className = 'btn small sec'; b.type = 'button'; b.textContent = 'Share'; b.onclick = async () => { try { await navigator.share({ title, url: l }); } catch (e) {} }; sh.appendChild(b); }
};
fetch('/api/pages').then(r => r.json()).then(r => { vp.innerHTML = (r.pages || []).map(pg => '<option value="' + esc(pg.path) + '">' + esc(pg.title) + '</option>').join(''); render(); }).catch(() => { vp.innerHTML = '<option value="/">Home page</option>'; render(); });
vp.onchange = () => { $('viralUrl').value = ''; render(); };
$('viralUrl').oninput = render;
$('viralCopy').onclick = async () => { const l = $('viralLink').textContent; if (!/^https:/.test(l)) return; try { await navigator.clipboard.writeText(l); status('Link copied.', 'ok'); } catch (e) { status('Copy failed.', 'bad'); } };
}
// objections
const ob = $('promoObjections');
if (ob && ob.dataset.filled !== link) {