「強制彈窗」屬於干擾性廣告,主流瀏覽器(Chrome、Firefox、Safari)內建攔截器會自動阻擋 window.open、alert、覆蓋層彈窗。生產環境請優先考慮原生廣告位、信息流廣告、激勵視頻等用戶可接受形式。本文僅作技術原理演示,不建議直接用於正式項目。
<?php
session_start();
// 配置
$adConfig = [
'maxPerSession' => 1, // 每 Session 最大彈出次數
'lifeTime' => 24 * 3600, // Session 生命週期 (秒)
'cookieDomain' => '.example.com', // 跨子域共享
];
// 初始化 Session 參數
session_set_cookie_params($adConfig['lifeTime'], '/', $adConfig['cookieDomain'], true, true); // Secure, HttpOnly
if (!isset($_SESSION['ad_pop_count'])) $_SESSION['ad_pop_count'] = 0;
// 判斷是否彈出
$shouldPop = $_SESSION['ad_pop_count'] < $adConfig['maxPerSession'];
if ($shouldPop) {
$_SESSION['ad_pop_count']++;
$popHtml = '<div id="forced-ad" style="position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);z-index:9999;background:white;padding:20px;border-radius:8px;box-shadow:0 0 20px rgba(0,0,0,.3);">
<button onclick="document.getElementById(\'forced-ad\').remove()" style="float:right;background:none;border:none;font-size:18px;cursor:pointer">×</button>
<a href="https://ad.example.com/landing" target="_blank"><img src="https://ad.example.com/banner.jpg" width="400"></a>
</div>';
} else {
$popHtml = '';
}
<!DOCTYPE html>
<html>
<head><meta charset="UTF-8"><title>頁面</title></head>
<body>
<!-- 頁面正文內容 -->
<?php if ($shouldPop): ?>
<div id="forced-ad" class="ad-popup">
<button class="ad-close" aria-label="關閉廣告">×</button>
<a href="https://ad.example.com/landing" target="_blank" rel="noopener">
<img src="https://ad.example.com/banner.jpg" alt="廣告" width="400">
</a>
</div>
<script>
// 1. 延遲顯示,避免阻塞首屏
setTimeout(() => document.getElementById('forced-ad').classList.add('show'), 2000);
// 2. 關閉按鈕
document.querySelector('.ad-close').onclick = () => document.getElementById('forced-ad').remove();
// 3. 記錄關閉,下次不再彈出 (可選,配合後端 Session)
// fetch('/api/ad/close', {method:'POST', credentials:'include'});
</script>
<style>
.ad-popup {position:fixed;top:50%;left:50%;transform:translate(-50%,-50%) scale(0.8);opacity:0;transition:.3s;z-index:9999;background:#fff;padding:1rem;border-radius:8px;box-shadow:0 0 30px #0003;}
.ad-popup.show {transform:translate(-50%,-50%) scale(1);opacity:1;}
.ad-close {position:absolute;top:4px;right:8px;background:none;border:none;font-size:1.2rem;cursor:pointer;color:#666;}
@media (max-width:480px) {.ad-popup {width:90%;max-width:400px;}}
</style>
<?php endif; ?>
</body>
</html>
<?php
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
$ip = $_SERVER['HTTP_X_FORWARDED_FOR'] ?? $_SERVER['REMOTE_ADDR'];
$key = "ad:pop:$ip";
$max = 1; // 每天 1 次
$ttl = 86400;
$count = $redis->incr($key);
if ($count === 1) $redis->expire($key, $ttl);
$shouldPop = $count <= $max;
// ... 輸出廣告 HTML
| 項目 | 要求 | 檢查方式 |
|---|---|---|
| 頻率控制 | 單用戶/單設備 24h 內 ≤ 1 次 | Session/Redis 計數器 |
| 關閉按鈕 | 明顯、可點擊、無誘導點擊區域 | 人工測試 + 自動化測試 |
| 不遮擋核心內容 | 彈窗不覆蓋導航、正文、表單 | 響應式測試 |
| 無自動播放聲音/視頻 | 靜默加載,用戶交互後播放 | Chrome 自動播放策略檢查 |
| 隱私合規 | 不收集個人信息,或已獲同意 | GDPR/個信法自查 |
| 瀏覽器攔截率 | 預期 > 80% 被攔截 | Chrome 開發者工具 → Console 觀察攔截日誌 |
PHP 實現強制廣告彈窗的技術要點:Session/Redis 計數頻控 → 後端注入 HTML/JS → 前端延遲顯示 + 關閉交互。但受限於瀏覽器攔截機制、用戶體驗紅線、法律法規,強烈建議放棄強制彈窗,轉向原生/信息流/激勵式廣告。若必須保留,請嚴格執行頻控、提供關閉、靜默加載、合規審核。