@slashgear/gdpr-cookie-scanner 3.6.0 → 3.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (149) hide show
  1. package/.dockerignore +3 -0
  2. package/.gitattributes +1 -0
  3. package/.github/workflows/website.yml +80 -0
  4. package/CHANGELOG.md +52 -0
  5. package/CLAUDE.md +12 -1
  6. package/CONTRIBUTING.md +32 -4
  7. package/NEXT_STEPS.md +37 -3
  8. package/README.md +23 -0
  9. package/dist/analyzers/colour.d.ts +36 -0
  10. package/dist/analyzers/colour.d.ts.map +1 -0
  11. package/dist/analyzers/colour.js +75 -0
  12. package/dist/analyzers/colour.js.map +1 -0
  13. package/dist/analyzers/compliance.d.ts.map +1 -1
  14. package/dist/analyzers/compliance.js +24 -6
  15. package/dist/analyzers/compliance.js.map +1 -1
  16. package/dist/analyzers/tcf-decoder.d.ts +9 -0
  17. package/dist/analyzers/tcf-decoder.d.ts.map +1 -0
  18. package/dist/analyzers/tcf-decoder.js +123 -0
  19. package/dist/analyzers/tcf-decoder.js.map +1 -0
  20. package/dist/analyzers/wording.d.ts +1 -0
  21. package/dist/analyzers/wording.d.ts.map +1 -1
  22. package/dist/analyzers/wording.js +39 -0
  23. package/dist/analyzers/wording.js.map +1 -1
  24. package/dist/report/generator.d.ts +1 -0
  25. package/dist/report/generator.d.ts.map +1 -1
  26. package/dist/report/generator.js +71 -1
  27. package/dist/report/generator.js.map +1 -1
  28. package/dist/report/html.d.ts.map +1 -1
  29. package/dist/report/html.js +123 -0
  30. package/dist/report/html.js.map +1 -1
  31. package/dist/scanner/consent-modal.d.ts.map +1 -1
  32. package/dist/scanner/consent-modal.js +4 -2
  33. package/dist/scanner/consent-modal.js.map +1 -1
  34. package/dist/scanner/index.d.ts.map +1 -1
  35. package/dist/scanner/index.js +4 -0
  36. package/dist/scanner/index.js.map +1 -1
  37. package/dist/scanner/tcf.d.ts +9 -0
  38. package/dist/scanner/tcf.d.ts.map +1 -0
  39. package/dist/scanner/tcf.js +72 -0
  40. package/dist/scanner/tcf.js.map +1 -0
  41. package/dist/types.d.ts +26 -0
  42. package/dist/types.d.ts.map +1 -1
  43. package/package.json +7 -3
  44. package/pnpm-workspace.yaml +3 -0
  45. package/scripts/build-showcase.mjs +113 -0
  46. package/src/analyzers/colour.ts +89 -0
  47. package/src/analyzers/compliance.ts +35 -10
  48. package/src/analyzers/tcf-decoder.ts +130 -0
  49. package/src/analyzers/wording.ts +44 -0
  50. package/src/report/generator.ts +83 -1
  51. package/src/report/html.ts +146 -0
  52. package/src/scanner/consent-modal.ts +3 -1
  53. package/src/scanner/index.ts +5 -0
  54. package/src/scanner/tcf.ts +80 -0
  55. package/src/types.ts +29 -0
  56. package/tests/analyzers/colour.test.ts +187 -0
  57. package/tests/analyzers/compliance.test.ts +102 -0
  58. package/tests/analyzers/tcf-decoder.test.ts +292 -0
  59. package/tests/analyzers/wording.test.ts +38 -0
  60. package/tests/scanner/button-classification.test.ts +32 -0
  61. package/website/Dockerfile +55 -0
  62. package/website/node_modules/.bin/oxfmt +21 -0
  63. package/website/node_modules/.bin/oxlint +21 -0
  64. package/website/node_modules/.bin/tsc +21 -0
  65. package/website/node_modules/.bin/tsserver +21 -0
  66. package/website/node_modules/.bin/tsx +21 -0
  67. package/website/package.json +29 -0
  68. package/{docs → website/public}/index.html +88 -50
  69. package/website/public/reports/www.20minutes.fr/after-accept.png +3 -0
  70. package/website/public/reports/www.20minutes.fr/after-reject.png +3 -0
  71. package/website/public/reports/www.20minutes.fr/gdpr-report-20minutes.fr-2026-02-22.html +907 -0
  72. package/website/public/reports/www.20minutes.fr/modal-initial.png +3 -0
  73. package/website/public/reports/www.arte.tv/after-accept.png +3 -0
  74. package/website/public/reports/www.arte.tv/after-reject.png +3 -0
  75. package/website/public/reports/www.arte.tv/gdpr-report-arte.tv-2026-02-24.html +998 -0
  76. package/website/public/reports/www.arte.tv/modal-initial.png +3 -0
  77. package/website/public/reports/www.backmarket.fr/after-accept.png +3 -0
  78. package/website/public/reports/www.backmarket.fr/after-reject.png +3 -0
  79. package/website/public/reports/www.backmarket.fr/gdpr-report-backmarket.fr-2026-02-24.html +1530 -0
  80. package/website/public/reports/www.backmarket.fr/modal-initial.png +3 -0
  81. package/website/public/reports/www.deezer.com/after-accept.png +3 -0
  82. package/website/public/reports/www.deezer.com/after-reject.png +3 -0
  83. package/website/public/reports/www.deezer.com/gdpr-report-deezer.com-2026-02-22.html +1668 -0
  84. package/website/public/reports/www.deezer.com/modal-initial.png +3 -0
  85. package/website/public/reports/www.france.tv/after-accept.png +3 -0
  86. package/website/public/reports/www.france.tv/after-reject.png +3 -0
  87. package/website/public/reports/www.france.tv/gdpr-report-france.tv-2026-02-23.html +977 -0
  88. package/website/public/reports/www.france.tv/modal-initial.png +3 -0
  89. package/website/public/reports/www.m6.fr/after-accept.png +3 -0
  90. package/website/public/reports/www.m6.fr/after-reject.png +3 -0
  91. package/website/public/reports/www.m6.fr/gdpr-report-m6.fr-2026-02-28.html +1862 -0
  92. package/website/public/reports/www.m6.fr/modal-initial.png +3 -0
  93. package/website/public/reports/www.netflix.com/after-accept.png +3 -0
  94. package/website/public/reports/www.netflix.com/after-reject.png +3 -0
  95. package/website/public/reports/www.netflix.com/gdpr-report-netflix.com-2026-02-23.html +1051 -0
  96. package/website/public/reports/www.netflix.com/modal-initial.png +3 -0
  97. package/website/public/reports/www.radiofrance.fr/after-accept.png +3 -0
  98. package/website/public/reports/www.radiofrance.fr/after-reject.png +3 -0
  99. package/website/public/reports/www.radiofrance.fr/gdpr-report-radiofrance.fr-2026-02-24.html +1146 -0
  100. package/website/public/reports/www.radiofrance.fr/modal-initial.png +3 -0
  101. package/website/public/reports/www.tf1.fr/after-accept.png +3 -0
  102. package/website/public/reports/www.tf1.fr/after-reject.png +3 -0
  103. package/website/public/reports/www.tf1.fr/gdpr-report-tf1.fr-2026-02-23.html +1512 -0
  104. package/website/public/reports/www.tf1.fr/modal-initial.png +3 -0
  105. package/website/src/index.ts +15 -0
  106. package/website/src/security.ts +26 -0
  107. package/website/tsconfig.json +14 -0
  108. package/.github/workflows/pages.yml +0 -40
  109. package/docs/reports/github.com/after-accept.png +0 -0
  110. package/docs/reports/github.com/after-reject.png +0 -0
  111. package/docs/reports/github.com/gdpr-checklist-github.com-2026-02-22.md +0 -44
  112. package/docs/reports/github.com/gdpr-cookies-github.com-2026-02-22.md +0 -29
  113. package/docs/reports/github.com/gdpr-report-github.com-2026-02-22.md +0 -102
  114. package/docs/reports/github.com/gdpr-report-github.com-2026-02-22.pdf +0 -0
  115. package/docs/reports/gitlab.com/after-accept.png +0 -0
  116. package/docs/reports/gitlab.com/after-reject.png +0 -0
  117. package/docs/reports/gitlab.com/gdpr-checklist-gitlab.com-2026-02-22.md +0 -44
  118. package/docs/reports/gitlab.com/gdpr-cookies-gitlab.com-2026-02-22.md +0 -55
  119. package/docs/reports/gitlab.com/gdpr-report-gitlab.com-2026-02-22.md +0 -200
  120. package/docs/reports/gitlab.com/gdpr-report-gitlab.com-2026-02-22.pdf +0 -0
  121. package/docs/reports/gitlab.com/modal-initial.png +0 -0
  122. package/docs/reports/npmjs.com/after-accept.png +0 -0
  123. package/docs/reports/npmjs.com/after-reject.png +0 -0
  124. package/docs/reports/npmjs.com/gdpr-checklist-npmjs.com-2026-02-22.md +0 -44
  125. package/docs/reports/npmjs.com/gdpr-cookies-npmjs.com-2026-02-22.md +0 -25
  126. package/docs/reports/npmjs.com/gdpr-report-npmjs.com-2026-02-22.md +0 -88
  127. package/docs/reports/npmjs.com/gdpr-report-npmjs.com-2026-02-22.pdf +0 -0
  128. package/docs/reports/reddit.com/after-accept.png +0 -0
  129. package/docs/reports/reddit.com/after-reject.png +0 -0
  130. package/docs/reports/reddit.com/gdpr-checklist-reddit.com-2026-02-22.md +0 -44
  131. package/docs/reports/reddit.com/gdpr-cookies-reddit.com-2026-02-22.md +0 -33
  132. package/docs/reports/reddit.com/gdpr-report-reddit.com-2026-02-22.md +0 -148
  133. package/docs/reports/reddit.com/gdpr-report-reddit.com-2026-02-22.pdf +0 -0
  134. package/docs/reports/reddit.com/modal-initial.png +0 -0
  135. package/docs/reports/stackoverflow.com/after-accept.png +0 -0
  136. package/docs/reports/stackoverflow.com/after-reject.png +0 -0
  137. package/docs/reports/stackoverflow.com/gdpr-checklist-stackoverflow.com-2026-02-22.md +0 -44
  138. package/docs/reports/stackoverflow.com/gdpr-cookies-stackoverflow.com-2026-02-22.md +0 -67
  139. package/docs/reports/stackoverflow.com/gdpr-report-stackoverflow.com-2026-02-22.md +0 -206
  140. package/docs/reports/stackoverflow.com/gdpr-report-stackoverflow.com-2026-02-22.pdf +0 -0
  141. package/docs/reports/stackoverflow.com/modal-initial.png +0 -0
  142. package/docs/reports/www.afp.com/after-accept.png +0 -0
  143. package/docs/reports/www.afp.com/after-reject.png +0 -0
  144. package/docs/reports/www.afp.com/gdpr-checklist-afp.com-2026-02-22.md +0 -44
  145. package/docs/reports/www.afp.com/gdpr-cookies-afp.com-2026-02-22.md +0 -42
  146. package/docs/reports/www.afp.com/gdpr-report-afp.com-2026-02-22.md +0 -202
  147. package/docs/reports/www.afp.com/gdpr-report-afp.com-2026-02-22.pdf +0 -0
  148. package/docs/reports/www.afp.com/modal-initial.png +0 -0
  149. /package/{docs → website/public}/style.css +0 -0
@@ -1,206 +0,0 @@
1
- # GDPR Compliance Report — stackoverflow.com
2
-
3
- > **Scan date:** 22/02/2026, 19:24:00
4
- > **Scanned URL:** https://stackoverflow.com
5
- > **Scan duration:** 12.5s
6
- > **Tool:** gdpr-cookie-scanner v0.1.0
7
-
8
- ## Global Compliance Score
9
-
10
- ### 🟠 66/100 — Grade C
11
-
12
- | Criterion | Score | Progress | Status |
13
- | ---------------- | ---------- | ---------- | ------ |
14
- | Consent validity | 25/25 | ██████████ | ✅ |
15
- | Easy refusal | 10/25 | ████░░░░░░ | ❌ |
16
- | Transparency | 20/25 | ████████░░ | ✅ |
17
- | Cookie behavior | 11/25 | ████░░░░░░ | ❌ |
18
- | **TOTAL** | **66/100** | | **C** |
19
-
20
- ## Executive Summary
21
-
22
- ✅ Consent modal detected (`#onetrust-banner-sdk`).
23
- ❌ **1 non-essential cookie(s)** set before any interaction (RGPD violation).
24
- ❌ **1 non-essential cookie(s)** persisting after rejection (RGPD violation).
25
- ❌ **7 tracker request(s)** fired before consent.
26
-
27
- **3 critical issue(s)** and **1 warning(s)** identified.
28
-
29
- ## 1. Consent Modal
30
-
31
- **CSS selector:** `#onetrust-banner-sdk`
32
- **Granular controls:** ✅ Yes
33
- **Layer count:** 2
34
- **Privacy policy link:** ⚠️ Not found in the modal
35
-
36
- ### Detected buttons
37
-
38
- | Button | Text | Visible | Font size | Contrast ratio |
39
- | -------------- | -------------------------- | ------- | --------- | -------------- |
40
- | ❓ Unknown | List of Partners (vendors) | ✅ | 13.12px | 11.45:1 |
41
- | 🟢 Accept | Accept all cookies | ✅ | 13.12px | 8.27:1 |
42
- | ❓ Unknown | Necessary cookies only | ✅ | 13.12px | 8.27:1 |
43
- | ⚙️ Preferences | Customize Settings | ✅ | 13.12px | 8.27:1 |
44
-
45
- ### Screenshot
46
-
47
- ![Consent modal](modal-initial.png)
48
-
49
- ### Modal text excerpt
50
-
51
- > We Care About Your PrivacyWe and our 277 partners store and access personal data, like browsing data or unique identifiers, on your device. Selecting Accept all cookies enables tracking technologies to support the purposes shown under we and our partners process data to provide. Selecting Necessary cookies only or withdrawing your consent will disable them. If trackers are disabled, some content and ads you see may not be as relevant to you. You can resurface this menu to change your choices or ...
52
-
53
- ## 2. Dark Patterns and Detected Issues
54
-
55
- ### ❌ Critical issues
56
-
57
- **No reject button on first layer**
58
-
59
- > CNIL (2022) requires reject to require no more clicks than accept
60
-
61
- **1 non-essential cookie(s) deposited before any interaction**
62
-
63
- > prov (unknown)
64
-
65
- **7 tracker request(s) fired before any consent**
66
-
67
- > Google Tag Manager, Google AdSense, Google DoubleClick, Google Analytics, Tracking Pixel
68
-
69
- ### ⚠️ Warnings
70
-
71
- **No privacy policy link found in the consent modal**
72
-
73
- > GDPR Art. 13 requires the privacy policy to be accessible from the consent interface
74
-
75
- ## 3. Cookies Set Before Any Interaction
76
-
77
- | Name | Domain | Category | Expiry | Consent required |
78
- | ---------------- | ------------------ | -------- | --------- | ---------------- |
79
- | `prov` | .stackoverflow.com | unknown | 12 months | ⚠️ Yes |
80
- | `__cflb` | stackoverflow.com | unknown | 1 days | ✅ No |
81
- | `__cf_bm` | .stackoverflow.com | unknown | < 1 day | ✅ No |
82
- | `_cfuvid` | .stackoverflow.com | unknown | Session | ✅ No |
83
- | `__cf_bm` | .i.sstatic.net | unknown | < 1 day | ✅ No |
84
- | `_cfuvid` | .i.sstatic.net | unknown | Session | ✅ No |
85
- | `cf_clearance` | .stackoverflow.com | unknown | 12 months | ✅ No |
86
- | `g_state` | stackoverflow.com | unknown | 6 months | ✅ No |
87
- | `OptanonConsent` | .stackoverflow.com | unknown | 12 months | ✅ No |
88
-
89
- ## 4. Cookies After Consent Rejection
90
-
91
- ✅ No non-essential cookie detected after rejection.
92
-
93
- _No cookies detected._
94
-
95
- ## 5. Cookies After Consent Acceptance
96
-
97
- | Name | Domain | Category | Expiry | Consent required |
98
- | ---------------------------- | ------------------- | ----------- | --------- | ---------------- |
99
- | `prov` | .stackoverflow.com | unknown | 12 months | ⚠️ Yes |
100
- | `__cflb` | stackoverflow.com | unknown | 1 days | ✅ No |
101
- | `__cf_bm` | .stackoverflow.com | unknown | < 1 day | ✅ No |
102
- | `_cfuvid` | .stackoverflow.com | unknown | Session | ✅ No |
103
- | `__cf_bm` | .i.sstatic.net | unknown | < 1 day | ✅ No |
104
- | `_cfuvid` | .i.sstatic.net | unknown | Session | ✅ No |
105
- | `cf_clearance` | .stackoverflow.com | unknown | 12 months | ✅ No |
106
- | `g_state` | stackoverflow.com | unknown | 6 months | ✅ No |
107
- | `OptanonAlertBoxClosed` | .stackoverflow.com | unknown | 12 months | ✅ No |
108
- | `_sharedID` | .stackoverflow.com | unknown | 1 months | ✅ No |
109
- | `_sharedID_cst` | .stackoverflow.com | unknown | 1 months | ✅ No |
110
- | `eupubconsent-v2` | .stackoverflow.com | unknown | 12 months | ✅ No |
111
- | `_ga` | .stackoverflow.com | analytics | 13 months | ⚠️ Yes |
112
- | `_ga_WCZ03SZFCQ` | .stackoverflow.com | analytics | 13 months | ⚠️ Yes |
113
- | `OptanonConsent` | .stackoverflow.com | unknown | 12 months | ✅ No |
114
- | `__eoi` | .stackoverflow.com | unknown | 6 months | ✅ No |
115
- | `pbjs-unifiedid` | stackoverflow.com | unknown | 2 months | ✅ No |
116
- | `pbjs-unifiedid_cst` | stackoverflow.com | unknown | 2 months | ✅ No |
117
- | `_cc_dc` | .crwdcntrl.net | unknown | 9 months | ✅ No |
118
- | `_cc_id` | .crwdcntrl.net | unknown | 9 months | ✅ No |
119
- | `_cc_cc` | .crwdcntrl.net | unknown | 9 months | ✅ No |
120
- | `_cc_aud` | .crwdcntrl.net | unknown | 9 months | ✅ No |
121
- | `panoramaId_expiry` | .stackoverflow.com | unknown | 7 days | ✅ No |
122
- | `_cc_id` | .stackoverflow.com | unknown | 9 months | ✅ No |
123
- | `panoramaId` | .stackoverflow.com | unknown | 7 days | ✅ No |
124
- | `uid` | .criteo.com | advertising | 13 months | ⚠️ Yes |
125
- | `cto_bidid` | .stackoverflow.com | unknown | 13 months | ✅ No |
126
- | `cto_bundle` | .criteo.com | unknown | 13 months | ✅ No |
127
- | `cto_bundle` | .stackoverflow.com | unknown | 13 months | ✅ No |
128
- | `__cflb` | cdn.sstatic.net | unknown | 1 days | ✅ No |
129
- | `__cf_bm` | .sstatic.net | unknown | < 1 day | ✅ No |
130
- | `_cfuvid` | .sstatic.net | unknown | Session | ✅ No |
131
- | `receive-cookie-deprecation` | .3lift.com | unknown | 3 months | ✅ No |
132
- | `DotomiUser` | .dotomi.com | unknown | 13 months | ✅ No |
133
- | `receive-cookie-deprecation` | .dotomi.com | unknown | 13 months | ✅ No |
134
- | `receive-cookie-deprecation` | prebid.media.net | unknown | 6 months | ✅ No |
135
- | `receive-cookie-deprecation` | .casalemedia.com | unknown | 12 months | ✅ No |
136
- | `id5` | .id5-sync.com | unknown | 3 months | ⚠️ Yes |
137
- | `khaos` | .rubiconproject.com | unknown | 12 months | ✅ No |
138
- | `audit` | .rubiconproject.com | unknown | 12 months | ✅ No |
139
- | `IDE` | .doubleclick.net | advertising | 13 months | ⚠️ Yes |
140
- | `APC` | .doubleclick.net | unknown | 6 months | ⚠️ Yes |
141
- | `flashtalkingad1` | .flashtalking.com | unknown | 13 months | ✅ No |
142
- | `_D9J` | .flashtalking.com | unknown | 12 months | ⚠️ Yes |
143
-
144
- ## 6. Network Requests — Detected Trackers
145
-
146
- ### Before interaction (7 tracker(s))
147
-
148
- | Tracker | Category | URL | Type |
149
- | ------------------ | ----------- | -------------------------------------------------------------- | ------ |
150
- | Google Tag Manager | analytics | `https://www.googletagmanager.com/gtag/js?id=G-WCZ03SZFCQ` | script |
151
- | Google AdSense | advertising | `https://pagead2.googlesyndication.com/tag/js/gpt.js` | script |
152
- | Google DoubleClick | advertising | `https://securepubads.g.doubleclick.net/tag/js/gpt.js` | script |
153
- | Google AdSense | advertising | `https://pagead2.googlesyndication.com/pagead/managed/js/g...` | script |
154
- | Google Analytics | analytics | `https://region1.google-analytics.com/g/collect?v=2&tid=G-...` | fetch |
155
- | Google AdSense | advertising | `https://pagead2.googlesyndication.com/pagead/managed/dict...` | other |
156
- | Tracking Pixel | pixel | `https://accounts.google.com/gsi/log?client_id=71776232868...` | xhr |
157
-
158
- ### After acceptance (68 tracker(s))
159
-
160
- | Tracker | Category | URL | Type |
161
- | ------------------ | ----------- | -------------------------------------------------------------- | -------- |
162
- | Google Tag Manager | analytics | `https://www.googletagmanager.com/gtag/js?id=G-WCZ03SZFCQ` | script |
163
- | Google AdSense | advertising | `https://pagead2.googlesyndication.com/tag/js/gpt.js` | script |
164
- | Google AdSense | advertising | `https://pagead2.googlesyndication.com/pagead/managed/js/g...` | script |
165
- | Google DoubleClick | advertising | `https://securepubads.g.doubleclick.net/tag/js/gpt.js` | script |
166
- | Google AdSense | advertising | `https://pagead2.googlesyndication.com/pagead/managed/dict...` | other |
167
- | Google Analytics | analytics | `https://region1.google-analytics.com/g/collect?v=2&tid=G-...` | fetch |
168
- | Tracking Pixel | pixel | `https://accounts.google.com/gsi/log?client_id=71776232868...` | xhr |
169
- | Google Analytics | analytics | `https://region1.google-analytics.com/g/collect?v=2&tid=G-...` | fetch |
170
- | Google Analytics | analytics | `https://region1.analytics.google.com/g/collect?v=2&tid=G-...` | fetch |
171
- | Google DoubleClick | advertising | `https://stats.g.doubleclick.net/g/collect?v=2&tid=G-WCZ03...` | ping |
172
- | Criteo | advertising | `https://static.criteo.net/js/ld/publishertag.ids.js` | script |
173
- | Google AdSense | advertising | `https://pagead2.googlesyndication.com/gampad/ads?pvsid=67...` | fetch |
174
- | Google AdSense | advertising | `https://d888e23a329526dc9ce3f0b7b6578905.safeframe.google...` | document |
175
- | Google AdSense | advertising | `https://pagead2.googlesyndication.com/gampad/ads?pvsid=67...` | fetch |
176
- | Google AdSense | advertising | `https://d888e23a329526dc9ce3f0b7b6578905.safeframe.google...` | document |
177
- | Google AdSense | advertising | `https://d888e23a329526dc9ce3f0b7b6578905.safeframe.google...` | document |
178
- | Google AdSense | advertising | `https://pagead2.googlesyndication.com/bg/xBXdrLeq7aQZSZ_B...` | script |
179
- | Google AdSense | advertising | `https://tpc.googlesyndication.com/safeframe/1-0-45/js/ext.js` | script |
180
- | Google AdSense | advertising | `https://pagead2.googlesyndication.com/pagead/js/r20260218...` | script |
181
- | Google AdSense | advertising | `https://tpc.googlesyndication.com/simgad/1623626705182823...` | image |
182
-
183
- _... and 48 additional request(s)._
184
-
185
- ## 7. Recommendations
186
-
187
- 1. **Add a "Reject all" button** at the first layer of the modal, requiring no more clicks than "Accept all" (CNIL 2022).
188
-
189
- 1. **Do not set any non-essential cookie before consent.** Gate the initialisation of third-party scripts on acceptance.
190
-
191
- 1. **Complete the modal information**: purposes, identity of sub-processors, retention period, right to withdraw.
192
-
193
- 1. **Remove or block non-essential cookies** after rejection, and verify consent handling server-side.
194
-
195
- ## Scan Errors and Warnings
196
-
197
- - ⚠️ No reject button found — could not test rejection flow
198
-
199
- ## Legal References
200
-
201
- - **RGPD Art. 7** — Conditions for consent
202
- - **RGPD Recital 32** — Consent must result from an unambiguous positive action
203
- - **ePrivacy Directive 2002/58/EC** — Consent requirement for non-essential cookies
204
- - **CEPD Guidelines 05/2020** — Consent under the RGPD
205
- - **CEPD Guidelines 03/2022** — Dark patterns on platforms
206
- - **CNIL Recommendation 2022** — Rejection must be as easy as acceptance (same number of clicks)
@@ -1,44 +0,0 @@
1
- # GDPR Compliance Checklist — www.afp.com
2
-
3
- > **Scan date:** 22/02/2026, 19:36:58
4
- > **Scanned URL:** https://www.afp.com/
5
- > **Global score:** 47/100 — Grade **D**
6
-
7
- **11 rule(s) compliant** · **3 non-compliant** · **3 warning(s)**
8
-
9
- ## Consent
10
-
11
- | Rule | Reference | Status | Detail |
12
- | ---------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ | -------------------------------------- |
13
- | Consent modal detected | [GDPR Art. 7](https://gdpr-info.eu/art-7-gdpr/) · [ePrivacy Dir. Art. 5(3)](https://eur-lex.europa.eu/legal-content/EN/TXT/?uri=CELEX%3A32002L0058) | ✅ Compliant | Detected (`#onetrust-banner-sdk`) |
14
- | No pre-ticked checkboxes | [GDPR Recital 32](https://gdpr-info.eu/recitals/no-32/) | ✅ Compliant | No pre-ticked checkbox detected |
15
- | Accept button label is unambiguous | [GDPR Art. 4(11)](https://gdpr-info.eu/art-4-gdpr/) | ✅ Compliant | Clear label: "Continuer sans accepter" |
16
-
17
- ## Easy refusal
18
-
19
- | Rule | Reference | Status | Detail |
20
- | ------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------- | ------------------------------- |
21
- | Reject button present at first layer | [CNIL Recommendation 2022](https://www.cnil.fr/fr/cookies-et-autres-traceurs/regles/cookies) | ❌ Non-compliant | No Reject button at first layer |
22
- | Rejecting requires no more clicks than accepting | [CNIL Recommendation 2022](https://www.cnil.fr/fr/cookies-et-autres-traceurs/regles/cookies) | ✅ Compliant | Cannot verify (missing buttons) |
23
- | Size symmetry between Accept and Reject | [EDPB Guidelines 03/2022](https://www.edpb.europa.eu/system/files/2022-03/edpb_03-2022_guidelines_on_dark_patterns_in_social_media_platform_interfaces_en.pdf) | ✅ Compliant | Button sizes are comparable |
24
- | Font symmetry between Accept and Reject | [EDPB Guidelines 03/2022](https://www.edpb.europa.eu/system/files/2022-03/edpb_03-2022_guidelines_on_dark_patterns_in_social_media_platform_interfaces_en.pdf) | ✅ Compliant | Font sizes are comparable |
25
-
26
- ## Transparency
27
-
28
- | Rule | Reference | Status | Detail |
29
- | ------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------- | ------------ | ----------------------------------------------------- |
30
- | Granular controls available | [EDPB Guidelines 05/2020](https://edpb.europa.eu/our-work-tools/our-documents/guidelines/guidelines-052020-consent-under-regulation-2016679_en) | ✅ Compliant | 0 checkbox(es) or preferences panel detected |
31
- | Processing purposes mentioned | [GDPR Art. 13-14](https://gdpr-info.eu/art-13-gdpr/) | ✅ Compliant | Mention found in the modal text |
32
- | Sub-processors / third parties mentioned | [GDPR Art. 13-14](https://gdpr-info.eu/art-13-gdpr/) | ⚠️ Warning | Information absent from the modal text |
33
- | Retention period mentioned | [GDPR Art. 13(2)(a)](https://gdpr-info.eu/art-13-gdpr/) | ✅ Compliant | Mention found in the modal text |
34
- | Right to withdraw consent mentioned | [GDPR Art. 7(3)](https://gdpr-info.eu/art-7-gdpr/) | ⚠️ Warning | Information absent from the modal text |
35
- | Privacy policy link present in the consent modal | [GDPR Art. 13](https://gdpr-info.eu/art-13-gdpr/) | ⚠️ Warning | No privacy policy link found inside the consent modal |
36
- | Privacy policy accessible from the main page | [GDPR Art. 13](https://gdpr-info.eu/art-13-gdpr/) | ✅ Compliant | Link found: https://www.afp.com/fr/mentions-legales |
37
-
38
- ## Cookie behavior
39
-
40
- | Rule | Reference | Status | Detail |
41
- | --------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------- | ----------------------------------------------------------------------------------- |
42
- | No non-essential cookie before consent | [GDPR Art. 7](https://gdpr-info.eu/art-7-gdpr/) · [ePrivacy Dir. Art. 5(3)](https://eur-lex.europa.eu/legal-content/EN/TXT/?uri=CELEX%3A32002L0058) | ❌ Non-compliant | 3 illegal cookie(s): `YSC` (social), `bcookie` (advertising), `li_gc` (advertising) |
43
- | Non-essential cookies removed after rejection | [GDPR Art. 7](https://gdpr-info.eu/art-7-gdpr/) · [CNIL Recommendation 2022](https://www.cnil.fr/fr/cookies-et-autres-traceurs/regles/cookies) | ✅ Compliant | No non-essential cookie persisting after rejection |
44
- | No network tracker before consent | [GDPR Art. 7](https://gdpr-info.eu/art-7-gdpr/) · [ePrivacy Dir. Art. 5(3)](https://eur-lex.europa.eu/legal-content/EN/TXT/?uri=CELEX%3A32002L0058) | ❌ Non-compliant | 13 tracker(s): Google Tag Manager, LinkedIn Insight Tag, Microsoft Clarity |
@@ -1,42 +0,0 @@
1
- # Cookie Inventory — www.afp.com
2
-
3
- > **Scan date:** 22/02/2026, 19:36:58
4
- > **Scanned URL:** https://www.afp.com/
5
- > **Unique cookies detected:** 19
6
-
7
- ## Instructions
8
-
9
- This table lists all cookies detected during the scan, across all phases.
10
- The **Description / Purpose** column is to be filled in by the DPO or technical owner.
11
-
12
- - **Before consent** — cookie present from page load, before any interaction
13
- - **After acceptance** — cookie set or persisting after clicking "Accept all"
14
- - **After rejection** — cookie present after clicking "Reject all"
15
-
16
- ## Cookie table
17
-
18
- | Cookie | Domain | Category | Phases | Expiry | Consent required | Description / Purpose |
19
- | --------------------------------------------------- | ------------- | ----------- | -------------------------------- | --------- | ---------------- | --------------------- |
20
- | `bcookie` | .linkedin.com | Advertising | before consent, after acceptance | 12 months | ⚠️ Yes | <!-- fill in --> |
21
- | `li_gc` | .linkedin.com | Advertising | before consent, after acceptance | 6 months | ⚠️ Yes | <!-- fill in --> |
22
- | `YSC` | .youtube.com | Social | before consent, after acceptance | Session | ⚠️ Yes | <!-- fill in --> |
23
- | `__cf_bm` | .page.afp.com | Unknown | before consent, after acceptance | < 1 day | ✅ No | <!-- fill in --> |
24
- | `__Secure-ROLLOUT_TOKEN` | .youtube.com | Unknown | before consent, after acceptance | 6 months | ✅ No | <!-- fill in --> |
25
- | `__Secure-YNID` | .youtube.com | Unknown | before consent, after acceptance | 6 months | ✅ No | <!-- fill in --> |
26
- | `_gcl_au` | .afp.com | Unknown | before consent, after acceptance | 3 months | ✅ No | <!-- fill in --> |
27
- | `_mkto_trk` | .afp.com | Unknown | before consent, after acceptance | 13 months | ✅ No | <!-- fill in --> |
28
- | `_pcid` | .afp.com | Unknown | before consent, after acceptance | 13 months | ✅ No | <!-- fill in --> |
29
- | `_pctx` | .afp.com | Unknown | before consent, after acceptance | 13 months | ✅ No | <!-- fill in --> |
30
- | `_pprv` | .afp.com | Unknown | before consent, after acceptance | 13 months | ✅ No | <!-- fill in --> |
31
- | `AKA_A2` | .afp.com | Unknown | after acceptance | < 1 day | ✅ No | <!-- fill in --> |
32
- | `BIGipServer~VS65000-N117~lon08web-nginx-app_https` | page.afp.com | Unknown | before consent, after acceptance | Session | ✅ No | <!-- fill in --> |
33
- | `gtmreferers` | www.afp.com | Unknown | before consent, after acceptance | 3 months | ✅ No | <!-- fill in --> |
34
- | `lidc` | .linkedin.com | Unknown | before consent, after acceptance | 1 days | ✅ No | <!-- fill in --> |
35
- | `OptanonAlertBoxClosed` | .www.afp.com | Unknown | after acceptance | 12 months | ✅ No | <!-- fill in --> |
36
- | `OptanonConsent` | .www.afp.com | Unknown | before consent, after acceptance | 12 months | ✅ No | <!-- fill in --> |
37
- | `VISITOR_INFO1_LIVE` | .youtube.com | Unknown | before consent, after acceptance | 6 months | ✅ No | <!-- fill in --> |
38
- | `VISITOR_PRIVACY_METADATA` | .youtube.com | Unknown | before consent, after acceptance | 6 months | ✅ No | <!-- fill in --> |
39
-
40
- ---
41
-
42
- _Automatically generated by gdpr-cookie-scanner. Categories marked "Unknown" could not be identified automatically and should be verified manually._
@@ -1,202 +0,0 @@
1
- # GDPR Compliance Report — www.afp.com
2
-
3
- > **Scan date:** 22/02/2026, 19:36:58
4
- > **Scanned URL:** https://www.afp.com/
5
- > **Scan duration:** 14.0s
6
- > **Tool:** gdpr-cookie-scanner v0.1.0
7
-
8
- ## Global Compliance Score
9
-
10
- ### 🔴 47/100 — Grade D
11
-
12
- | Criterion | Score | Progress | Status |
13
- | ---------------- | ---------- | ---------- | ------ |
14
- | Consent validity | 20/25 | ████████░░ | ✅ |
15
- | Easy refusal | 10/25 | ████░░░░░░ | ❌ |
16
- | Transparency | 14/25 | ██████░░░░ | ⚠️ |
17
- | Cookie behavior | 3/25 | █░░░░░░░░░ | ❌ |
18
- | **TOTAL** | **47/100** | | **D** |
19
-
20
- ## Executive Summary
21
-
22
- ✅ Consent modal detected (`#onetrust-banner-sdk`).
23
- ❌ **3 non-essential cookie(s)** set before any interaction (RGPD violation).
24
- ❌ **3 non-essential cookie(s)** persisting after rejection (RGPD violation).
25
- ❌ **13 tracker request(s)** fired before consent.
26
-
27
- **3 critical issue(s)** and **3 warning(s)** identified.
28
-
29
- ## 1. Consent Modal
30
-
31
- **CSS selector:** `#onetrust-banner-sdk`
32
- **Granular controls:** ✅ Yes
33
- **Layer count:** 2
34
- **Privacy policy link:** ⚠️ Not found in the modal
35
-
36
- ### Detected buttons
37
-
38
- | Button | Text | Visible | Font size | Contrast ratio |
39
- | -------------- | -------------------------- | ------- | --------- | -------------- |
40
- | ⚙️ Preferences | Paramètres des cookies | ✅ | 13.008px | 5.2:1 |
41
- | ❓ Unknown | Autoriser tous les cookies | ✅ | 13.008px | 5.2:1 |
42
- | 🟢 Accept | Continuer sans accepter | ✅ | 11.04px | 3.83:1 |
43
-
44
- ### Screenshot
45
-
46
- ![Consent modal](modal-initial.png)
47
-
48
- ### Modal text excerpt
49
-
50
- > En cliquant sur « Autoriser tous les cookies », vous acceptez le stockage de cookies sur votre appareil pour améliorer la navigation sur le site, analyser son utilisation et contribuer à nos efforts de marketing. Paramètres des cookies Autoriser tous les cookiesContinuer sans accepter
51
-
52
- ## 2. Dark Patterns and Detected Issues
53
-
54
- ### ❌ Critical issues
55
-
56
- **No reject button on first layer**
57
-
58
- > CNIL (2022) requires reject to require no more clicks than accept
59
-
60
- **3 non-essential cookie(s) deposited before any interaction**
61
-
62
- > YSC (social), bcookie (advertising), li_gc (advertising)
63
-
64
- **13 tracker request(s) fired before any consent**
65
-
66
- > Google Tag Manager, LinkedIn Insight Tag, Microsoft Clarity, Tracking Pixel
67
-
68
- ### ⚠️ Warnings
69
-
70
- **Missing required information: "third-parties"**
71
-
72
- > The consent text does not mention third-parties
73
-
74
- **Missing required information: "withdrawal"**
75
-
76
- > The consent text does not mention withdrawal
77
-
78
- **No privacy policy link found in the consent modal**
79
-
80
- > GDPR Art. 13 requires the privacy policy to be accessible from the consent interface
81
-
82
- ## 3. Cookies Set Before Any Interaction
83
-
84
- | Name | Domain | Category | Expiry | Consent required |
85
- | --------------------------------------------------- | ------------- | ----------- | --------- | ---------------- |
86
- | `__Secure-YNID` | .youtube.com | unknown | 6 months | ✅ No |
87
- | `YSC` | .youtube.com | social | Session | ⚠️ Yes |
88
- | `__Secure-ROLLOUT_TOKEN` | .youtube.com | unknown | 6 months | ✅ No |
89
- | `VISITOR_INFO1_LIVE` | .youtube.com | unknown | 6 months | ✅ No |
90
- | `VISITOR_PRIVACY_METADATA` | .youtube.com | unknown | 6 months | ✅ No |
91
- | `_mkto_trk` | .afp.com | unknown | 13 months | ✅ No |
92
- | `_gcl_au` | .afp.com | unknown | 3 months | ✅ No |
93
- | `gtmreferers` | www.afp.com | unknown | 3 months | ✅ No |
94
- | `_pcid` | .afp.com | unknown | 13 months | ✅ No |
95
- | `_pctx` | .afp.com | unknown | 13 months | ✅ No |
96
- | `_pprv` | .afp.com | unknown | 13 months | ✅ No |
97
- | `OptanonConsent` | .www.afp.com | unknown | 12 months | ✅ No |
98
- | `__cf_bm` | .page.afp.com | unknown | < 1 day | ✅ No |
99
- | `bcookie` | .linkedin.com | advertising | 12 months | ⚠️ Yes |
100
- | `li_gc` | .linkedin.com | advertising | 6 months | ⚠️ Yes |
101
- | `lidc` | .linkedin.com | unknown | 1 days | ✅ No |
102
- | `BIGipServer~VS65000-N117~lon08web-nginx-app_https` | page.afp.com | unknown | Session | ✅ No |
103
-
104
- ## 4. Cookies After Consent Rejection
105
-
106
- ✅ No non-essential cookie detected after rejection.
107
-
108
- _No cookies detected._
109
-
110
- ## 5. Cookies After Consent Acceptance
111
-
112
- | Name | Domain | Category | Expiry | Consent required |
113
- | --------------------------------------------------- | ------------- | ----------- | --------- | ---------------- |
114
- | `AKA_A2` | .afp.com | unknown | < 1 day | ✅ No |
115
- | `_mkto_trk` | .afp.com | unknown | 13 months | ✅ No |
116
- | `__Secure-YNID` | .youtube.com | unknown | 6 months | ✅ No |
117
- | `YSC` | .youtube.com | social | Session | ⚠️ Yes |
118
- | `VISITOR_INFO1_LIVE` | .youtube.com | unknown | 6 months | ✅ No |
119
- | `VISITOR_PRIVACY_METADATA` | .youtube.com | unknown | 6 months | ✅ No |
120
- | `__Secure-ROLLOUT_TOKEN` | .youtube.com | unknown | 6 months | ✅ No |
121
- | `_gcl_au` | .afp.com | unknown | 3 months | ✅ No |
122
- | `gtmreferers` | www.afp.com | unknown | 3 months | ✅ No |
123
- | `__cf_bm` | .page.afp.com | unknown | < 1 day | ✅ No |
124
- | `_pcid` | .afp.com | unknown | 13 months | ✅ No |
125
- | `_pctx` | .afp.com | unknown | 13 months | ✅ No |
126
- | `bcookie` | .linkedin.com | advertising | 12 months | ⚠️ Yes |
127
- | `li_gc` | .linkedin.com | advertising | 6 months | ⚠️ Yes |
128
- | `lidc` | .linkedin.com | unknown | 1 days | ✅ No |
129
- | `BIGipServer~VS65000-N117~lon08web-nginx-app_https` | page.afp.com | unknown | Session | ✅ No |
130
- | `OptanonAlertBoxClosed` | .www.afp.com | unknown | 12 months | ✅ No |
131
- | `OptanonConsent` | .www.afp.com | unknown | 12 months | ✅ No |
132
- | `_pprv` | .afp.com | unknown | 13 months | ✅ No |
133
-
134
- ## 6. Network Requests — Detected Trackers
135
-
136
- ### Before interaction (13 tracker(s))
137
-
138
- | Tracker | Category | URL | Type |
139
- | -------------------- | ----------- | -------------------------------------------------------------- | -------- |
140
- | Google Tag Manager | analytics | `https://www.googletagmanager.com/gtm.js?id=GTM-T4C5DKK` | script |
141
- | Google Tag Manager | analytics | `https://www.googletagmanager.com/gtag/js?id=AW-1090164081...` | script |
142
- | LinkedIn Insight Tag | advertising | `https://snap.licdn.com/li.lms-analytics/insight.min.js` | script |
143
- | Microsoft Clarity | analytics | `https://www.clarity.ms/tag/t3we3mu2lf?ref=gtm` | script |
144
- | Tracking Pixel | pixel | `https://www.google.com/ccm/collect?frm=0&en=page_view&dl=...` | fetch |
145
- | Google Tag Manager | analytics | `https://www.googletagmanager.com/static/service_worker/62...` | document |
146
- | Tracking Pixel | pixel | `https://www.google.com/ccm/collect?frm=0&en=page_view&dl=...` | fetch |
147
- | Tracking Pixel | pixel | `https://kxgqdwd.pa-cd.com/event?s=628508&idclient=mly3a95...` | ping |
148
- | Tracking Pixel | pixel | `https://px.ads.linkedin.com/collect?v=2&fmt=js&pid=347975...` | image |
149
- | Microsoft Clarity | analytics | `https://scripts.clarity.ms/0.8.54/clarity.js` | script |
150
- | Microsoft Clarity | analytics | `https://y.clarity.ms/collect` | xhr |
151
- | Tracking Pixel | pixel | `https://px4.ads.linkedin.com/collect?v=2&fmt=js&pid=34797...` | image |
152
- | Microsoft Clarity | analytics | `https://y.clarity.ms/collect` | xhr |
153
-
154
- ### After acceptance (26 tracker(s))
155
-
156
- | Tracker | Category | URL | Type |
157
- | -------------------- | ----------- | -------------------------------------------------------------- | -------- |
158
- | Google Tag Manager | analytics | `https://www.googletagmanager.com/gtm.js?id=GTM-T4C5DKK` | script |
159
- | Google Tag Manager | analytics | `https://www.googletagmanager.com/gtag/js?id=AW-1090164081...` | script |
160
- | LinkedIn Insight Tag | advertising | `https://snap.licdn.com/li.lms-analytics/insight.min.js` | script |
161
- | Microsoft Clarity | analytics | `https://www.clarity.ms/tag/t3we3mu2lf?ref=gtm` | script |
162
- | Google Tag Manager | analytics | `https://www.googletagmanager.com/a?id=GTM-T4C5DKK&v=3&t=t...` | image |
163
- | Google Tag Manager | analytics | `https://www.googletagmanager.com/a?id=GTM-T4C5DKK&v=3&t=t...` | image |
164
- | Tracking Pixel | pixel | `https://www.google.com/ccm/collect?frm=0&en=page_view&dl=...` | fetch |
165
- | Google Tag Manager | analytics | `https://www.googletagmanager.com/a?id=GTM-T4C5DKK&v=3&t=t...` | image |
166
- | Google Tag Manager | analytics | `https://www.googletagmanager.com/a?id=GTM-T4C5DKK&v=3&t=t...` | image |
167
- | Google Tag Manager | analytics | `https://www.googletagmanager.com/a?id=GTM-T4C5DKK&v=3&t=t...` | image |
168
- | Google Tag Manager | analytics | `https://www.googletagmanager.com/static/service_worker/62...` | document |
169
- | Tracking Pixel | pixel | `https://www.google.com/ccm/collect?frm=0&en=page_view&dl=...` | fetch |
170
- | Google Tag Manager | analytics | `https://www.googletagmanager.com/a?ctid=GTM-T4C5DKK&t=s&s...` | image |
171
- | Tracking Pixel | pixel | `https://kxgqdwd.pa-cd.com/event?s=628508&idclient=mly3ad9...` | ping |
172
- | Tracking Pixel | pixel | `https://px.ads.linkedin.com/collect?v=2&fmt=js&pid=347975...` | image |
173
- | Microsoft Clarity | analytics | `https://scripts.clarity.ms/0.8.54/clarity.js` | script |
174
- | Microsoft Clarity | analytics | `https://y.clarity.ms/collect` | xhr |
175
- | Tracking Pixel | pixel | `https://px4.ads.linkedin.com/collect?v=2&fmt=js&pid=34797...` | image |
176
- | Google Tag Manager | analytics | `https://www.googletagmanager.com/a?id=GTM-T4C5DKK&v=3&t=t...` | image |
177
- | Microsoft Clarity | analytics | `https://y.clarity.ms/collect` | xhr |
178
-
179
- _... and 6 additional request(s)._
180
-
181
- ## 7. Recommendations
182
-
183
- 1. **Add a "Reject all" button** at the first layer of the modal, requiring no more clicks than "Accept all" (CNIL 2022).
184
-
185
- 1. **Do not set any non-essential cookie before consent.** Gate the initialisation of third-party scripts on acceptance.
186
-
187
- 1. **Complete the modal information**: purposes, identity of sub-processors, retention period, right to withdraw.
188
-
189
- 1. **Remove or block non-essential cookies** after rejection, and verify consent handling server-side.
190
-
191
- ## Scan Errors and Warnings
192
-
193
- - ⚠️ No reject button found — could not test rejection flow
194
-
195
- ## Legal References
196
-
197
- - **RGPD Art. 7** — Conditions for consent
198
- - **RGPD Recital 32** — Consent must result from an unambiguous positive action
199
- - **ePrivacy Directive 2002/58/EC** — Consent requirement for non-essential cookies
200
- - **CEPD Guidelines 05/2020** — Consent under the RGPD
201
- - **CEPD Guidelines 03/2022** — Dark patterns on platforms
202
- - **CNIL Recommendation 2022** — Rejection must be as easy as acceptance (same number of clicks)
File without changes