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:
+52
-3
@@ -372,7 +372,7 @@
|
||||
});
|
||||
$('cType').addEventListener('change', () => {
|
||||
const t = $('cType').value;
|
||||
$('cImageRow').hidden = t === 'text' || t === 'solo';
|
||||
$('cImageRow').hidden = t !== 'banner'; // only banners carry a creative; login frames its URL
|
||||
$('cTitleRow').hidden = t !== 'text' && t !== 'solo';
|
||||
$('cBodyRow').hidden = t !== 'text';
|
||||
$('cSoloRow').hidden = t !== 'solo';
|
||||
@@ -644,6 +644,7 @@
|
||||
$('mcVerifyBtn').addEventListener('click', busy($('mcVerifyBtn'), async () => {
|
||||
await api('/api/auth/email/verify', { email: $('mcEmail').value, code: $('mcCode').value });
|
||||
IAP.status('You are in.', 'ok');
|
||||
await showLoginAd();
|
||||
await render();
|
||||
}));
|
||||
})();
|
||||
@@ -656,6 +657,7 @@
|
||||
$('loginBtn').addEventListener('click', busy($('loginBtn'), async () => {
|
||||
await api('/api/login', { email: $('liEmail').value, password: $('liPass').value });
|
||||
IAP.status('Logged in.', 'ok');
|
||||
await showLoginAd();
|
||||
await render();
|
||||
}));
|
||||
$('walletSigninLink').addEventListener('click', async e => {
|
||||
@@ -664,6 +666,7 @@
|
||||
IAP.status('Check your wallet for the free sign-in signature…');
|
||||
await IAPWallet.signIn();
|
||||
IAP.status('Signed in with your wallet.', 'ok');
|
||||
await showLoginAd();
|
||||
await render();
|
||||
} catch (err) { IAP.status((err && err.message) || String(err), 'bad'); }
|
||||
});
|
||||
@@ -692,9 +695,55 @@
|
||||
await render();
|
||||
});
|
||||
|
||||
// ad surfaces: login ads greet the sign-in screen; members see live
|
||||
// ── login ad interstitial (ClickBaitPays pattern): after a successful
|
||||
// sign-in the sponsor card appears; "Open Ad" opens the CTA link in a NEW
|
||||
// tab (a real, counted click) while the timer counts down on THIS page —
|
||||
// deliberately not paused, the member is expected to be in the ad tab.
|
||||
// At zero, "Go to dashboard" appears.
|
||||
async function showLoginAd() {
|
||||
try {
|
||||
const { ad } = await (await fetch('/api/ads/slot?type=login')).json();
|
||||
if (!ad || !ad.targetUrl) return;
|
||||
const gate = $('loginGate');
|
||||
const openBtn = $('lgOpen');
|
||||
const goBtn = $('lgContinue');
|
||||
const timer = $('lgTimer');
|
||||
$('lgCreative').innerHTML = ad.imageUrl
|
||||
? '<img src="' + ad.imageUrl + '" alt="sponsor ad">'
|
||||
: '<span class="lg-linkcard">' + (ad.title ? String(ad.title).replace(/[&<>]/g, '') : 'Visit today\'s sponsor') + '</span>';
|
||||
$('lgStatus').textContent = 'Login ad sponsor — click "Open Ad" to begin.';
|
||||
timer.hidden = true;
|
||||
goBtn.hidden = true;
|
||||
openBtn.disabled = false;
|
||||
gate.hidden = false;
|
||||
await new Promise(done => {
|
||||
openBtn.onclick = () => {
|
||||
window.open(ad.targetUrl, '_blank'); // the click relay counts it
|
||||
openBtn.disabled = true;
|
||||
$('lgStatus').textContent = 'Ad open in a new tab. View it and come back — the timer runs here.';
|
||||
let left = ad.dwell || 10;
|
||||
timer.hidden = false;
|
||||
timer.textContent = 'Time remaining: ' + left + 's';
|
||||
const t = setInterval(() => {
|
||||
left -= 1;
|
||||
if (left > 0) { timer.textContent = 'Time remaining: ' + left + 's'; return; }
|
||||
clearInterval(t);
|
||||
timer.textContent = 'Time is up';
|
||||
timer.classList.add('done');
|
||||
$('lgStatus').textContent = 'Thanks for the look. Your dashboard is ready.';
|
||||
goBtn.hidden = false;
|
||||
}, 1000);
|
||||
goBtn.onclick = () => done();
|
||||
};
|
||||
});
|
||||
gate.hidden = true;
|
||||
$('lgTimer').classList.remove('done');
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
// ad surfaces: a banner greets the sign-in screen; members see live
|
||||
// banner + text placements inside the back office (they ARE the audience)
|
||||
IAP.adSlot('login', 'adSlotLogin');
|
||||
IAP.adSlot('banner', 'adSlotLogin');
|
||||
IAP.adSlot('banner', 'adSlotOverview');
|
||||
IAP.adSlot('text', 'adSlotSide');
|
||||
|
||||
|
||||
Reference in New Issue
Block a user