|
|
如今,大多数网站都希望处理您的数据,并使用 Cookie 横幅征得您的同意。虽然这些横幅旨在让您掌控局面,但在实际操作中,它们往往导致重复且耗时的点击——尤其是当您的浏览器在关闭时清除 Cookie 时。同一个横幅会再次出现,您将发现自己一遍又一遍地做出相同的选择。
Consent-O-Matic 是一款旨在解决此问题的浏览器扩展。该工具由奥胡斯大学高级可视化与交互中心(CAVI)开发,可自动为您处理同意横幅。在安装过程中设定好偏好设置后,Consent-O-Matic 将识别众多常见的同意管理平台(CMP)横幅,应用您的选择,并在扩展图标旁显示一个小勾号进行确认。
由于 Consent-O-Matic 是一个开源项目,任何人都可以通过添加新规则、更新旧规则或更新文档来为其改进做出贡献。这种协作方式确保扩展能跟上在线同意横幅不断变化的格局——并使每个人都能更轻松地保护自己的数据,减少麻烦。
Consent-O-Matic 目前适用于 200 多种 CMP(完整列表请见此处),包括 UserCentrics、CookieBot、OneTrust 等主流平台,以及针对特定网站的 Cookie 横幅。
Consent-O-Matic 在安装后在浏览器中使用以下权限集合:
该扩展仅在两种情况下与网络通信:
通过扩展图标报告的网站 URL 会以 URI 编码的查询字符串形式发送到由奥胡斯大学托管的网站(例如,LinkedIn 将被报告为 https://gdprconsent.projects.cavi.au.dk/report.php?url=www.linkedin.com)。
我们强烈建议直接通过浏览器的官方扩展商店进行安装(顶部提及)。通过官方渠道安装将自动使您在新版本发布时保持更新。
也可以通过其他方式获取扩展。
作为扩展商店的替代方案,您可以手动从 GitHub 上的 Releases 页面下载并解压发布的版本。
最后,如果您打算审查或修改代码,可以直接从源代码构建和安装:``` git clone https://github.com/cavi-au/Consent-O-Matic.git cd Consent-O-Matic npm install
然后运行其中一个 ```npm run build-firefox``` 或 ```npm run build-chromium``` 或 ```npm run build-safari```
对于 Firefox 或 Chromium,现在可以按照上述安装发布归档的方式操作,但将浏览器指向 `build` 文件夹或您从 build/dist/ 提取 zip 的文件夹。Safari 需要加载 XCode 项目以进一步构建应用程序。
我们不推荐从源代码安装。
## 扩展 Consent-O-Matic
如果您喜欢的 CMP 不在当前列表中,可以自行创建自定义列表并添加(点击浏览器中的扩展图标,点击"More add-on settings",点击"Rule lists",然后输入自定义列表的 URL。如果您**确实**想要贡献,也可以顺便创建 Pull Request。
用户可以在特定网站的规则不起作用时发送报告。完整报告 URL 列表可在[此处](https://gdprconsent.projects.cavi.au.dk/reports.php)查看。数字表示该 URL 被报告的次数。此列表当前不显示 URL 的规则是否/何时被检查/调整,因此在开始处理之前始终验证规则是否仍然损坏或缺失。
### 规则元素
* [基本结构](#basic-structure)
* [检测器](#detectors)
* [方法](#methods)
* [DOM 选择](#dom-selection)
* [操作](#actions)
* [点击](#click)
* [列表](#list)
* [同意](#consent)
* [滑动](#slide)
* [If CSS](#if-css)
* [等待 CSS](#wait-for-css)
* [遍历](#for-each)
* [等待](#wait)
* [隐藏](#hide)
* [关闭](#close)
* [匹配器](#matchers)
* [CSS](#css)
* [复选框](#checkbox)
* [同意](#consent-1)
* [同意类别](#consent-categories)
* [完整示例](#full-example)
### 基本结构
Consent-O-Matic 的规则列表是一个 JSON 结构,包含检测 CMP(同意管理提供商)的规则,以及在检测到 CMP 弹窗时处理该弹窗的规则。
每个 CMP 是一个命名条目,包含两部分:`detectors` 和 `methods`。名称理想情况下应该是底层 CMP 的实际名称(正确大小写和空格),或者是网站的域名(如果该域名唯一)。该名称将显示在扩展设置的关于部分,因此请使其对用户友好。```json
{
"MyCMP": {
"detectors": [ ... ],
"methods": [ ... ]
},
"AnotherCMP": {
"detectors": [ ... ],
"methods": [ ... ]
},
}
如果在一个CMP中添加了超过1个检测器,则只要其中任何一个检测器触发,该CMP即被视为已检测到。
检测器是负责检测是否应应用某条规则集的部分。基本上,如果检测器触发,则相应的方法将被应用。
检测器结构:```json { "presentMatcher": [{ ... }], "showingMatcher": [{ ... }] }
当前匹配器用于检测CMP是否存在于页面上。
某些CMP在重新访问页面时,即使您之前已同意,仍会将弹窗HTML插入DOM中。我们只希望在同意表单确实显示在页面上时才处理它。这就是显示匹配器的作用。
存在匹配器和显示匹配器都遵循[`Matchers`](#matchers)的通用结构。
存在匹配器和显示匹配器可以是多个匹配器,只有当所有匹配器(分别针对存在和显示)都适用时,才会触发检测器。
#### 方法
方法是动作的集合。Consent-O-Matic支持4种方法:`OPEN_OPTIONS`、`DO_CONSENT`、`SAVE_CONSENT`、`HIDE_CMP`
所有这些方法都是可选的,如果存在,则在检测器触发时,方法将按以下顺序执行。```
HIDE_CMP
OPEN_OPTIONS
HIDE_CMP
DO_CONSENT
SAVE_CONSENT
方法采用以下形式:```json { "name": " ... ", "action": { ... } }
其中 `name` 是四种支持的方法之一,`action` 是要执行的 [action](#actions)。
---
### DOM 选择
大多数动作和匹配器都有一些它们所应用的目标。因此,Consent-O-Matic 提供了一个 DOM 选择机制,可以轻松帮助选择正确的 DOM 元素。```json
"parent": {
"selector": ".some.css.selector",
"textFilter": "someTextFilter",
"styleFilter": {
"option": "someStyleOption",
"value": "someStyleValue",
"negated": false
},
"displayFilter": true,
"iframeFilter": false,
"childFilter": {}
},
"target": {
"selector": ".some.css.selector",
"textFilter": "someTextFilter",
"styleFilter": {
"option": "someStyleOption",
"value": "someStyleValue",
"negated": false
},
"displayFilter": true,
"iframeFilter": false,
"childFilter": {}
}
共有两个部分:parent 和 target。parent 是可选的,但如果存在,则会首先解析它,并将其用作 target 的起始点。这允许你构建非常复杂的元素选择,而使用单一纯 CSS 选择器通常无法实现。一个例子是深入到 shadow DOM 中——使用 parent 定位带有 shadow 的元素,然后通过选择器查询其子元素。
parent 和 target 除 selector 外的所有参数都是可选的。
选择方法的工作方式是:使用来自 selector 的 CSS 选择器,然后通过以下各种可用过滤器对得到的 DOM 节点进行筛选:
textFilter 筛选所有不包含给定文本的节点。也可以以数组形式给出,例如 "textFilter":["filter1", "filter2"],此时它会筛选所有不包含任何一个给定文本筛选器的节点。
styleFilter 基于计算样式(computedStyles)进行筛选。option 是要比较的样式选项,例如 position;value 是比较的值;negated 设置该选项值是否应与给定值匹配或不匹配。
displayFilter 可用于根据节点是否隐藏显示来筛选节点。
iframeFilter 根据节点是否位于 iframe 内部来筛选节点。
childFilter 是一个全新的 DOM 选择,然后基于 childFilter 是否做出了选择来对原始选择进行筛选。
以下是一个 DOM 选择示例:```json "parent": { "selector": ".myParent", "iframeFilter": true, "childFilter": { "target": { "selector": ".myChild", "textFilter": "Gregor" } } }, "target": { "selector": ".myTarget" }
这个选择器首先尝试找到 `parent`,它是一个位于 iframe 内部、具有类 `myParent` 的 DOM 元素,并且有一个包含文本 "Gregor" 的、具有类 `myChild` 的子 DOM 元素。
然后,以这个 parent 作为 "root",它尝试找到一个具有类 `myTarget` 的 DOM 元素。
这个元素随后可以成为某个动作或匹配器的目标。
---
### 动作
动作是 Consent-O-Matic 中实际执行操作的部分。有些动作对目标选择执行操作,其他的与控制流有关。
#### 点击
此动作模拟对其目标的鼠标点击。
示例:```json
{
"type": "click",
"target": {
"selector": ".myButton",
"textFilter": "Save settings"
},
"openInTab": false
}
openInTab 如果设置为 true,将触发 ctrl+shift+click 而不是普通点击,这会使链接(如果有的话)在新标签页中打开,并聚焦该标签页。
在这个例子中,我们只使用了简单的 target 和 textFilter,但完整的 DOM 选择 也是支持的。
此操作按顺序运行一系列操作。
示例:```json { "type": "list", "actions": [] }
`actions` 是一个动作数组,这些动作将按顺序全部执行。
#### 同意
同意动作接受一个同意数组,并尝试应用用户的同意选择。
示例:```json
{
"type": "consent",
"consents": []
}
consents 是 同意 类型的数组
某些同意表单使用滑块来设置同意级别,此操作支持模拟滑动此类滑块。
示例:```json { "type": "slide", "target": { "selector": ".mySliderKnob" }, "dragTarget": { "target": { "selector": ".myChoosenOption" } }, "axis": "y" }
`target` 是用于模拟滑动动作的目标DOM元素。
`dragTarget` 是用于计算滑动距离的DOM元素。
`axis` 选择滑块应水平("x")还是垂直("y")移动。
滑动事件将模拟鼠标将 `target` 在指定轴向上从 `target` 拖动到 `dragTarget` 的距离。
#### 如果使用CSS
此操作用于控制流程,根据DOM选择是否找到元素来执行另一个操作。
示例:```json
{
"type": "ifcss",
"target": {
"selector": "",
},
"trueAction": {
"type": "click",
"target": {
"selector": ".myTrueButton"
}
},
"falseAction": {
"type": "click",
"target": {
"selector": ".myFalseButton"
}
}
}
trueAction 是在 DOM 选择找到元素时执行的操作。
falseAction 是在 DOM 选择未找到元素时执行的操作。
此操作会等待直到 DOM 选择器找到匹配的 DOM 元素。主要用于同意表单中某些内容加载缓慢需要等待的情况。
示例:```json { "type": "waitcss", "target": { "selector": ".myWaitTarget" }, "retries": 10, "waitTime": 200, "negated": false }
`retries` 是检查目标 DOM 元素的次数。默认为 10。
`waitTime` 决定重试间隔时间。默认为 250。
`negated` 使 "Wait For CSS" 等待直到目标未被找到。
#### 对于每个
如果某组动作需要多次运行,但每次以不同的 DOM 节点作为根节点,可以使用 for each 动作。它为其 DOM 选择所选择的每个 DOM 元素运行一次动作;所有在 for each 循环内运行的动作都将把 DOM 视为从当前选中的节点开始。
示例:```json
{
"type": "foreach",
"target": {
"selector": ".loopElement"
},
"action": {}
}
action 是对每个找到的 DOM 元素执行的操作。
此操作在继续之前等待指定的毫秒数。
示例:```json { "type": "wait", "waitTime": 250 }
#### Hide
该操作会在DOM选择上设置CSS类'ConsentOMatic-CMP-Hider'。默认的CSS规则随后会将元素的透明度设置为0。
示例:```json
{
"type": "hide",
"target": {
"selector": ".myHiddenClass"
}
}
此操作关闭当前标签页,适用于像 Evidon 这样的同意提供者——它们通常会在新标签页中打开同意控制面板。
示例:```json { "type": "close" }
### 匹配器
匹配器用于检查某个DOM选择是否存在,或者某个DOM选择的状态。
#### CSS
该匹配器检查某个DOM选择是否存在,如果存在则返回匹配。
示例:```json
{
"type": "css",
"target": {
"selector": ".myMatchingClass"
}
}
此匹配器检查 <input type='checkbox' /> 的状态,如果复选框被选中,则返回匹配。
示例:```json { "type": "checkbox", "target": { "selector": ".myInputCheckbox" } }
---
### 同意
这是 [同意动作](#consent) 内部使用的内容,用于定义用户应该给予或拒绝的实际同意。
每个同意都有一个类型,与 Consent-O-Matic 中的同意类别相匹配,因此如果用户将第一个同意类别切换为开启(类型 A)且同意类型为“A”,则该同意将被启用。
通常,同意以切换开关或一组开/关按钮的形式呈现。因此,`consent` 为每种情况提供了相应的机制。
示例:```json
{
"type": "A",
"toggleAction": {},
"matcher": {},
"trueAction": {},
"falseAction": {}
}
type 是此规则定义的同意类别类型,用于根据用户对该类别的选择来决定此同意是开启还是关闭。
toggleAction 该操作用于在弹窗使用切换开关或开关来表达同意时选择同意。如果匹配器显示同意状态与用户要求的状态不同,则执行该操作,否则不执行。
trueAction 和 falseAction 是当同意必须通过按两个按钮之一(而不是切换开/关)来给出时使用的操作。这些操作将根据用户对同意的选择来执行。如果用户已同意此类别类型,则执行 trueAction;如果用户未同意此类别类型,则执行 falseAction。
如果内容配置中同时存在 toggleAction 和 matcher,则使用 toggleAction;如果缺少其中一个,则使用 trueAction/falseAction。
如插件设置中所见,按相同顺序:
综合来看,这是一个名为“MyCMP”的 CMP 的完整示例,其中有 2 个同意类别需要切换。```json { "MyCMP": { "detectors": [ { "presentMatcher": { "type": "css", "target": { "selector": "#theCMP" } }, "showingMatcher": { "target": { "selector": "#theCMP.isShowing" } } } ], "methods": [ { "name": "OPEN_OPTIONS", "action": { "type": "click", "target": { "selector": ".button", "textFilter": "Change settings" } } }, { "name": "DO_CONSENT", "action": { "type": "list", "actions": [ { "type": "click", "target": { "selector": ".menu-vendors" } }, { "type": "consent", "consents": [ { "type": "A", "matcher": { "type": "checkbox", "parent": { "selector": ".vendor-item", "textFilter": "Functional cookies" }, "target": { "selector": "input" } }, "toggleAction": { "type": "click", "parent": { "selector": ".vendor-item", "textFilter": "Functional cookies" }, "target": { "selector": "label" } } }, { "type": "F", "matcher": { "type": "checkbox", "parent": { "selector": ".vendor-item", "textFilter": "Advertisement cookies" }, "target": { "selector": "input" } }, "toggleAction": { "type": "click", "parent": { "selector": ".vendor-item", "textFilter": "Advertisement cookies" }, "target": { "selector": "label" } } } ] } ] } }, { "name": "SAVE_CONSENT", "action": { "type": "click", "target": { "selector": ".save-consent-btn" } } } ] } }