Promo tools: drop the printable handouts section and /flyers page

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
martbost
2026-09-09 06:12:00 -05:00
parent f3f9662d99
commit f717acad97
8 changed files with 6 additions and 2465 deletions
+3 -3
View File
@@ -33,8 +33,8 @@ const CANNED = [
a: 'Join free with just your email at https://instantadpay.com/my, no wallet and no password needed. Your wallet only comes out when you buy a package or switch on payouts, and the site walks you through it.' },
{ re: /(referral link|invite link|share link|refer)/i,
a: 'You get your share link the moment you sign in, free members included. One tip: switch on payouts (one free wallet step in Members) before your people start buying, because the contract locks each buyer to their sponsor at their first purchase.' },
{ re: /(promo tools?|social posts?|email swipes?|banners?|handouts?|flyers?|text a friend|objection|share buttons?)/i,
a: 'Promo tools (Members > Promo tools) has pill menus for each kit: Social posts (X, Facebook, LinkedIn, Telegram or WhatsApp, with post and share buttons), Text a friend (SMS-sized messages with Text it, WhatsApp, Telegram and Copy), Email swipes (short, standard, long, follow-up), Banners (every standard ad size plus square, story and Telegram sizes, download or copy URL), printable Handouts with your QR code (Open your handouts), your Banner wall link, and an Objection handling bank with the truth plus a ready-to-send reply. Everything is personalized with your invite link.' },
{ re: /(promo tools?|social posts?|email swipes?|banners?|text a friend|objection|share buttons?)/i,
a: 'Promo tools (Members > Promo tools) has pill menus for each kit: Social posts (X, Facebook, LinkedIn, Telegram or WhatsApp, with post and share buttons), Text a friend (SMS-sized messages with Text it, WhatsApp, Telegram and Copy), Email swipes (short, standard, long, follow-up), Banners (every standard ad size plus square, story and Telegram sizes, download or copy URL), your Banner wall link, and an Objection handling bank with the truth plus a ready-to-send reply. Everything is personalized with your invite link.' },
{ re: /(solo ad|inbox ad|inbox)/i,
a: 'Solo ads are full-message ads delivered straight into member inboxes on-site. Compose one under Campaigns (pick "Solo ad"): subject line, a rich-text message with a real editor (bold, headings, lists, links), an attached image or video if you want one, and a call-to-action button with your own label. You pay 5 credits per guaranteed delivery, 10 deliveries minimum. On the reading side, your Inbox section collects solos from other members — give one a real read (10 seconds on the open message) and claim 2 credits, up to 5 rewarded reads a day. You never receive your own solo.' },
{ re: /(chat|message (my )?(sponsor|upline|team|downline)|talk to (my )?sponsor|contact (my )?sponsor|ask (my )?sponsor|reach (my )?sponsor)/i,
@@ -55,7 +55,7 @@ function systemPrompt() {
FACTS:
- Free to join with email only (6-digit code sign-in, no passwords). Wallet appears only at purchase or payout activation. Every new member gets a small welcome batch of ad credits — unlocked by the WELCOME TOUR on first sign-in: they visit their upline's line-banner sites (up to 3, 10 seconds each — the same 3 levels the contract pays), then claim the credits. Members with no upline banners get the credits instantly.
- PROMO TOOLS (Members > Promo tools, pill menu): Social posts for X/Facebook/LinkedIn/Telegram-WhatsApp with post/share buttons; Text a friend (5 SMS-sized messages with Text it / WhatsApp / Telegram / Copy); Email swipes (short, standard, long, follow-up); Banners in every standard ad size plus 1080x1080, 1080x1920 and 1280x720 (download or copy URL); printable half-sheet Handouts at /flyers with the member's own QR code and invite link (two per letter page with a cut line); the member's Banner wall link; an Objection handling bank (truth + ready-to-send reply); a Videos tab (hook videos in production). Every piece carries the member's invite link; angle links add ?v=instant|adspend|free|ledger. Members who want copy in their own voice can use mybrandedvoice.com.
- PROMO TOOLS (Members > Promo tools, pill menu): Social posts for X/Facebook/LinkedIn/Telegram-WhatsApp with post/share buttons; Text a friend (5 SMS-sized messages with Text it / WhatsApp / Telegram / Copy); Email swipes (short, standard, long, follow-up); Banners in every standard ad size plus 1080x1080, 1080x1920 and 1280x720 (download or copy URL); the member's Banner wall link; an Objection handling bank (truth + ready-to-send reply); a Videos tab (hook videos in production). Every piece carries the member's invite link; angle links add ?v=instant|adspend|free|ledger. Members who want copy in their own voice can use mybrandedvoice.com.
- LINE BANNER (free, set in Profile): every member can set a destination URL (must allow framing) plus an optional banner image. It is shown to their next THREE levels of new members during welcome tours (position 1 for directs, 2, 3 below), and on their public BANNER WALL at /wall/<username> — a shareable page showing their line ladder with their join link. Free viral traffic that compounds as the team grows; no credits spent.
- Ad packages: Micro $5/500 credits, Activation $20/2,000, Builder $50/5,500, Growth $100/12,000, Leader $250/32,500. Dollar-priced, settled in POL (Polygon) at the live Chainlink rate. 1 credit = 1 cent of ad delivery.
- Live formats: display banners (per impression), text ads (per impression), full-screen LOGIN ADS (per day: right after a member signs in they land on a sponsor interstitial — they click "Open Ad", the advertiser's page opens in a NEW tab, a countdown runs on the interstitial, and at zero a "Go to dashboard" button appears. Just a CTA link is enough; an optional banner image can be the clickable creative. No framing requirement since it opens in its own tab), WATCH-TO-EARN VIDEO ADS (advertiser uploads an MP4/WebM or gives a direct https .mp4/.webm link and picks a required watch length — 10s/30s/60s — which sets the per-view price; viewers watch in an escape-proof player under Earn credits > Watch videos, the watch time is enforced on the server clock, and they earn credits per completed watch; you never see your own videos), and solo ads. Banner ads also require a size (standard IAB sizes like 728x90, 300x250). Coming: featured rotation with disclosed rotation size, verified-visit packs.
-81
View File
@@ -1,81 +0,0 @@
// Printable half-sheet handouts with the member's QR + invite link.
// The ref token (username, share code or member #) comes from ?ref=, then
// localStorage (set by Promo tools), then the signed-in account.
(function () {
'use strict';
var $ = function (id) { return document.getElementById(id); };
var ORIGIN = location.origin;
var DESIGNS = [
{ angle: 'instant', tag: 'Polygon · same-transaction payouts', h: 'Advertise &amp; earn.<br>Paid on-chain, <em>instantly.</em>',
lead: 'Every ad package splits to real wallets the second it sells. No pending. No withdraw button.',
bullets: ['Free to join with just an email', 'Ad packages from $5, seven ad formats', 'Every payout public on the blockchain'] },
{ angle: 'adspend', tag: 'For marketers who buy traffic', h: 'You were buying <em>ads anyway.</em>',
lead: 'Here the ad spend in your line pays you, in the same transaction, on a public ledger.',
bullets: ['Banners, text, login, solo, video, featured, visits', 'Dwell-timed views: real people, not scripts', '50 / 20 / 10 sponsor split, written in code'] },
{ angle: 'free', tag: 'Costs nothing to try', h: 'Watch first.<br><em>Spend never.</em>',
lead: 'Join free, view a few ads, earn credits, and run your first campaign for zero dollars.',
bullets: ['Email sign-in, no password, no wallet needed', 'Earn credits for your attention every day', 'Upgrade only if you want more reach'] }
];
function getRef() {
var q = new URLSearchParams(location.search).get('ref');
if (q && /^[A-Za-z0-9_]{1,20}$/.test(q)) return q;
try { var s = localStorage.getItem('iap.ref'); if (s && /^[A-Za-z0-9_]{1,20}$/.test(s)) return s; } catch (e) {}
return '';
}
function qrSvg(url) {
try { var q = qrcode(0, 'M'); q.addData(url); q.make(); return q.createSvgTag({ cellSize: 4, margin: 2, scalable: true }); } catch (e) { return ''; }
}
function el(tag, cls, html) { var d = document.createElement(tag); if (cls) d.className = cls; if (html != null) d.innerHTML = html; return d; }
function card(d, url, shortUrl) {
var hs = el('div', 'hs');
hs.appendChild(el('div', 'lines'));
var inner = el('div', 'in');
var logo = el('img', 'logo'); logo.src = '/logo.png'; logo.alt = 'InstantAdPay'; inner.appendChild(logo);
inner.appendChild(el('span', 'tag', d.tag));
inner.appendChild(el('h2', null, d.h));
inner.appendChild(el('p', 'lead', d.lead));
var ul = el('ul'); d.bullets.forEach(function (b) { ul.appendChild(el('li', null, b)); }); inner.appendChild(ul);
inner.appendChild(el('div', 'foot', 'Scan the code or visit <b>' + shortUrl + '</b>'));
hs.appendChild(inner);
var ov = el('div', 'hs-qrov');
ov.appendChild(el('div', 'q', url ? qrSvg(url) : '<div class="qph"></div>'));
ov.appendChild(el('div', 'scan', 'SCAN ME'));
ov.appendChild(el('div', 'lnk', shortUrl));
hs.appendChild(ov);
hs.appendChild(el('div', 'hs-disc', 'Advertising, not investing. No income is guaranteed; results depend on your effort. Crypto carries risk of loss.'));
return hs;
}
function build(ref) {
var wrap = $('halfsheets'); wrap.innerHTML = '';
DESIGNS.forEach(function (d) {
var url = ref ? ORIGIN + '/join/' + ref + '?v=' + d.angle : '';
var shortUrl = ref ? 'instantadpay.com/join/' + ref : 'instantadpay.com';
var page = el('div', 'hs-page');
var pr = el('button', 'btn small hs-print', 'Print this one'); pr.type = 'button';
pr.addEventListener('click', function () {
document.body.classList.add('print-one'); page.classList.add('printing');
window.print();
setTimeout(function () { document.body.classList.remove('print-one'); page.classList.remove('printing'); }, 400);
});
page.appendChild(pr);
page.appendChild(card(d, url, shortUrl));
page.appendChild(el('div', 'hs-cut', '✂ cut here'));
var copy = card(d, url, shortUrl); copy.classList.add('hs-copy'); page.appendChild(copy);
wrap.appendChild(page);
});
}
var input = $('flRef');
var ref = getRef();
if (ref) input.value = ref;
build(ref);
input.addEventListener('input', function () {
var v = input.value.trim();
if (!v || /^[A-Za-z0-9_]{1,20}$/.test(v)) { build(v); try { if (v) localStorage.setItem('iap.ref', v); } catch (e) {} }
});
if (!ref) { // signed-in member without a stored ref: ask the site
fetch('/api/me').then(function (r) { return r.json(); }).then(function (me) {
var t = me && me.signedIn && (me.username || me.refCode || me.memberId);
if (t && !input.value) { input.value = String(t); build(String(t)); }
}).catch(function () {});
}
})();
+1 -1
View File
@@ -1013,7 +1013,7 @@
b.addEventListener('click', () => setEarnSub(b.dataset.earn)));
// promo tools: pill menu switches between posts / swipes / banners / wall / videos
function setPromoSub(name) {
const ids = ['posts', 'text', 'swipe', 'banners', 'flyers', 'wall', 'objections', 'videos'];
const ids = ['posts', 'text', 'swipe', 'banners', 'wall', 'objections', 'videos'];
if (!ids.includes(name)) name = 'posts';
ids.forEach(id => { const el = $('promo-' + id); if (el) el.hidden = id !== name; });
document.querySelectorAll('.promo-pills [data-promo]').forEach(b => {
-3
View File
@@ -143,9 +143,6 @@ window.IAPPromo = (function () {
d.appendChild(body); ob.appendChild(d);
}
}
// handouts link
if ($('flyersOpen')) $('flyersOpen').href = '/flyers' + (token ? '?ref=' + encodeURIComponent(token) : '');
try { if (token) localStorage.setItem('iap.ref', String(token)); } catch (e) {}
}
return { fill, POSTS, TEXTS, SWIPES, OBJECTIONS };
File diff suppressed because it is too large Load Diff
-70
View File
@@ -1,70 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="robots" content="noindex">
<title>Printable handouts | InstantAdPay</title>
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Sora:wght@600;700;800&display=swap">
<link rel="icon" type="image/png" href="/logo-icon.png">
<link rel="stylesheet" href="/assets/site.css?v=20260909a">
<style>
.flw{max-width:760px;margin:0 auto;padding:26px 16px 70px}
.fl-id{display:flex;gap:10px;flex-wrap:wrap;align-items:center;margin:14px 0 18px}
.fl-id input{max-width:220px}
.hs-page{margin:0 auto 26px;max-width:680px}
.hs{position:relative;aspect-ratio:8.5/5.5;border-radius:14px;overflow:hidden;box-shadow:0 10px 30px rgba(0,0,0,.45);
background:radial-gradient(120% 90% at 8% 0%,#16352c 0%,#0b1512 58%,#07100d 100%);color:#eef7f3;
font-family:var(--disp);-webkit-print-color-adjust:exact;print-color-adjust:exact;container-type:inline-size}
.hs .lines{position:absolute;inset:0;background:repeating-linear-gradient(0deg,rgba(67,232,195,.07) 0 1px,transparent 1px 5.2%)}
.hs .in{position:absolute;inset:0;padding:5% 6% 10.5%;display:flex;flex-direction:column;gap:1.8%}
.hs img.logo{width:30%;height:auto;display:block}
.hs .tag{display:inline-block;width:max-content;border:1px solid rgba(67,232,195,.5);color:#43e8c3;border-radius:999px;padding:.6% 2.4%;font-size:2.2cqw;font-weight:700;letter-spacing:.08em;text-transform:uppercase}
.hs h2{font-size:5.2cqw;line-height:1.05;margin:0;letter-spacing:-.02em;max-width:66%;text-wrap:balance}
.hs h2 em{font-style:normal;color:#43e8c3}
.hs p.lead{font-size:2.2cqw;line-height:1.35;margin:0;color:#b7cdc4;max-width:64%}
.hs ul{margin:0;padding:0;list-style:none;display:flex;flex-direction:column;gap:.6%;font-size:2.15cqw;max-width:64%;color:#eef7f3}
.hs ul li::before{content:"✓ ";color:#43e8c3;font-weight:800}
.hs .foot{display:none}
.hs .foot b{color:#43e8c3}
.hs-qrov{position:absolute;right:4%;top:50%;transform:translateY(-50%);width:24%;background:#fff;border-radius:6%/9%;
padding:2.4% 2% 1.8%;text-align:center;color:#0b1512;box-shadow:0 6px 20px rgba(0,0,0,.55)}
.hs-qrov .q{width:100%;line-height:0}
.hs-qrov .q svg{width:100%;height:auto;display:block}
.hs-qrov .q .qph{width:100%;aspect-ratio:1;border:2px dashed #99a;border-radius:6px;box-sizing:border-box}
.hs-qrov .scan{font-weight:800;letter-spacing:.12em;font-size:1.9cqw;margin-top:5%}
.hs-qrov .lnk{font-weight:700;font-size:1.6cqw;overflow-wrap:anywhere;line-height:1.2;color:#1c7c65}
.hs-disc{position:absolute;left:6%;bottom:2.4%;width:60%;font-size:1.45cqw;line-height:1.3;color:#8ba69c}
.hs-print{position:absolute;top:10px;right:10px;z-index:10}
.hs-copy,.hs-cut{display:none}
@media print{
@page{size:letter;margin:0}
body{background:#fff!important}
.fl-top,.fl-id,.fl-intro,.hs-print,#status{display:none!important}
.flw{max-width:none;padding:0;margin:0}
.hs-page{max-width:none;margin:0;height:11in;page-break-after:always;page-break-inside:avoid;display:flex;flex-direction:column}
.hs-page .hs{border-radius:0;box-shadow:none;flex:1;aspect-ratio:auto;display:flex}
.hs-copy{display:flex}
.hs-cut{display:flex;justify-content:center;align-items:center;gap:8px;border-top:2.5px dashed #98a2ad;font-size:10px;color:#667;padding:2px 0;background:#fff}
body.print-one .hs-page:not(.printing){display:none!important}
#halfsheets .hs-page:last-child{page-break-after:auto}
body.print-one .hs-page.printing{page-break-after:auto!important}
}
</style>
</head>
<body>
<main class="flw">
<div class="fl-top" style="display:flex;justify-content:space-between;align-items:center;gap:12px;flex-wrap:wrap">
<a href="/"><img src="/logo.png" alt="InstantAdPay" style="height:34px;display:block"></a>
<a class="btn small sec" href="/my#promo">← Back to Promo tools</a>
</div>
<p class="eyebrow" style="margin-top:22px">For members · belly-to-belly</p>
<h1 style="font-size:clamp(28px,5vw,40px);margin:6px 0 8px">Printable <em>handouts</em></h1>
<p class="fl-intro muted">Three half-sheet designs, two per letter page with a cut line. Each one carries your personal QR code and invite link, so a scan lands the prospect in your line. Print in color; the QR scans in black and white too.</p>
<div class="fl-id"><label style="font-weight:700">Your username or member #:</label><input id="flRef" placeholder="e.g. martbost" autocomplete="off"><span class="small muted">Opened from Promo tools? It is filled in for you.</span></div>
<div id="halfsheets"></div>
</main>
<script src="/assets/common.js?v=20260909a"></script>
<script src="/assets/qrlib.js"></script>
<script src="/assets/flyers.js?v=20260909a"></script>
</body>
</html>
+2 -9
View File
@@ -543,7 +543,6 @@
<button class="chip-t" data-promo="text" type="button" role="tab">Text a friend</button>
<button class="chip-t" data-promo="swipe" type="button" role="tab">Email swipes</button>
<button class="chip-t" data-promo="banners" type="button" role="tab">Banners</button>
<button class="chip-t" data-promo="flyers" type="button" role="tab">Handouts</button>
<button class="chip-t" data-promo="wall" type="button" role="tab">Banner wall</button>
<button class="chip-t" data-promo="objections" type="button" role="tab">Objections</button>
<button class="chip-t" data-promo="videos" type="button" role="tab">Videos</button>
@@ -577,12 +576,6 @@
group sizes. Pair one with your invite link. Download, or copy the image URL for ad networks.</p>
<div id="promoBanners" class="promo-banners"></div>
</div>
<div class="card promo-sec" id="promo-flyers" hidden>
<h3>Printable handouts</h3>
<p class="muted small">Old-school still works. Three half-sheet designs, two per letter page with a cut line,
each with <b>your</b> QR code and invite link baked in. Coffee shops, gyms, community boards, laundromats.</p>
<p><a class="btn small" id="flyersOpen" href="/flyers" target="_blank" rel="noopener">Open your handouts</a></p>
</div>
<div class="card promo-sec" id="promo-wall" hidden>
<h3>Your banner wall</h3>
<p class="muted small">A public page showing your line banner and your upline ladder, with your
@@ -743,8 +736,8 @@
</div>
<script src="/assets/common.js?v=20260909a"></script>
<script src="/assets/wallet.js?v=20260908t"></script>
<script src="/assets/promo.js?v=20260909a"></script>
<script src="/assets/my.js?v=20260909d"></script>
<script src="/assets/promo.js?v=20260909b"></script>
<script src="/assets/my.js?v=20260909e"></script>
<script src="/assets/chat.js?v=20260907l"></script>
</body>
</html>
-1
View File
@@ -1485,7 +1485,6 @@ const server = http.createServer(async (req, res) => {
if (p === '/my') return sendFile(res, path.join(PUBLIC_DIR, 'my.html'));
if (p === '/admin') return sendFile(res, path.join(PUBLIC_DIR, 'admin.html'));
if (p === '/shorts') return sendFile(res, path.join(PUBLIC_DIR, 'shorts.html'));
if (p === '/flyers') return sendFile(res, path.join(PUBLIC_DIR, 'flyers.html'));
if (/^\/view\/[a-f0-9]{32}$/.test(p)) return sendFile(res, path.join(PUBLIC_DIR, 'view.html'));
m = /^\/uploads\/([a-z0-9]{24}\.(?:png|jpg|webp|gif|mp4|webm))$/.exec(p);
if (m) return sendFile(res, path.join(UPLOADS_DIR, m[1]));