GDPR and Data Privacy Compliance for Web Applications

The General Data Protection Regulation (GDPR) governs the processing of personal data for individuals in the European Union — regardless of where your application is based. Non-compliance can result in fines of up to €20 million or 4% of global annual turnover.
Consent Management Platform Integration
Under GDPR, consent must be freely given, specific, informed, and unambiguous. Pre-checked consent boxes are illegal. Implement a consent management platform that records granular user preferences and maintains an audit trail.
// Consent record structure
interface ConsentRecord {
userId: string;
timestamp: string;
ipAddress: string;
userAgent: string;
consents: {
necessary: true, // Always required
analytics: boolean,
marketing: boolean,
functional: boolean,
};
version: string;
signature: string; // HMAC for tamper evidence
}
// Consent banner logic
function getConsentStatus(userId: string): ConsentStatus {
const record = await ConsentModel.findOne({ userId })
.sort({ timestamp: -1 });
if (!record) return { status: 'pending', version: CURRENT_VERSION };
// Check if consent version matches current policy version
if (record.version !== CURRENT_VERSION) return { status: 'update_needed' };
// Check if consent is older than 6 months (requires renewal)
if (Date.now() - new Date(record.timestamp).getTime() > 180 * 86400000) {
return { status: 'expired' };
}
return { status: 'valid', consents: record.consents };
}
Store consent records as part of your audit trail — include timestamp, IP address, user agent, and the exact version of the privacy policy at the time of consent. Make it as easy to withdraw consent as it was to give it.
Data Subject Access Request (DSAR) Handling
Individuals have the right to access any personal data you hold about them within 30 days. Automate DSAR processing to meet this deadline efficiently.
// DSAR processing pipeline
async function processDSAR(userId: string): Promise<Buffer> {
const user = await UserModel.findById(userId).lean();
const personalData = {
account: {
email: user.email,
name: user.name,
createdAt: user.createdAt,
lastLogin: user.lastLogin,
},
communications: await CommunicationModel.find({ userId }).lean(),
orders: await OrderModel.find({ userId }).populate('items').lean(),
analytics: await AnalyticsModel.find({ anonymousId: user.anonymousId })
.select('pageViews sessions -_id').lean(),
consentHistory: await ConsentModel.find({ userId }).lean(),
supportTickets: await TicketModel.find({ userId }).lean(),
};
// Generate structured JSON export or CSV
const exportData = anonymizeThirdPartyReferences(personalData);
return await createEncryptedExport(exportData, user.email);
}
Implement a DSAR portal where users can initiate requests and track progress. For manual DSARs, maintain an internal SLA tracking system that escalates approaching the 30-day deadline. Redact or pseudonymize data that references other individuals.
Cookie Compliance
The ePrivacy Directive (Cookie Law) requires explicit consent for non-essential cookies — analytics, marketing, and personalization. Essential cookies (session, CSRF, load balancing) are exempt.
// Cookie categorization in consent banner
const COOKIE_LEGEND = {
essential: {
cookies: ['sid', 'csrf-token', 'locale'],
purpose: 'Session management, security, user preferences',
consent: 'required',
},
analytics: {
cookies: ['_ga', '_gid', '_ga_*', 'cluid'],
purpose: 'Site usage analytics, page views, navigation paths',
consent: 'optional',
},
marketing: {
cookies: ['_fbp', 'ads_prefs', 'tracking_id'],
purpose: 'Personalized advertising, campaign attribution',
consent: 'optional',
},
};
// Conditionally load tracking scripts based on consent
function loadAnalytics(): void {
if (getCookieConsent('analytics')) {
// Load Google Analytics or Plausible
initializeAnalytics();
}
}
For EU visitors, block all non-essential cookies until explicit consent is given. Use a cookie scanner to document all cookies set by your application and third-party scripts. Re-run the scanner after any dependency update or third-party script addition.
Privacy Policy and Data Processing Records
Under GDPR's accountability principle, you must maintain records of processing activities (ROPA). Your privacy policy must specify:
- The categories of personal data collected
- The purposes of processing (legal basis)
- Data retention periods
- Third-party data processors and sub-processors
- International data transfer mechanisms
- Individual rights (access, rectification, erasure, portability)
# Record of Processing Activities (ROPA) entry
processing_activity:
name: "User account management"
data_categories:
- identity: [name, email, phone]
- technical: [ip_address, user_agent, browser_fingerprint]
- usage: [login_timestamps, feature_usage]
purposes:
- "Service delivery and account management"
- "Security and fraud prevention"
legal_basis: "Contractual necessity (Art. 6(1)(b))"
retention: "Account life + 90 days after deletion request"
processors:
- name: "Railway"
purpose: "Hosting infrastructure"
data_transfer: "Standard Contractual Clauses"
- name: "PostHog"
purpose: "Product analytics"
data_transfer: "Adequacy decision (US Data Privacy Framework)"
Update the ROPA whenever you add a new data processing activity or engage a new processor. Link each processing activity to its legal basis and verify that consent or legitimate interest assessments are documented.
Data Minimization and Retention
Collect only the personal data you genuinely need. Define retention schedules for each data category and implement automated purging.
// Automated data retention enforcement
async function enforceRetentionPolicies(): Promise<void> {
const now = new Date();
// Delete raw analytics data older than 26 months
await AnalyticsModel.deleteMany({
createdAt: { $lt: new Date(now.getTime() - 26 * 30 * 86400000) },
});
// Anonymize support tickets after 3 years (keep aggregated metrics)
await TicketModel.updateMany(
{ createdAt: { $lt: new Date(now.getTime() - 3 * 365 * 86400000) } },
{ $set: { userId: null, email: null, name: 'Anonymized' } }
);
// Permanently delete accounts with deletion requests older than 90 days
const deletionCutoff = new Date(now.getTime() - 90 * 86400000);
const requestsToExecute = await DeletionRequestModel.find({
requestedAt: { $lt: deletionCutoff },
status: 'pending',
});
for (const request of requestsToExecute) {
await permanentlyDeleteUser(request.userId);
request.status = 'completed';
await request.save();
}
}
Data Breach Notification Procedures
GDPR requires notification to supervisory authorities within 72 hours of becoming aware of a personal data breach. Maintain a documented breach response plan.
// Breach notification workflow
async function handleDataBreach(breach: DataBreachReport): Promise<void> {
// 1. Contain the breach
await containBreach(breach);
// 2. Assess risk to data subjects
const riskLevel = assessRisk(breach);
// 3. Notify DPO and legal team
await notifyInternal({
severity: riskLevel,
affectedRecords: breach.affectedUserIds.length,
dataTypes: breach.dataCategories,
timeElapsed: Date.now() - breach.detectedAt,
});
// 4. Notify supervisory authority (within 72 hours)
if (riskLevel === 'high' || riskLevel === 'medium') {
await notifySupervisoryAuthority({
name: 'SoniNow',
breachDescription: formatBreachDescription(breach),
affectedCount: breach.affectedUserIds.length,
likelyConsequences: assessConsequences(breach),
mitigationMeasures: breach.mitigationSteps,
dpoContact: '[email protected]',
});
}
// 5. Notify affected data subjects
if (riskLevel === 'high') {
await notifyDataSubjects(breach);
}
// 6. Document the breach
await BreachLogModel.create({
...breach,
notifiedAuthority: true,
notifiedSubjects: riskLevel === 'high',
timestamp: new Date(),
});
}
International Data Transfers
Following Schrems II and the EU-US Data Privacy Framework, document your transfer mechanisms for data leaving the EEA. For US-based processors, verify participation in the Data Privacy Framework. For other countries, implement Standard Contractual Clauses or Binding Corporate Rules.
GDPR compliance is an ongoing commitment, not a one-time project. Our <a href="/services/web-development">web development services</a> include privacy-by-design architecture, consent management implementation, and compliance documentation. Contact SoniNow to ensure your application meets GDPR requirements.