Login ads as post-signin interstitials: Open Ad in new tab, timer here, Go to Dashboard

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
martbost
2026-09-05 16:28:57 -05:00
parent 2cc2855488
commit 1c31679b6c
8 changed files with 106 additions and 16 deletions
+6 -2
View File
@@ -594,7 +594,11 @@ const server = http.createServer(async (req, res) => {
// -- ad engine (spec §8b v1: banners, text, login ads)
if (p === '/api/ads/slot' && req.method === 'GET') {
const ad = await ads.serve(String(u.searchParams.get('type') || 'banner'));
const t = String(u.searchParams.get('type') || 'banner');
const ad = await ads.serve(t);
// login ads: the member clicks "Open Ad" (a real, counted click into a
// new tab) while the countdown runs on our interstitial page
if (ad && t === 'login') ad.dwell = ads.rates().loginDwellSeconds || 10;
return json(res, 200, { ad });
}
m = /^\/api\/ads\/click\/(\d+)$/.exec(p);
@@ -619,7 +623,7 @@ const server = http.createServer(async (req, res) => {
if (!s || !s.email) return json(res, 401, { error: 'Sign in first.' });
const memberId = await auth.refreshMemberId(s); // 0 is fine: earned credits fund banner/text
const b = await readBody(req);
if (!['login', 'solo'].includes(String(b.type || ''))) { // surf views frame the target: catch frame-breakers at the door (login + solo are click-through only)
if (!['login', 'solo'].includes(String(b.type || ''))) { // banner/text surf views frame the target: catch frame-breakers at the door (login opens a new tab, solo links are click-through)
const fc = await frameCheck(b.targetUrl);
if (!fc.ok) return json(res, 400, { error: fc.reason });
}