loader image
ADS

${t.desc}

${t.sub}

${t.loadingTitle}

${t.loadingDesc}

`; document.body.appendChild(overlay); const btn = document.getElementById('offerwall-btn'); const safeStart = () => { const now = Date.now(); if (now - lastClickTs < CLICK_COOLDOWN_MS) return; lastClickTs = now; if (flowActive) return; showRewardedAd(btn); }; // mobile first btn.addEventListener('pointerup', safeStart, { passive: true }); btn.addEventListener('touchend', safeStart, { passive: true }); // fallback desktop btn.addEventListener('click', safeStart); } function removeOverlay() { const overlay = document.getElementById('offerwall-overlay'); if (overlay) overlay.remove(); document.body.classList.remove('offerwall-locked'); } function setLoadingState(isLoading) { const loading = document.getElementById('offerwall-loading'); const btn = document.getElementById('offerwall-btn'); if (btn) btn.style.display = isLoading ? 'none' : ''; if (loading) loading.classList.toggle('show', !!isLoading); } function setBtnText(btnEl, text) { try { const label = btnEl.querySelector('span:last-child'); if (label) label.textContent = text; } catch (_) {} } function loadScriptOnceExact(src, attrs) { return new Promise((resolve, reject) => { const existing = document.querySelector('script[data-ow-src="' + src + '"]'); if (existing) { if (existing.dataset.loaded === '1') return resolve(); existing.addEventListener('load', () => resolve(), { once:true }); existing.addEventListener('error', () => reject(new Error('Failed: ' + src)), { once:true }); return; } const s = document.createElement('script'); s.async = true; s.src = src; s.dataset.owSrc = src; if (attrs) Object.keys(attrs).forEach(k => s.setAttribute(k, String(attrs[k]))); s.onload = () => { s.dataset.loaded = '1'; resolve(); }; s.onerror = () => reject(new Error('Failed: ' + src)); document.head.appendChild(s); }); } function reinjectScriptExact(src, attrs) { return new Promise((resolve, reject) => { document.querySelectorAll('script[src="' + src + '"]').forEach(el => el.remove()); const s = document.createElement('script'); s.async = true; s.src = src; if (attrs) Object.keys(attrs).forEach(k => s.setAttribute(k, String(attrs[k]))); s.onload = () => resolve(); s.onerror = () => reject(new Error('Failed: ' + src)); document.head.appendChild(s); }); } function loadGPT() { if (window.googletag && window.googletag.apiReady) return Promise.resolve(); if (!gptLoading) { gptLoading = loadScriptOnceExact(GPT_SRC, { crossorigin: 'anonymous' }) .then(() => { window.googletag = window.googletag || { cmd: [] }; }); } return gptLoading; } function destroyRewardedSlotSafe() { try { if (window.googletag && rewardedSlot) window.googletag.destroySlots([rewardedSlot]); } catch (_) {} rewardedSlot = null; } function forceRefreshOnceSoon() { try { const gt = window.googletag; if (!gt || !gt.apiReady) return; gt.cmd.push(function () { try { const pub = gt.pubads && gt.pubads(); if (!pub) return; setTimeout(() => { try { const slots = pub.getSlots ? pub.getSlots() : []; if (slots && slots.length) { console.log('[Offerwall] Forcing refresh on slots:', slots.length); pub.refresh(slots); } else { console.warn('[Offerwall] No slots found to refresh (yet).'); } } catch (e) { console.warn('[Offerwall] refresh error:', e); } }, 300); } catch (e) { console.warn('[Offerwall] pubads error:', e); } }); } catch (_) {} } function finalizePostFlow(hardTimeout, minCloseAt) { const wait = Math.max(0, minCloseAt - Date.now()); setTimeout(() => { clearTimeout(hardTimeout); if (POST_OFFERWALL_MODE === 'redirect') { window.location.href = REDIRECT_URL; } else { removeOverlay(); flowActive = false; } }, wait); } function startPostOfferwallFlow() { if (postBooting) return; postBooting = true; setLoadingState(true); const minCloseAt = Date.now() + LOADING_MIN_MS; const hardTimeout = setTimeout(() => { console.warn('[Offerwall] post-flow timeout -> fallback'); try { if (POST_OFFERWALL_MODE === 'redirect') window.location.href = REDIRECT_URL; else removeOverlay(); } finally { flowActive = false; } }, POST_FLOW_TIMEOUTMS); if (POST_OFFERWALL_MODE === 'redirect') { finalizePostFlow(hardTimeout, minCloseAt); return; } Promise.resolve() .then(() => loadGPT()) .then(() => reinjectScriptExact(OTZ_SRC)) .then(() => forceRefreshOnceSoon()) .then(() => finalizePostFlow(hardTimeout, minCloseAt)) .catch((e) => { console.warn('[Offerwall] post-flow ads boot failed:', e); finalizePostFlow(hardTimeout, minCloseAt); }); } function showRewardedAd(btnEl) { if (flowActive) return; flowActive = true; btnEl.disabled = true; setBtnText(btnEl, 'Carregando...'); // watchdog: se travar, continua o fluxo (como você pediu) const watchdog = setTimeout(() => { console.warn('[Offerwall] WATCHDOG -> continuando fluxo'); destroyRewardedSlotSafe(); startPostOfferwallFlow(); }, WATCHDOG_MS); loadGPT() .then(() => { window.googletag = window.googletag || { cmd: [] }; googletag.cmd.push(function () { destroyRewardedSlotSafe(); rewardedSlot = googletag .defineOutOfPageSlot(adUnitPath, googletag.enums.OutOfPageFormat.REWARDED) ?.addService(googletag.pubads()); // se não conseguir criar slot, continua o fluxo if (!rewardedSlot) { console.warn('[Offerwall] Slot rewarded não criado -> continuando fluxo'); clearTimeout(watchdog); startPostOfferwallFlow(); return; } let bought = false; let completed = false; // ✅ SE NÃO COMPRAR EM 3.5s -> CONTINUA O FLUXO (pedido do user) const noBuyFallback = setTimeout(() => { if (!bought) { console.warn('[Offerwall] Sem rewardedSlotReady em', FALLBACK_MS, 'ms -> continuando fluxo'); clearTimeout(watchdog); destroyRewardedSlotSafe(); startPostOfferwallFlow(); } }, FALLBACK_MS); const pubads = googletag.pubads(); pubads.addEventListener('rewardedSlotReady', (e) => { bought = true; clearTimeout(noBuyFallback); try { e.makeRewardedVisible(); } catch (_) {} }); pubads.addEventListener('rewardedSlotGranted', () => { completed = true; }); pubads.addEventListener('rewardedSlotClosed', () => { clearTimeout(noBuyFallback); clearTimeout(watchdog); // sempre destrói ao fechar destroyRewardedSlotSafe(); if (completed) { // sucesso normal -> continua pós-sucesso startPostOfferwallFlow(); } else { // fechou sem grant -> mantém offerwall aberto e permite tentar de novo console.warn('[Offerwall] Fechou antes do grant -> mantém bloqueado'); flowActive = false; postBooting = false; // libera tentativa futura btnEl.disabled = false; setBtnText(btnEl, t.btn); } }); // ✅ no rewarded, só pode isso googletag.display(rewardedSlot); }); }) .catch((err) => { console.warn('[Offerwall] GPT não carregou -> continuando fluxo:', err); clearTimeout(watchdog); destroyRewardedSlotSafe(); startPostOfferwallFlow(); }); } document.addEventListener('DOMContentLoaded', () => { if (ALWAYS_SHOW_OFFERWALL) createOverlay(); else createOverlay(); }); })();

Ver página(abrir em uma nova aba)