搜索全站
插件 17 分钟阅读

WordPress Cookie 同意插件配置指南:同意记录、脚本阻断与合规要点

装了 Cookie 提示条不等于合规。本文讲清 Cookie 同意的四项硬指标:事前阻断、同等 rejection、可撤回、留痕迹,给出 Cookie Notice / CookieYes 的配置清单与自签发 trace 记录的实现方式。

U
UFO_PF 2022-07-05 · 阅读 17 分钟
Wo 插件
阅读提示
本文约 6,461 字,预计阅读 17 分钟。文中命令与配置均经过实测,可直接参考执行。

引言:以为装了提示条就合规,结果被投诉的是「早于同意就埋点」

绝大多数外贸站的 Cookie 合规止步于”页面右下角弹了个小条”。这类提示条做了一件正确的事——告知,但恰恰漏掉了合规里最核心的一条:在用户做出选择之前,不能加载任何非必要的追踪脚本。

欧盟 GDPR + ePrivacy 的要求是「事前同意(prior consent)」:如果 GA4、Facebook Pixel、Hotjar 在用户点同意之前就已经向 Google 服务器发了请求并写下了 cookie,那么后端显示的”接受率 92%”在法律上是无效的——因为用户没有真正的拒绝选项,他还没来得及反应,数据就已经出去了。这正是 2022–2024 年间大批网站收到 CNIL(法国)、Garante(意大利)罚单的主要理由。

对国内面向欧盟 / 英国 / 加州用户的站点,这不是可选项。而且《个人信息保护法》对境内用户也有类似的”单独同意”要求。本文从技术落地角度,讲清一个真正达标的 Cookie 同意方案该怎么做。

原理分析:合规的四道硬门槛

要求 不达标的表现 技术判据
事前阻断 打开页面时 Network 面板已出现 googletagmanager.com 请求 未阻断时必然出现
拒绝与接受同等重要 只有「Accept」一个大按钮,拒绝要点两三次 UI 层级对等
可随时撤回 关闭后再无入口 提供常驻重新打开入口
同意留痕 无法证明某用户何时同意了什么 有 consent log 记录

技术上「事前阻断」只有一种可靠做法:不要把 gtag/GTM 的 <script> 直接写进主题 head,而是交给同意插件按其状态动态注入;或者更彻底的方案——把 GA 脚本的 <script> 类型改成 text/plain 并加 data-cookiecategory="analytics",由同意插件在获得许可后把它改成 text/javascript 再 eval 执行。

CookieYes、Complianz、Borlabs Cookie、Real Cookie Banner 都支持这种”类别化管理”。Cookie Notice(由 Hu-manity.co 团队维护,安装量 100 万+)是轻量代表,但它的免费版在脚本阻断上能力有限,需要搭配手动改造。

第二件必须想清楚的是记录存哪。最简单能过关的做法是在 MySQL 里建一张 consent log 表,记录 consent_id / 匿名 IP 哈希 / 同意时间 / 同意的类别 / 使用的政策版本。不要记原始 IP(那本身就是个人信息),记 wp_hash() 之后的值即可。

保姆级实操

步骤 1:盘点站点上到底有哪些追踪脚本

动手之前先 inventory。用健康检查:

# 1) 抓自己首页,列出所有外域脚本/图片请求
curl -s -A "Mozilla/5.0" https://example.com/ \
  | grep -oE '(script|iframe|img)[^>]*src="[^"]+"' \
  | grep -oE 'https?://[^/"]+' | sort -u

# 2) 检查 Set-Cookie 的域与生命周期
curl -sI https://example.com/ | grep -i set-cookie

把结果按「必要 / 分析 / 营销 / 偏好」四类分好,这是后面所有配置的基础表。

步骤 2:安装并配置 CookieYes(免费版够大多数站点)

后台安装 CookieYes | GDPR Cookie Consent,激活后:

  • Cookie Scanner:先跑一次自动扫描,它会枚举当前已存在的 cookie 并给出建议分类。注意扫描只能抓到”已发生”的 cookie,改完要重扫。
  • Consent Banner → Layout:选 Classic 或 Box,Show As 一定选 Banner/Box 而不是 “Notification only”,后者没有按钮等于无效。
  • Buttons:把 Reject 按钮打开。Accept 与 Reject 的样式必须一致(同色背景是可接受的,但 Reject 不能做成灰色小字)。
  • Consent Expiry:建议 6–12 个月(很多监管机构认为超过 13 个月不合理)。
  • Policy Version:每次改隐私政策后 bump 一次,插件会据此重新征求同意——这一步很多人忘了,导致老用户停留在旧政策的同意状态上。

步骤 3:把第三方脚本改造成可被阻断的形式

以 GA4 为例,原本的加载代码要改成这个形式(注意 type="text/plain" 与 data-cookiecategory):

<!-- Google Analytics 4:默认不执行,由同意插件解锁 -->
<script type="text/plain" data-cookiecategory="analytics" async
        src="https://www.googletagmanager.com/gtag/js?id=G-XXXXXXXXXX"></script>
<script type="text/plain" data-cookiecategory="analytics">
    window.dataLayer = window.dataLayer || [];
    function gtag(){ dataLayer.push( arguments ); }
    gtag( 'js', new Date() );
    gtag( 'config', 'G-XXXXXXXXXX', { anonymize_ip: true } );
</script>

对应的 GTM 容器也一样处理:

<script type="text/plain" data-cookiecategory="analytics">
    (function(w,d,s,l,i){ w[l]=w[l]||[]; w[l].push({'gtm.start': new Date().getTime(), event:'gtm.js'});
    var f=d.getElementsByTagName(s)[0], j=d.createElement(s), dl=l!='dataLayer'?'&l='+l:'';
    j.async=true; j.src='https://www.googletagmanager.com/gtm.js?id='+i+dl; f.parentNode.insertBefore(j,f);
    })(window,document,'script','dataLayer','GTM-XXXXXXX');
</script>

步骤 4:记录同意日志(自己写一张 log 表最稳)

CookieYes / Complianz 都自带日志,但如果你想自己留一份便于审计:

/**
 * 接收前端同意回调,写入自定义表。表结构见下方 SQL。
 */
add_action( 'wp_ajax_mf_log_consent', 'mf_log_consent' );
add_action( 'wp_ajax_nopriv_mf_log_consent', 'mf_log_consent' );
function mf_log_consent() {
    check_ajax_referer( 'mf_consent', 'nonce' );
    global $wpdb;
    $cats = isset( $_POST['categories'] ) ? array_map( 'sanitize_key', (array) $_POST['categories'] ) : array();
    $wpdb->insert(
        $wpdb->prefix . 'consent_log',
        array(
            'ip_hash'   => wp_hash( $_SERVER['REMOTE_ADDR'] . wp_salt() ),
            'categories' => implode( ',', $cats ),
            'policy_ver' => sanitize_text_field( $_POST['policy_ver'] ?? '1' ),
            'created_at' => current_time( 'mysql', 1 ),
        ),
        array( '%s', '%s', '%s', '%s' )
    );
    wp_send_json_success();
}

配套建表(用 dbDelta,放在插件激活钩子里):

function mf_create_consent_table() {
    global $wpdb;
    $table   = $wpdb->prefix . 'consent_log';
    $charset = $wpdb->get_charset_collate();
    $sql = "CREATE TABLE {$table} (
        id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
        ip_hash varchar(64) NOT NULL,
        categories varchar(255) NOT NULL,
        policy_ver varchar(20) NOT NULL DEFAULT '1',
        created_at datetime NOT NULL,
        PRIMARY KEY (id),
        KEY idx_created (created_at)
    ) {$charset};";
    require_once ABSPATH . 'wp-admin/includes/upgrade.php';
    dbDelta( $sql );
}

步骤 5:提供「撤回同意」常驻入口

在页脚固定放一个链接,点击后 reopen banner:

// 页脚挂一个重新打开 Cookie 设置的入口
add_action( 'wp_footer', function() {
    echo '<button type="button" class="mf-cookie-settings" data-cky-tag="settings-button">Cookie 设置</button>';
} );

CookieYes 的短代码版本也能直接用:[cky_preference]/[cky_policy]。

步骤 6:验证——最重要的一步

无痕模式打开站点,先不要点任何按钮,打开 DevTools Network 面板刷新:

# 期望输出为空:同意前不应有任何 analytics/googletagmanager 请求
curl -s https://example.com/ | grep -c 'googletagmanager.com'

再点 Accept,确认此时才出现 gtag/js 请求;点完全一致 Reject,确认没有任何第三方脚本请求;最后验证刷新后(已拒绝)依然不加载。

常见踩坑

  1. 同意前脚本已经跑起来了:八成是脚本被写在了主题 header.php 里,绕过了同意插件。必须走 type="text/plain" 或插件的注入机制。
  2. 点了拒绝但 cookie 还在:旧 cookie 不会自动消失。需要在拒绝回调里显式删除 _ga / _fbp 等:

js
document.cookie = '_ga=; Max-Age=0; path=/; domain=.' + location.hostname;
document.cookie = '_ga_XXXX=; Max-Age=0; path=/; domain=.' + location.hostname;

  1. 案例:某跨境电商站的 GA4 通过 Google Site Kit 安装(Site Kit 会在 wp_head 里直接注入 snippet,不受同意插件管辖),导致无论用户点接受还是拒绝,GA 都在正常采集。德国客户做合规审查时抓到了这一条,要求限期整改并出具同意日志,而站点压根没有 consent log 功能。最后整个统计体系迁移到 GTM + 同意钩子方案才过关。教训:用 Site Kit 这类”一站式安装”的统计接入,必须额外确认它是否受同意插件管控。
  2. 只有 Accept 按钮:这是最常见的罚金事由(法国 CNIL 罚 Google 和 Facebook 的核心理由就是这个)。必须与 Reject 同等视觉权重。
  3. banner 被 z-index 压在下面:悬浮客服、登录弹窗的 z-index 经常是 99999,把 consent banner 盖住视为未告知。给 banner 容器 z-index 设为 2147483647。
  4. 对 EU 用户才弹,IP 库判断错误:IP 归属地判断存在误差,且很多用户用 VPN。稳妥做法是对所有访客展示(至少一次),只是对非 EU 用户不强制阻断,这属于合规实践里的保守选择。
  5. 同意日志记了原始 IP:日志系统本身就成了新的个人信息处理行为,反而增加义务。记 hash + 时间戳足够。
  6. iframe(YouTube、Google Maps)自动写入 cookie:嵌入 iframe 在点击前就会 set cookie。要么用「点击才加载」的 nocookie 预览图,要么明确写入隐私政策并在 banner 里声明为必要。

延伸阅读:Complianz 与 CookieYes 插件对比

总结

四句话的判断清单:①同意之前,Network 面板里不能出现任何第三方追踪域;②Accept 与 Reject 必须视觉对等;③任何页面都能重新打开设置修改选择;④同意要有日志,且日志本身不存敏感字段。 达到这四条,面对绝大多数审计基本站得住。工具选择上:预算有限、脚本简单用 CookieYes;WordPress + 服务器一体化的多区域方案用 Complianz(下一篇详解);不想引入插件、只需要管控少量脚本,用上面的 type="text/plain" 方案二十行代码也能达标。

合规配套内容:WordPress 隐私政策页面生成与修改

U
UFO_PF作者

专注 WordPress 生态的实战作者,内容以「可复制、可验证」为第一原则。

留下你的想法

邮箱地址不会被公开。带 * 的为必填项。