Managing Consent
Learn how to implement a complete consent management system with the NDPR Toolkit
Introduction
Consent is a cornerstone of data protection under the Nigeria Data Protection Regulation (NDPR). Organizations must obtain valid consent before collecting, processing, or sharing personal data. This guide will help you implement a comprehensive consent management system using the NDPR Toolkit.
NDPR Consent Requirements
Under the NDPR, valid consent must be:
- Freely given: Data subjects must have a genuine choice and control
- Specific: Consent must be granular for different types of processing
- Informed: Data subjects must understand what they're consenting to
- Unambiguous: Consent must be given through a clear affirmative action
- Withdrawable: Data subjects must be able to withdraw consent easily
The Consent Lifecycle
A complete consent management system covers the entire lifecycle of consent, from collection to withdrawal. The NDPR Toolkit provides components for each stage of this lifecycle:
Consent Collection
The first step is collecting consent from data subjects. This typically happens when users first visit your website or when they sign up for your service. The NDPR Toolkit's ConsentBanner component is designed for this purpose.
Code Example
import { ConsentBanner } from '@tantainnovative/ndpr-toolkit';
function App() {
const consentOptions = [
{
id: 'necessary',
label: 'Necessary Cookies',
description: 'These cookies are essential for the website to function properly.',
required: true
},
{
id: 'analytics',
label: 'Analytics Cookies',
description: 'These cookies help us understand how visitors interact with our website.',
required: false
},
{
id: 'marketing',
label: 'Marketing Cookies',
description: 'These cookies are used to track visitors across websites to display relevant advertisements.',
required: false
}
];
const handleSaveConsent = (consents) => {
// Save consent preferences to your backend or local storage
console.log('Consent preferences:', consents);
// Example: Save to localStorage
localStorage.setItem('userConsents', JSON.stringify(consents));
// Example: Send to backend API
fetch('/api/consents', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(consents),
});
};
return (
<div>
<ConsentBanner
options={consentOptions}
onSave={handleSaveConsent}
privacyPolicyUrl="/privacy-policy"
position="bottom"
showCloseButton={false}
/>
{/* Rest of your application */}
</div>
);
}
Consent Storage
Once collected, consent preferences must be securely stored and easily retrievable. The NDPR Toolkit provides utilities for storing consent in various formats, including local storage, cookies, and server-side databases.
Code Example
import { ConsentStorage } from '@tantainnovative/ndpr-toolkit';
// Create a consent storage instance
const consentStorage = new ConsentStorage({
storageType: 'localStorage', // or 'cookie', 'indexedDB', 'api'
apiEndpoint: '/api/consents', // Only required for 'api' storage type
cookieOptions: { // Only required for 'cookie' storage type
domain: 'example.com',
secure: true,
sameSite: 'strict',
maxAge: 60 * 60 * 24 * 365 // 1 year in seconds
}
});
// Save consent
function saveConsent(userId, consents) {
return consentStorage.saveConsent(userId, consents);
}
// Retrieve consent
async function getConsent(userId) {
return await consentStorage.getConsent(userId);
}
// Example usage
const userId = 'user123';
const consents = {
necessary: true,
analytics: true,
marketing: false,
timestamp: new Date().toISOString(),
version: '1.0'
};
saveConsent(userId, consents);
// Later, retrieve the consent
getConsent(userId).then(savedConsents => {
console.log('Retrieved consents:', savedConsents);
});
Consent Verification
Before processing personal data, you must verify that the user has given consent for the specific processing activity. The NDPR Toolkit provides utilities for checking consent status.
Code Example
import { useConsent } from '@tantainnovative/ndpr-toolkit';
function AnalyticsComponent() {
const { hasConsent, isLoading } = useConsent('analytics');
useEffect(() => {
if (!isLoading && hasConsent) {
// Initialize analytics only if user has given consent
initializeAnalytics();
}
}, [hasConsent, isLoading]);
if (isLoading) {
return <div>Loading consent preferences...</div>;
}
if (!hasConsent) {
return (
<div>
<p>Analytics are disabled based on your consent preferences.</p>
<button onClick={() => openConsentManager()}>
Update Preferences
</button>
</div>
);
}
return <div>Analytics are enabled and tracking your usage.</div>;
}
function MarketingComponent() {
const { hasConsent, isLoading } = useConsent('marketing');
// Similar implementation for marketing features
}
Consent Management
Data subjects must be able to view and update their consent preferences at any time. The NDPR Toolkit's ConsentManager component provides a user interface for managing consent preferences.
Code Example
import { ConsentManager } from '@tantainnovative/ndpr-toolkit';
function PrivacySettingsPage() {
const consentOptions = [
{
id: 'necessary',
label: 'Necessary Cookies',
description: 'These cookies are essential for the website to function properly.',
required: true
},
{
id: 'analytics',
label: 'Analytics Cookies',
description: 'These cookies help us understand how visitors interact with our website.',
required: false
},
{
id: 'marketing',
label: 'Marketing Cookies',
description: 'These cookies are used to track visitors across websites to display relevant advertisements.',
required: false
}
];
const handleSaveConsent = (consents) => {
// Save updated consent preferences
console.log('Updated consent preferences:', consents);
// Example: Save to localStorage
localStorage.setItem('userConsents', JSON.stringify(consents));
// Example: Send to backend API
fetch('/api/consents', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(consents),
});
};
return (
<div>
<h1>Privacy Settings</h1>
<p>
Manage your consent preferences for how we use your data.
You can change these settings at any time.
</p>
<ConsentManager
options={consentOptions}
onSave={handleSaveConsent}
initialValues={JSON.parse(localStorage.getItem('userConsents') || '{}')}
/>
</div>
);
}
Consent Records
For compliance purposes, you must maintain records of consent, including when and how consent was given or withdrawn. The NDPR Toolkit provides utilities for maintaining detailed consent records.
Code Example
import { ConsentRecorder } from '@tantainnovative/ndpr-toolkit';
// Create a consent recorder instance
const consentRecorder = new ConsentRecorder({
storageType: 'api',
apiEndpoint: '/api/consent-records'
});
// Record a consent event
function recordConsentEvent(userId, event) {
const consentEvent = {
userId,
eventType: event.type, // 'given', 'updated', 'withdrawn'
consents: event.consents,
timestamp: new Date().toISOString(),
source: event.source, // 'banner', 'settings', 'account-deletion', etc.
ipAddress: event.ipAddress,
userAgent: event.userAgent,
version: event.version
};
return consentRecorder.recordEvent(consentEvent);
}
// Example usage
const userId = 'user123';
const consentEvent = {
type: 'given',
consents: {
necessary: true,
analytics: true,
marketing: false
},
source: 'banner',
ipAddress: '192.168.1.1',
userAgent: 'Mozilla/5.0...',
version: '1.0'
};
recordConsentEvent(userId, consentEvent);
// Retrieve consent history for a user
consentRecorder.getEventHistory(userId).then(history => {
console.log('Consent history:', history);
});
Consent Withdrawal
Data subjects must be able to withdraw their consent as easily as they gave it. The NDPR Toolkit provides components and utilities for handling consent withdrawal.
Implementation Tip
When a user withdraws consent, you must stop processing their data for the purposes they've withdrawn consent for. This may include deleting data or disabling certain features. Make sure your application architecture supports this granular control.
Complete Implementation Example
Here's a complete example of how to implement a consent management system using the NDPR Toolkit:
import { useState, useEffect } from 'react';
import {
ConsentBanner,
ConsentManager,
ConsentStorage,
ConsentRecorder,
ConsentContext,
useConsent
} from '@tantainnovative/ndpr-toolkit';
// Define consent options
const consentOptions = [
{
id: 'necessary',
label: 'Necessary Cookies',
description: 'These cookies are essential for the website to function properly.',
required: true
},
{
id: 'analytics',
label: 'Analytics Cookies',
description: 'These cookies help us understand how visitors interact with our website.',
required: false
},
{
id: 'marketing',
label: 'Marketing Cookies',
description: 'These cookies are used to track visitors across websites to display relevant advertisements.',
required: false
},
{
id: 'personalization',
label: 'Personalization',
description: 'These cookies allow us to provide personalized content and recommendations.',
required: false
}
];
// Create storage and recorder instances
const consentStorage = new ConsentStorage({ storageType: 'localStorage' });
const consentRecorder = new ConsentRecorder({ storageType: 'api', apiEndpoint: '/api/consent-records' });
// Main application with consent management
function App() {
const [userId, setUserId] = useState(null);
const [showBanner, setShowBanner] = useState(false);
const [consents, setConsents] = useState(null);
useEffect(() => {
// Generate or retrieve user ID
const storedUserId = localStorage.getItem('userId');
if (storedUserId) {
setUserId(storedUserId);
} else {
const newUserId = `user_${Date.now()}`;
localStorage.setItem('userId', newUserId);
setUserId(newUserId);
}
}, []);
useEffect(() => {
if (userId) {
// Check if user has already given consent
consentStorage.getConsent(userId).then(storedConsents => {
if (storedConsents) {
setConsents(storedConsents);
} else {
// No stored consents, show the banner
setShowBanner(true);
}
});
}
}, [userId]);
const handleSaveConsent = (newConsents) => {
// Save the consent preferences
setConsents(newConsents);
consentStorage.saveConsent(userId, newConsents);
// Record the consent event
const eventType = consents ? 'updated' : 'given';
consentRecorder.recordEvent({
userId,
eventType,
consents: newConsents,
timestamp: new Date().toISOString(),
source: eventType === 'given' ? 'banner' : 'settings',
userAgent: navigator.userAgent,
version: '1.0'
});
// Hide the banner if it's showing
setShowBanner(false);
};
const openConsentManager = () => {
// Open a modal with the consent manager
setShowConsentManager(true);
};
const [showConsentManager, setShowConsentManager] = useState(false);
return (
<ConsentContext.Provider value={{ consents, openConsentManager }}>
<div className="app">
<header>
<h1>My NDPR-Compliant Website</h1>
<nav>
<ul>
<li><a href="/">Home</a></li>
<li><a href="/about">About</a></li>
<li><a href="/contact">Contact</a></li>
<li>
<button onClick={openConsentManager}>
Privacy Settings
</button>
</li>
</ul>
</nav>
</header>
<main>
{/* Main content of your application */}
<HomePage />
</main>
<footer>
<p>© 2023 My Company</p>
<button onClick={openConsentManager}>
Manage Cookie Preferences
</button>
</footer>
{/* Consent banner */}
{showBanner && (
<ConsentBanner
options={consentOptions}
onSave={handleSaveConsent}
privacyPolicyUrl="/privacy-policy"
position="bottom"
showCloseButton={false}
/>
)}
{/* Consent manager modal */}
{showConsentManager && (
<div className="modal">
<div className="modal-content">
<h2>Privacy Settings</h2>
<ConsentManager
options={consentOptions}
onSave={(newConsents) => {
handleSaveConsent(newConsents);
setShowConsentManager(false);
}}
initialValues={consents || {}}
onCancel={() => setShowConsentManager(false)}
/>
</div>
</div>
)}
</div>
</ConsentContext.Provider>
);
}
// Example component that uses consent
function HomePage() {
const { hasConsent: hasAnalyticsConsent } = useConsent('analytics');
const { hasConsent: hasMarketingConsent } = useConsent('marketing');
const { hasConsent: hasPersonalizationConsent } = useConsent('personalization');
const { openConsentManager } = useConsent();
useEffect(() => {
if (hasAnalyticsConsent) {
// Initialize analytics
console.log('Initializing analytics...');
}
}, [hasAnalyticsConsent]);
useEffect(() => {
if (hasMarketingConsent) {
// Initialize marketing tools
console.log('Initializing marketing tools...');
}
}, [hasMarketingConsent]);
return (
<div>
<h2>Welcome to our website</h2>
{hasPersonalizationConsent ? (
<div>
<h3>Personalized Content</h3>
<p>Here's some content tailored just for you!</p>
</div>
) : (
<div>
<h3>Standard Content</h3>
<p>
Enable personalization to see content tailored to your interests.
<button onClick={openConsentManager}>
Update Privacy Settings
</button>
</p>
</div>
)}
{/* More content... */}
</div>
);
}
Best Practices
No Pre-checked Boxes
Never use pre-checked boxes for optional consent options. The NDPR requires that consent be given through a clear affirmative action, and pre-checked boxes do not meet this requirement.
Clear Language
Use clear, plain language to explain what data you're collecting, why you're collecting it, and how it will be used. Avoid legal jargon that may confuse users.
Granular Consent
Provide granular consent options for different types of processing. Don't bundle multiple purposes into a single consent option. This allows users to consent to some types of processing but not others.
Easy Withdrawal
Make it as easy to withdraw consent as it is to give it. Provide a clear, accessible way for users to update their consent preferences at any time.
Record Keeping
Maintain detailed records of consent, including when and how consent was given or withdrawn. This is essential for demonstrating compliance with the NDPR.
Regular Review
Regularly review and update your consent mechanisms to ensure they remain compliant with the NDPR and effective for your users. Consider conducting user testing to ensure your consent mechanisms are clear and usable.
Common Pitfalls to Avoid
- Cookie Walls: Blocking access to your website unless users accept all cookies is generally not considered valid consent under the NDPR, as it doesn't give users a genuine choice.
- Bundling Consent: Requiring users to consent to multiple unrelated purposes as a package deal is not compliant with the NDPR's requirement for specific consent.
- Ignoring Consent: Loading tracking scripts or cookies before obtaining consent is a common mistake that violates the NDPR.
- Unclear Language: Using vague or technical language that users may not understand undermines the "informed" aspect of valid consent.
- Difficult Withdrawal: Making it difficult for users to withdraw consent, such as by hiding the option in a complex settings menu, is not compliant with the NDPR.
- Inadequate Records: Failing to maintain adequate records of consent can make it difficult to demonstrate compliance with the NDPR.
Additional Resources
NDPR Implementation Framework
Official guidance on implementing the NDPR, including consent requirements.
View FrameworkConsent Component Documentation
Technical documentation for the Consent Management components.
View Documentation