-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathgdpr.html
More file actions
312 lines (289 loc) · 18.7 KB
/
gdpr.html
File metadata and controls
312 lines (289 loc) · 18.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>GDPR Compliance Checklist for Websites — Trackers, Consent, Privacy Policies | Gridwork</title>
<meta name="description" content="GDPR compliance checklist for websites. Check your trackers, cookie consent, privacy policy, and data collection against GDPR requirements. Free scanner.">
<meta property="og:title" content="GDPR Compliance Checklist for Websites">
<meta property="og:description" content="Check your website's GDPR compliance: trackers, consent banners, privacy policies.">
<meta property="og:type" content="website">
<meta property="og:url" content="https://thegridwork.space/gdpr.html">
<meta name="twitter:card" content="summary_large_image">
<link rel="canonical" href="https://thegridwork.space/gdpr.html">
<link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'><rect width='32' height='32' rx='6' fill='%2308080f'/><circle cx='8' cy='8' r='2' fill='%2300d4aa'/><circle cx='16' cy='8' r='2' fill='%2300d4aa'/><circle cx='24' cy='8' r='2' fill='%2300d4aa'/><circle cx='8' cy='16' r='2' fill='%2300d4aa'/><circle cx='16' cy='16' r='2.5' fill='%2300d4aa'/><circle cx='24' cy='16' r='2' fill='%2300d4aa'/><circle cx='8' cy='24' r='2' fill='%2300d4aa'/><circle cx='16' cy='24' r='2' fill='%2300d4aa'/><circle cx='24' cy='24' r='2' fill='%2300d4aa'/><line x1='8' y1='8' x2='16' y2='16' stroke='%2300d4aa' stroke-width='0.8' opacity='0.4'/><line x1='24' y1='8' x2='16' y2='16' stroke='%2300d4aa' stroke-width='0.8' opacity='0.4'/><line x1='8' y1='24' x2='16' y2='16' stroke='%2300d4aa' stroke-width='0.8' opacity='0.4'/><line x1='24' y1='24' x2='16' y2='16' stroke='%2300d4aa' stroke-width='0.8' opacity='0.4'/></svg>">
<script type="application/ld+json">
[
{
"@context": "https://schema.org",
"@type": "WebPage",
"name": "GDPR Compliance Checklist for Websites",
"description": "Check your website's GDPR compliance: trackers, consent banners, privacy policies, and data collection practices.",
"url": "https://thegridwork.space/gdpr.html",
"dateModified": "2026-04-21"
},
{
"@context": "https://schema.org",
"@type": "FAQPage",
"mainEntity": [
{
"@type": "Question",
"name": "Does GDPR apply to my website?",
"acceptedAnswer": {
"@type": "Answer",
"text": "GDPR applies to any website that collects, processes, or stores personal data from EU residents — regardless of where the website operator is based. Personal data includes IP addresses, names, email addresses, cookies, and any other information that can identify an individual directly or indirectly."
}
},
{
"@type": "Question",
"name": "What is required for GDPR-compliant cookie consent?",
"acceptedAnswer": {
"@type": "Answer",
"text": "A GDPR-compliant consent banner must: appear before any non-essential cookies are set; offer granular category choices; make 'Reject All' as prominent as 'Accept All'; use no pre-checked boxes; and allow users to withdraw consent at any time as easily as they gave it. Cookie walls that block access without consent are prohibited."
}
},
{
"@type": "Question",
"name": "What are the GDPR fines for websites?",
"acceptedAnswer": {
"@type": "Answer",
"text": "GDPR fines reach up to EUR 20 million or 4% of global annual turnover for serious violations (whichever is higher). Less severe violations carry fines up to EUR 10 million or 2% of turnover. Over 2,800 fines totalling EUR 7.1 billion have been issued since 2018. Google Analytics alone has been the subject of enforcement actions in multiple EU member states."
}
},
{
"@type": "Question",
"name": "Is Google Analytics GDPR compliant?",
"acceptedAnswer": {
"@type": "Answer",
"text": "Standard Google Analytics configurations have been ruled non-compliant by multiple EU data protection authorities (Austria, France, Italy, Netherlands) due to data transfers to the United States. Using Google Analytics without appropriate safeguards — such as IP anonymization, server-side proxying, or switching to a privacy-first alternative like Plausible or Fathom — carries significant GDPR risk."
}
},
{
"@type": "Question",
"name": "How do I scan my website for GDPR compliance issues?",
"acceptedAnswer": {
"@type": "Answer",
"text": "The Gridwork Privacy Scanner (npx gridwork-privacy) detects 30+ third-party trackers, analyzes your consent banner, checks for scripts loaded before consent, and reviews your privacy policy for required disclosures. Run it against any URL to get a compliance report in seconds."
}
}
]
}
]
</script>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600;700;800&display=swap" rel="stylesheet">
<style>
*, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; }
:root {
--void: #08080f; --surface: #0e0e18; --surface-2: #141422;
--border: #1c1c30; --border-light: #24243a;
--text: #e2e2ec; --text-2: #9494a8; --text-3: #6a6a80;
--teal: #00d4aa; --teal-dim: #00a88a; --teal-deep: #007a64;
--teal-glow: rgba(0, 212, 170, 0.08);
--warn: #ffbd2e; --danger: #ff6b6b;
--mono: 'JetBrains Mono', ui-monospace, 'SF Mono', monospace;
--radius: 12px; --radius-sm: 8px;
}
html { font-size: 16px; -webkit-font-smoothing: antialiased; }
body { font-family: var(--mono); background: var(--void); color: var(--text); min-height: 100vh; }
nav { padding: 1.5rem 2rem; display: flex; align-items: center; justify-content: space-between; max-width: 960px; margin: 0 auto; }
nav a { color: var(--text-3); text-decoration: none; font-size: 0.8125rem; font-weight: 600; }
nav a:hover { color: var(--teal); }
.nav-brand { color: var(--text); font-weight: 800; font-size: 0.9375rem; letter-spacing: -0.03em; }
main { max-width: 960px; margin: 0 auto; padding: 2rem 2rem 6rem; }
.page-hero { padding: 3rem 0 2rem; }
.page-label { font-size: 0.75rem; font-weight: 600; color: var(--teal); letter-spacing: 0.2em; text-transform: uppercase; margin-bottom: 1rem; }
.page-title { font-size: clamp(1.75rem, 4vw, 2.5rem); font-weight: 800; letter-spacing: -0.04em; margin-bottom: 1rem; line-height: 1.1; }
.page-desc { font-size: 1rem; color: var(--text-2); line-height: 1.6; max-width: 600px; margin-bottom: 2rem; }
.btn { display: inline-flex; align-items: center; gap: 0.5rem; padding: 0.75rem 1.75rem; border-radius: var(--radius-sm); font-family: var(--mono); font-size: 0.875rem; font-weight: 600; text-decoration: none; transition: all 0.25s; cursor: pointer; border: none; }
.btn-primary { background: var(--teal); color: var(--void); }
.btn-primary:hover { background: var(--teal-dim); box-shadow: 0 0 40px rgba(0, 212, 170, 0.25); }
.btn-ghost { background: transparent; color: var(--text-2); border: 1px solid var(--border-light); }
.btn-ghost:hover { color: var(--text); border-color: var(--text-3); }
section { padding: 2.5rem 0; }
.section-title { font-size: clamp(1.25rem, 2.5vw, 1.5rem); font-weight: 800; letter-spacing: -0.03em; margin-bottom: 1rem; }
.checklist { display: grid; gap: 1px; background: var(--border); border-radius: var(--radius); overflow: hidden; margin-bottom: 2rem; }
.check-item { background: var(--surface); padding: 1.25rem 1.5rem; display: flex; align-items: flex-start; gap: 1rem; }
.check-num { font-size: 0.75rem; font-weight: 700; color: var(--teal); min-width: 24px; padding-top: 0.125rem; }
.check-text { font-size: 0.875rem; color: var(--text-2); line-height: 1.5; }
.check-text strong { color: var(--text); }
.check-text .ref { color: var(--text-3); font-size: 0.75rem; }
.fine-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 1px; background: var(--border); border-radius: var(--radius); overflow: hidden; margin-bottom: 2rem; }
.fine-item { background: var(--surface); padding: 1.5rem; }
.fine-value { font-size: 1.5rem; font-weight: 800; color: var(--danger); margin-bottom: 0.25rem; }
.fine-label { font-size: 0.6875rem; color: var(--text-3); letter-spacing: 0.05em; }
.tracker-table { display: grid; gap: 1px; background: var(--border); border-radius: var(--radius); overflow: hidden; margin-bottom: 2rem; }
.tracker-row { background: var(--surface); padding: 1rem 1.5rem; display: grid; grid-template-columns: 1fr 1fr auto; gap: 1rem; align-items: center; font-size: 0.8125rem; }
.tracker-row.header { font-weight: 700; color: var(--text-3); font-size: 0.6875rem; letter-spacing: 0.1em; text-transform: uppercase; }
.tracker-name { color: var(--text); font-weight: 600; }
.tracker-concern { color: var(--text-2); }
.risk-high { color: var(--danger); font-weight: 600; font-size: 0.75rem; }
.risk-med { color: var(--warn); font-weight: 600; font-size: 0.75rem; }
.risk-low { color: var(--teal); font-weight: 600; font-size: 0.75rem; }
.install-block { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); padding: 2.5rem; text-align: center; margin: 3rem 0; }
.install-block h3 { font-size: 1.25rem; font-weight: 800; margin-bottom: 0.75rem; }
.install-block p { font-size: 0.875rem; color: var(--text-2); margin-bottom: 1.5rem; line-height: 1.5; }
.install-cmd { display: inline-flex; align-items: center; gap: 0.75rem; padding: 0.75rem 1.25rem; background: var(--void); border: 1px solid var(--border); border-radius: var(--radius-sm); font-size: 0.9375rem; color: var(--text); cursor: pointer; transition: border-color 0.2s; margin-bottom: 1rem; }
.install-cmd:hover { border-color: var(--teal-deep); }
.install-cmd .hint { font-size: 0.6875rem; color: var(--text-3); }
footer { padding: 3rem 0; border-top: 1px solid var(--border); display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 1rem; font-size: 0.8125rem; }
footer a { color: var(--text-3); text-decoration: none; }
footer a:hover { color: var(--teal); }
.footer-mark { font-weight: 700; color: var(--text-3); }
.footer-links { display: flex; gap: 1.5rem; }
@media (max-width: 640px) {
main { padding: 1rem 1.25rem 4rem; }
.tracker-row { grid-template-columns: 1fr; gap: 0.25rem; }
.tracker-row.header { display: none; }
footer { flex-direction: column; align-items: flex-start; }
}
</style>
</head>
<body>
<nav>
<a href="/" class="nav-brand">GRIDWORK</a>
<a href="/#products">All products</a>
</nav>
<main>
<div class="page-hero">
<div class="page-label">GDPR Compliance</div>
<h1 class="page-title">Is your website GDPR compliant?</h1>
<p class="page-desc">The General Data Protection Regulation applies to any website that collects data from EU residents. Most sites fail on trackers, consent, or privacy policies. Here's what to check.</p>
<a href="/#try" class="btn btn-primary">Scan your site free</a>
</div>
<div class="fine-grid">
<div class="fine-item">
<div class="fine-value">4%</div>
<div class="fine-label">Max fine (% of global turnover)</div>
</div>
<div class="fine-item">
<div class="fine-value">20M</div>
<div class="fine-label">Max fine (EUR, whichever higher)</div>
</div>
<div class="fine-item">
<div class="fine-value">2,800+</div>
<div class="fine-label">Fines issued since 2018</div>
</div>
<div class="fine-item">
<div class="fine-value">7.1B+</div>
<div class="fine-label">Total fines (EUR)</div>
</div>
</div>
<section>
<h2 class="section-title">Website compliance checklist</h2>
<div class="checklist">
<div class="check-item">
<span class="check-num">01</span>
<span class="check-text"><strong>Cookie consent banner.</strong> Must appear before any non-essential cookies are set. Must offer granular choices. "Accept All" cannot be more prominent than "Reject All." <span class="ref">ePrivacy Directive Art. 5(3)</span></span>
</div>
<div class="check-item">
<span class="check-num">02</span>
<span class="check-text"><strong>Reject option.</strong> Withdrawing consent must be as easy as giving it. A visible "Reject All" or "Only Necessary" button is required at the same prominence level. <span class="ref">GDPR Art. 7(3)</span></span>
</div>
<div class="check-item">
<span class="check-num">03</span>
<span class="check-text"><strong>No pre-checked boxes.</strong> Non-essential cookie categories must be unchecked by default. The CJEU Planet49 ruling explicitly prohibits pre-ticked consent boxes. <span class="ref">CJEU C-673/17</span></span>
</div>
<div class="check-item">
<span class="check-num">04</span>
<span class="check-text"><strong>No cookie walls.</strong> Blocking content access until cookies are accepted undermines freely given consent. Users must be able to access content without consenting to non-essential cookies. <span class="ref">EDPB Guidelines 05/2020</span></span>
</div>
<div class="check-item">
<span class="check-num">05</span>
<span class="check-text"><strong>Scripts blocked until consent.</strong> Analytics, advertising, and social media scripts must not load until the user actively consents. Defer all non-essential scripts. <span class="ref">ePrivacy Directive Art. 5(3)</span></span>
</div>
<div class="check-item">
<span class="check-num">06</span>
<span class="check-text"><strong>Privacy policy.</strong> Must be clearly accessible from every page. Must disclose: what data you collect, why, legal basis, who receives it, retention periods, and user rights. <span class="ref">GDPR Art. 13</span></span>
</div>
<div class="check-item">
<span class="check-num">07</span>
<span class="check-text"><strong>Data subject rights.</strong> Your policy must inform users of their rights: access, rectification, erasure, restriction, portability, and objection. Provide a contact method. <span class="ref">GDPR Art. 15-22</span></span>
</div>
<div class="check-item">
<span class="check-num">08</span>
<span class="check-text"><strong>Third-party disclosures.</strong> List categories of recipients or specific third parties that receive personal data. This includes analytics providers, ad networks, and CDNs. <span class="ref">GDPR Art. 13(1)(e)</span></span>
</div>
<div class="check-item">
<span class="check-num">09</span>
<span class="check-text"><strong>Data retention periods.</strong> Specify how long each category of personal data is retained and the criteria for determining retention. <span class="ref">GDPR Art. 13(2)(a)</span></span>
</div>
<div class="check-item">
<span class="check-num">10</span>
<span class="check-text"><strong>DPO contact.</strong> If you have a Data Protection Officer, provide their contact details. If not required, provide a privacy contact email. <span class="ref">GDPR Art. 13(1)(b)</span></span>
</div>
</div>
</section>
<section>
<h2 class="section-title">Common trackers and their GDPR risk</h2>
<div class="tracker-table">
<div class="tracker-row header">
<span>Tracker</span>
<span>Concern</span>
<span>Risk</span>
</div>
<div class="tracker-row">
<span class="tracker-name">Google Analytics</span>
<span class="tracker-concern">US data transfer. Multiple EU DPA enforcement actions.</span>
<span class="risk-high">High</span>
</div>
<div class="tracker-row">
<span class="tracker-name">Facebook Pixel</span>
<span class="tracker-concern">Cross-site tracking for ad targeting. Multiple fines.</span>
<span class="risk-high">High</span>
</div>
<div class="tracker-row">
<span class="tracker-name">TikTok Pixel</span>
<span class="tracker-concern">Data transfer to China. High regulatory scrutiny.</span>
<span class="risk-high">High</span>
</div>
<div class="tracker-row">
<span class="tracker-name">Hotjar</span>
<span class="tracker-concern">Session recording captures user behavior data.</span>
<span class="risk-med">Medium</span>
</div>
<div class="tracker-row">
<span class="tracker-name">Google Tag Manager</span>
<span class="tracker-concern">Container loads third-party scripts. Each needs consent.</span>
<span class="risk-med">Medium</span>
</div>
<div class="tracker-row">
<span class="tracker-name">Intercom</span>
<span class="tracker-concern">Chat widget tracks user behavior beyond chat.</span>
<span class="risk-med">Medium</span>
</div>
<div class="tracker-row">
<span class="tracker-name">Plausible</span>
<span class="tracker-concern">No cookies, no personal data. Privacy-friendly.</span>
<span class="risk-low">Low</span>
</div>
<div class="tracker-row">
<span class="tracker-name">Fathom</span>
<span class="tracker-concern">No cookies. Generally GDPR-compliant without consent.</span>
<span class="risk-low">Low</span>
</div>
</div>
</section>
<div class="install-block">
<h3>Scan your site for GDPR compliance</h3>
<p>Gridwork Privacy Scanner detects 30+ trackers, analyzes your consent banner, checks your privacy policy, and reviews data collection forms. One command.</p>
<div class="install-cmd" onclick="navigator.clipboard.writeText('npx gridwork-privacy').then(() => { this.querySelector('.hint').textContent = 'copied'; setTimeout(() => this.querySelector('.hint').textContent = 'click to copy', 2000); })">
<code>npx gridwork-privacy</code>
<span class="hint">click to copy</span>
</div>
<br>
<a href="https://github.com/thegridwork/privacy" class="btn btn-ghost" target="_blank" rel="noopener" style="margin-top: 1rem;">View source on GitHub</a>
</div>
<footer>
<a href="/" class="footer-mark">GRIDWORK</a>
<nav class="footer-links">
<a href="/eu-ai-act.html">EU AI Act</a>
<a href="https://github.com/thegridwork" target="_blank">GitHub</a>
<a href="https://www.npmjs.com/search?q=gridwork" target="_blank">npm</a>
<a href="mailto:thegridwork@proton.me">Contact</a>
</nav>
</footer>
</main>
</body>
</html>