Implementing the "Do Not Sell" Requirement
Implementing the "Do Not Sell" Requirement
CCPA's signature requirement mandates a clear and conspicuous "Do Not Sell My Personal Information" link on the homepage and any page where personal information is collected. This opt-out mechanism must be easy to use and cannot require account creation. The implementation must respect user choice across sessions and devices, requiring sophisticated tracking and preference management systems.
// Do Not Sell implementation
class DoNotSellManager {
constructor() {
this.optOutCookie = 'ccpa_opt_out';
this.optOutDuration = 365 * 24 * 60 * 60 * 1000; // 1 year
this.optOutDatabase = new OptOutDatabase();
}
// Initialize Do Not Sell functionality
init() {
this.renderDoNotSellLink();
this.checkOptOutStatus();
this.setupGlobalPrivacyControl();
}
// Render Do Not Sell link
renderDoNotSellLink() {
const link = document.createElement('a');
link.href = '/privacy/do-not-sell';
link.className = 'ccpa-do-not-sell-link';
link.textContent = 'Do Not Sell My Personal Information';
link.setAttribute('aria-label', 'Opt out of personal information sales');
// Add to footer and header as required
const positions = ['.footer-links', '.header-menu', '.privacy-links'];
positions.forEach(selector => {
const container = document.querySelector(selector);
if (container) {
container.appendChild(link.cloneNode(true));
}
});
}
// Check current opt-out status
checkOptOutStatus() {
// Check cookie
const cookieOptOut = this.getCookie(this.optOutCookie);
// Check Global Privacy Control signal
const gpcOptOut = navigator.globalPrivacyControl || navigator.doNotTrack === '1';
// Check database for authenticated users
const dbOptOut = this.checkDatabaseOptOut();
// Apply most restrictive preference
if (cookieOptOut || gpcOptOut || dbOptOut) {
this.applyOptOut();
}
}
// Process opt-out request
async processOptOut(requestData = {}) {
const optOutRecord = {
timestamp: new Date().toISOString(),
method: requestData.method || 'direct-link',
ipAddress: await this.getHashedIP(),
userAgent: navigator.userAgent,
authenticated: !!requestData.userId
};
// Set opt-out cookie
this.setCookie(this.optOutCookie, 'true', this.optOutDuration);
// Record in database if authenticated
if (requestData.userId) {
await this.optOutDatabase.recordOptOut(requestData.userId, optOutRecord);
}
// Apply opt-out immediately
this.applyOptOut();
// Notify third parties
await this.notifyThirdParties();
// Show confirmation
this.showOptOutConfirmation();
return {
success: true,
record: optOutRecord
};
}
// Apply opt-out preferences
applyOptOut() {
// Disable advertising cookies
this.disableAdvertisingCookies();
// Update consent management platform
if (window.consentManager) {
window.consentManager.updateConsent({
advertising: false,
sale_of_data: false
});
}
// Disable third-party scripts
this.disableThirdPartyTracking();
// Update ad personalization
this.disableAdPersonalization();
// Signal to backend
this.signalOptOutToBackend();
}
// Handle Global Privacy Control
setupGlobalPrivacyControl() {
if (navigator.globalPrivacyControl) {
console.log('Global Privacy Control detected');
this.processOptOut({ method: 'gpc-signal' });
// Show GPC acknowledgment
this.showGPCAcknowledgment();
}
}
// Disable third-party tracking
disableThirdPartyTracking() {
// Google Analytics
window['ga-disable-UA-XXXXX-Y'] = true;
// Facebook Pixel
if (typeof fbq !== 'undefined') {
fbq('dataProcessingOptions', ['LDU'], 1, 1000);
}
// Other third-party scripts
const trackingScripts = [
'doubleclick.net',
'facebook.com/tr',
'amazon-adsystem.com',
'googlesyndication.com'
];
// Prevent loading of tracking scripts
const observer = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
mutation.addedNodes.forEach((node) => {
if (node.tagName === 'SCRIPT' && node.src) {
if (trackingScripts.some(domain => node.src.includes(domain))) {
node.remove();
console.log('Blocked tracking script:', node.src);
}
}
});
});
});
observer.observe(document.documentElement, {
childList: true,
subtree: true
});
}
// Show opt-out confirmation
showOptOutConfirmation() {
const confirmation = document.createElement('div');
confirmation.className = 'ccpa-opt-out-confirmation';
confirmation.innerHTML = `
<div class="confirmation-content">
<h3>Opt-Out Confirmed</h3>
<p>Your opt-out preference has been recorded. We will not sell your personal information.</p>
<p>Note: This opt-out applies only to sales of personal information. You may still see ads, but they won't be based on your personal information sold by us.</p>
<button onclick="this.parentElement.parentElement.remove()">Close</button>
</div>
`;
document.body.appendChild(confirmation);
}
}
// Initialize Do Not Sell functionality
document.addEventListener('DOMContentLoaded', () => {
const doNotSellManager = new DoNotSellManager();
doNotSellManager.init();
});