Implementation of Consent Withdrawal Mechanism for Data Processing
Per GDPR (Article 7.3), user must be able to withdraw consent as easily as granting it. If consent was given with one button click, withdrawal should not require 10 steps.
Points for Withdrawing Consent
- Account settings (Privacy / My Data section)
- Footer link "Manage cookies"
- Email with unsubscribe link
- Button to reopen cookie banner
Implementation in Account Cabinet
// PrivacySettings.jsx
function PrivacySettings() {
const [consent, setConsent] = useState(null)
const [loading, setLoading] = useState(true)
useEffect(() => {
fetch('/api/my/consent')
.then(r => r.json())
.then(data => { setConsent(data.current); setLoading(false) })
}, [])
const updateConsent = async (category, value) => {
const updated = { ...consent, [category]: value }
await fetch('/api/my/consent', {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ categories: updated })
})
setConsent(updated)
// Apply immediately
if (!value && category === 'analytics') {
window['ga-disable-G-XXXXXXXX'] = true
}
}
const revokeAll = async () => {
if (!confirm('Are you sure? This does not delete your account, only additional processing consent.')) return
await fetch('/api/my/consent', { method: 'DELETE' })
setConsent({ necessary: true, analytics: false, marketing: false })
}
if (loading) return <Spinner />
return (
<div className="privacy-settings">
<h2>Data Management</h2>
{Object.entries({
analytics: 'Analytics and service improvement',
marketing: 'Personalized advertising',
preferences: 'Remember preferences'
}).map(([key, label]) => (
<label key={key} className="consent-toggle">
<span>{label}</span>
<input
type="checkbox"
checked={consent?.[key] ?? false}
onChange={e => updateConsent(key, e.target.checked)}
/>
</label>
))}
<button className="btn-danger" onClick={revokeAll}>
Withdraw all consents
</button>
<a href="#" onClick={() => window.CookieBot?.renew()}>
Edit cookie settings
</a>
</div>
)
}
Server-Side Withdrawal Processing
@app.route('/api/my/consent', methods=['PUT'])
@login_required
def update_consent():
new_categories = request.json['categories']
# Log change
consent_logger.log(
request,
categories=new_categories,
event_type='updated',
user_id=current_user.id
)
# Apply changes immediately
if not new_categories.get('marketing'):
unsubscribe_from_marketing(current_user.id)
remove_from_ad_audiences(current_user.email)
return jsonify({'status': 'updated', 'categories': new_categories})
def unsubscribe_from_marketing(user_id: int):
user = db.get_user(user_id)
# Mailchimp
mailchimp_client.lists.update_list_member_tags(
list_id=MAILCHIMP_LIST_ID,
subscriber_hash=md5(user.email.lower()),
body={'tags': [{'name': 'marketing_opted_out', 'status': 'active'}]}
)
# Disable ad pixels for this user
db.execute("""
UPDATE users SET marketing_opted_out = true,
marketing_opt_out_at = NOW()
WHERE id = %s
""", (user_id,))
Cookie Banner: Reopen
// Footer link: "Manage cookies"
document.getElementById('cookie-settings-link').addEventListener('click', (e) => {
e.preventDefault()
// Cookiebot
if (window.CookieBot) {
window.CookieBot.renew()
return
}
// CookieYes
if (window.revisitCkyConsent) {
window.revisitCkyConsent()
return
}
// Custom banner
ConsentBanner.show()
})







