Mistake 6: Poor Third-Party Integration Privacy
Mistake 6: Poor Third-Party Integration Privacy
Developers often integrate third-party services without considering privacy implications. They might share entire user objects when only email is needed, fail to anonymize data before sending to analytics, or grant third-party scripts unrestricted access to user data. Each integration multiplies privacy risks and compliance obligations.
The convenience of dropping in third-party SDKs or scripts obscures their data collection practices. That "simple" analytics script might be fingerprinting users, setting tracking cookies, or collecting far more data than expected. Social media widgets often track users even without interaction. Payment processors might retain more data than necessary.
// ❌ Bad: Careless third-party integration
function integrateAnalytics(user) {
// Sending everything!
analytics.identify(user.id, {
email: user.email,
name: user.fullName,
phone: user.phone,
address: user.address,
creditCard: user.paymentMethods[0] // Never do this!
});
}
function addSocialWidget() {
// Direct script injection - no control
const script = document.createElement('script');
script.src = 'https://socialmedia.com/widget.js';
document.head.appendChild(script);
}
// ✅ Good: Privacy-conscious integration
class ThirdPartyIntegrator {
async integrateAnalytics(userId) {
// Check consent first
if (!await this.hasConsent(userId, 'analytics')) {
return;
}
// Minimize data shared
const analyticsData = {
userId: this.hashUserId(userId),
// Only non-identifying properties
accountType: 'basic',
createdMonth: await this.getUserCreatedMonth(userId)
};
// Use proxy to control data flow
await this.analyticsProxy.identify(analyticsData);
}
async loadSocialWidget() {
// Check consent
if (!this.hasConsent('social_media')) {
return this.showConsentPrompt('social_media');
}
// Load in sandboxed iframe
const iframe = document.createElement('iframe');
iframe.src = '/privacy-proxy/social-widget';
iframe.sandbox = 'allow-scripts allow-same-origin';
iframe.style.border = 'none';
// Communicate via postMessage
iframe.onload = () => {
iframe.contentWindow.postMessage({
type: 'init',
config: this.getSanitizedConfig()
}, '*');
};
document.getElementById('social-container').appendChild(iframe);
}
// Proxy for controlling third-party APIs
createPrivacyProxy(service) {
return new Proxy(service, {
get(target, prop) {
return function(...args) {
// Filter sensitive data
const filtered = args.map(arg =>
this.filterSensitiveData(arg)
);
// Log for audit
this.logThirdPartyCall(service.name, prop, filtered);
// Call original method
return target[prop](...filtered);
}.bind(this);
}
});
}
}