Most articles about GDPR compliance for websites stop at the legal surface: “be transparent”, “get consent”, “update your privacy policy”. Useful, but if you’re the developer who actually has to push the commit, you need more than vague principles. You need to know where in the codebase the consent banner lives, how to block scripts before consent, and what headers to set.
This guide is written for developers, by developers. We’ve shipped GDPR-compliant projects at Pixelseed for years, and here is the practical playbook we use in 2026.
What GDPR Actually Requires From a Website (Short Version)
Before touching code, here is the technical translation of the regulation:
- Lawful basis for every piece of personal data you collect (consent, contract, legitimate interest, etc.).
- Prior consent for non-essential cookies and trackers, before they fire.
- Right of access, rectification, deletion, and portability for users.
- Data minimization: only collect what you actually need.
- Security: encryption in transit, sensible storage, breach notification within 72 hours.
- Transparency: a clear privacy policy and a record of processing activities.
Now let’s translate this into actual implementation.

Step 1: Audit What Your Website Actually Collects
Open DevTools, go to the Application tab, and list every cookie, every localStorage entry, and every outbound request. You will be surprised.
Typical sources of personal data on a website
| Source | Data collected | Requires consent? |
|---|---|---|
| Google Analytics / GA4 | IP, client ID, behavior | Yes |
| Meta Pixel / TikTok Pixel | IP, behavior, conversions | Yes |
| Contact / signup forms | Email, name, message | Lawful basis required |
| Session cookies | Auth, cart | No (strictly necessary) |
| Embedded YouTube, Maps, fonts | IP sent to third party | Yes |
| Server logs | IP, user agent | Legitimate interest, document it |
Write the result of your audit in a Record of Processing Activities (RoPA). A simple Markdown file in your repo is fine for small teams.
Step 2: Implement Cookie Consent the Right Way
This is where 80% of websites fail. The rules in 2026 are clear:
- No non-essential script fires before the user gives consent.
- “Reject all” must be as easy as “Accept all” (same number of clicks, same visual weight).
- Pre-ticked boxes are illegal.
- You must be able to withdraw consent as easily as you gave it.
- Consent must be logged with a timestamp.
The wrong way
<!-- Loads GA before consent. Non-compliant. -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-XXXX"></script>
The right way: block until consent
<!-- Default: deny everything -->
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('consent', 'default', {
'ad_storage': 'denied',
'analytics_storage': 'denied',
'ad_user_data': 'denied',
'ad_personalization': 'denied'
});
</script>
<!-- Then, after the user accepts in your CMP -->
<script>
gtag('consent', 'update', {
'analytics_storage': 'granted'
});
</script>
For non-Google scripts, use type="text/plain" with a data attribute, and only swap to text/javascript after consent:
<script type="text/plain" data-category="analytics" src="/tracker.js"></script>
Which consent tool?
- Self-hosted, lightweight: Klaro!, CookieConsent by Orest Bida, or a custom React component (~5 KB).
- SaaS: Axeptio, Cookiebot, Didomi, Iubenda. Useful if you need IAB TCF v2.2 support for ad networks.
Whatever you pick, make sure it stores a consent receipt: timestamp, IP hash, choices made, banner version. You’ll need it if a Data Protection Authority asks.

Step 3: Fix the Backend, Not Just the Banner
A consent banner alone won’t make you compliant. Your backend has to behave too.
Encrypt and minimize
- Force HTTPS everywhere with HSTS.
- Hash IPs in logs if you don’t need the raw value (a SHA-256 with daily salt rotation is usually enough).
- Don’t store what you don’t need. If your form only needs an email, don’t ask for a phone number.
- Set retention periods. A 90-day TTL on analytics raw data is reasonable.
Security headers
Strict-Transport-Security: max-age=63072000; includeSubDomains; preload
Content-Security-Policy: default-src 'self'; ...
Referrer-Policy: strict-origin-when-cross-origin
Permissions-Policy: geolocation=(), camera=(), microphone=()
X-Content-Type-Options: nosniff
Subject Access Requests (SAR)
You must be able to export and delete a user’s data within 30 days. Build the endpoints now, before you’re asked:
GET /api/me/exportreturns a JSON dump of everything linked to the user.DELETE /api/meperforms a real deletion (or anonymization if you have legal retention obligations).
Document the cascade: what gets deleted, what gets anonymized, what stays in backups (and for how long).
Step 4: Forms, Newsletters, and Lawful Basis
Every form on your site should:
- Have an explicit, unticked checkbox for marketing communications.
- Separate consent for separate purposes (newsletter vs. partner offers, for example).
- Link to your privacy policy directly above the submit button.
- Store the consent text shown at the time of submission, not just a boolean.
Database example for a clean consent record:
CREATE TABLE consents (
id BIGSERIAL PRIMARY KEY,
user_id BIGINT,
purpose VARCHAR(64), -- 'newsletter', 'analytics', etc.
granted BOOLEAN,
policy_version VARCHAR(16),
consent_text TEXT,
ip_hash CHAR(64),
created_at TIMESTAMPTZ DEFAULT NOW()
);

Step 5: Write a Privacy Policy That Matches Reality
A privacy policy is not a legal copy-paste. It must describe what your code actually does. At minimum, it should contain:
- Identity and contact of the data controller (and DPO if you have one).
- Categories of data collected and the purpose for each.
- Lawful basis for each processing activity.
- List of third parties and sub-processors (hosting, analytics, email, CDN).
- Data transfers outside the EU/EEA and the safeguards used (SCCs, adequacy decisions).
- Retention periods.
- User rights and how to exercise them.
- Right to lodge a complaint with a supervisory authority.
Version your privacy policy. Store the version number on every consent record. When you change the policy materially, re-prompt users.
Step 6: Third-Party Embeds Are a Trap
YouTube, Google Maps, Google Fonts loaded from the CDN, Vimeo, Twitter widgets: each one sends the user’s IP to a third party the moment the page loads. Two clean fixes:
- Self-host what you can: Google Fonts can be downloaded and served from your own domain.
- Lazy load with consent: show a placeholder with a “Click to load YouTube video” button. The embed only loads after the click.
<div class="yt-placeholder" data-video="abc123">
<button>Load video (sets a YouTube cookie)</button>
</div>

Step 7: Test Like an Auditor
Before pushing to production, run through this checklist:
- Open the site in incognito. No third-party cookie should appear before you click anything.
- Click “Reject all”. Reload. Still no tracking cookie.
- Click “Accept all”. Verify the expected scripts load and the consent receipt is stored.
- Test the consent withdrawal flow. A user should reach it in two clicks max from any page.
- Run Lighthouse and a tool like 2GDPR, CookieServe, or Webbkoll to spot leaks.
- Check that your
/privacyand/cookiespages are linked in the footer of every page.
Bonus: A Minimal Compliance Stack We Use at Pixelseed
- Consent management: a custom 4 KB vanilla JS banner, or Klaro! for bigger sites.
- Analytics: Plausible or Matomo (self-hosted, no personal data, no banner needed for those alone in most cases).
- Forms: server-side validation, double opt-in for newsletters, consent log in Postgres.
- Hosting: EU-based providers when possible (Scaleway, OVH, Hetzner).
- Monitoring: log retention capped at 30 days, IP hashed.
FAQ
Do non-EU websites need to be GDPR compliant?
Yes, if you process personal data of people located in the EU, regardless of where your server or company is. A US e-commerce site shipping to France falls under GDPR.
Is a cookie banner enough to be GDPR compliant?
No. A banner is the visible 10%. The other 90% is your data handling: lawful basis, retention, security, user rights, sub-processor contracts, and your privacy policy.
Can I use Google Analytics in 2026 and stay compliant?
Yes, but only with GA4, consent mode v2 properly configured, IP anonymization, and a clear mention in your privacy policy. Many EU companies now prefer Plausible or Matomo to avoid the question entirely.
What’s the fine for non-compliance?
Up to 20 million euros or 4% of global annual turnover, whichever is higher. In practice, small websites usually receive warnings first, but the reputational cost of a public complaint can be much worse.
Do I need a DPO?
Only if you are a public authority, do large-scale monitoring, or process special categories of data at scale. Most SMB websites don’t, but having a named privacy contact is good practice.
How long should I keep consent logs?
As long as the processing lasts, plus the limitation period for legal claims (usually 3 to 5 years depending on the country). Keep them, but minimize what’s inside (hashed IP, not raw IP).
GDPR compliance is not a one-off task. It’s a way of building. When privacy is a constraint baked into your architecture, you ship better software and you sleep better at night. If you need help auditing or rebuilding a site to be compliant, that’s exactly what we do at Pixelseed. Get in touch.