You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

单页面多广告场景下如何用PHP实现网站访问量仅单次统计

解决单页面多广告重复记录网站访问量的问题

我来帮你排查下问题并给出可行的解决方案哈~

先分析你的Cookie方案失效的原因

你的思路方向是对的,但大概率是这两个细节没处理到位:

  • Cookie路径问题:默认生成的Cookie路径是当前脚本所在目录,如果你的广告代码分散在不同子目录,每个脚本的Cookie互相不可见,导致每个广告脚本都判断用户是“新访客”。
  • 并行执行的竞态问题:多个广告脚本几乎同时加载执行,Cookie还没来得及被第一个脚本设置成功,后面的脚本就已经读取到“Cookie不存在”的状态,于是都执行了插入操作。

最优解决方案:用PHP会话(Session)替代单纯的Cookie

Session本质是基于Cookie的,但自带全局可见性和会话锁机制,能完美解决上述问题。修改后的代码如下:

// 先启动会话,确保全局共享会话数据,同时会话锁会防止并行脚本重复执行
session_start();

// 检查会话中是否已经标记过本次页面访问的记录
if (!isset($_SESSION['web_impression_recorded'])) {
    // 执行网站访问量插入操作
    $stmt = $conn->prepare("INSERT INTO webimps (zoneweb, session, time, ref, device, visitorip, os, oldnew, browser, wview) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"); 
    $stmt->bind_param("ssssssssss", $web, $session, $time, $ref, $device, $ip, $user_os, 'new', $user_browser, $one); 
    $stmt->execute(); 
    $stmt->close();

    // 标记会话已完成访问记录,同一会话内的所有脚本都会读到这个标记
    $_SESSION['web_impression_recorded'] = true;

    // 可选:兼容你原来的Cookie逻辑,设置根路径的Cookie
    setcookie('userstatus', 'old', time() + 86400, '/'); // 有效期1天,路径设为根目录
} else {
    $oldnew = "old";
}

为什么这个方案有效?

  • 全局可见:Session的Cookie默认路径是网站根目录(/),所有子目录的广告脚本都能读取到同一个会话数据。
  • 避免竞态session_start()会自动加会话锁,当第一个脚本启动会话并设置标记后,其他并行加载的广告脚本会等待锁释放,此时读取到的会话标记已经存在,就不会重复执行插入操作。

如果广告是独立请求(比如iframe/异步脚本)

如果你的广告代码是通过iframe嵌入或异步请求加载的独立PHP文件,那可以调整逻辑:

  1. 主页面的头部先执行访问量记录逻辑,提前标记会话
  2. 广告脚本只需要检查会话标记,跳过访问量记录,只处理广告曝光量

主页面代码示例:

// 主页面头部优先执行
session_start();
if (!isset($_SESSION['web_impression_recorded'])) {
    // 插入网站访问量
    // ...(你的插入代码)
    $_SESSION['web_impression_recorded'] = true;
}

广告脚本代码:

session_start();
// 只记录广告曝光量,跳过访问量插入
$stmt = $conn->prepare("INSERT INTO adimps (...) VALUES (...)"); 
// ...广告曝光量的绑定和执行逻辑

备选方案:IP+时间窗口(不推荐,仅作补充)

如果担心用户禁用Cookie导致会话失效,可以用IP+时间窗口的方式,但这种方式不够精准(比如同一IP下多个用户会被视为同一访客),代码示例:

$ip = $_SERVER['REMOTE_ADDR'];
$time_window = time() - 300; // 5分钟内同一IP只记录一次访问量

// 检查最近5分钟内该IP是否已有访问记录
$stmt = $conn->prepare("SELECT id FROM webimps WHERE visitorip = ? AND time > ? LIMIT 1");
$stmt->bind_param("ss", $ip, $time_window);
$stmt->execute();
$stmt->store_result();

if ($stmt->num_rows === 0) {
    // 执行网站访问量插入
    // ...你的插入代码
}
$stmt->close();

内容的提问来源于stack exchange,提问作者Oliver

火山引擎 最新活动