Privacy & Compliance Guide
The Teads SDK is designed with privacy at its core, providing comprehensive tools for managing user consent and ensuring compliance with global privacy regulations. This guide covers everything you need to know about privacy management, consent handling, and regulatory compliance.
Overview
The SDK includes the TeadsPrivacy component that:
- ✅ Automatically detects and respects IAB consent strings
- ✅ Supports GDPR, CCPA, and GPP frameworks
- ✅ Manages IDFA (Identifier for Advertisers) consent
- ✅ Provides manual consent configuration options
- ✅ Ensures end-to-end privacy compliance
Supported Privacy Standards
🇪🇺 GDPR (General Data Protection Regulation)
Full support for European privacy requirements including:
- IAB TCF v1.1 and v2.0 consent strings
- Purpose and vendor consent management
- Legitimate interest handling
🇺🇸 CCPA (California Consumer Privacy Act)
Complete CCPA compliance with:
- IAB US Privacy String support
- Opt-out mechanism implementation
- Sale of personal information controls
🌍 GPP (Global Privacy Platform)
Support for the IAB's Global Privacy Platform:
- Multi-jurisdiction privacy signals
- Section-specific consent handling
- Future-proof privacy framework
ATT (App Tracking Transparency)
iOS 14+ privacy features:
- IDFA consent management
- SKAdNetwork integration
- Privacy nutrition labels support
Basic Implementation
Automatic Privacy Detection
The SDK automatically detects and respects privacy signals from your CMP (Consent Management Platform):
import TeadsSDK
// The SDK automatically reads consent from UserDefaults
// No additional configuration needed if using IAB-compliant CMP
@main
struct YourApp: App {
init() {
// Initialize SDK - privacy is handled automatically
Teads.configure(with: "YOUR_PARTNER_KEY")
}
}
Manual Privacy Configuration
For apps with custom consent implementations:
import TeadsSDK
class PrivacyManager {
func configurePrivacy() {
let privacy = TeadsPrivacy.shared
// GDPR consent
privacy.setGDPRApplies(true)
privacy.setGDPRConsentString("YOUR_CONSENT_STRING")
// CCPA consent
privacy.setUSPrivacyString("1YNN")
// GPP consent
privacy.setGPPString("DBABLA~BAAAAAAAAAA")
// IDFA consent
privacy.setSubjectToIDFAConsent(true)
}
}
Complete Privacy Implementation Example
Here's a comprehensive example combining all privacy frameworks for apps with custom consent implementations, meaning for when you are not using a CMP to handle it on your behalf:
import TeadsSDK
import AppTrackingTransparency
import AdSupport
class ComprehensivePrivacyManager {
static let shared = ComprehensivePrivacyManager()
private let privacy = TeadsPrivacy.shared
// MARK: - Initialization
func initializePrivacy() {
// Check for automatic consent
if hasAutomaticConsent() {
print("Using automatic consent from CMP")
} else {
// Configure manual consent
configureManualConsent()
}
// Request IDFA if needed
requestIDFAIfAppropriate()
// Monitor consent changes
observeConsentChanges()
}
// MARK: - Automatic Consent Detection
private func hasAutomaticConsent() -> Bool {
let defaults = UserDefaults.standard
// Check for IAB consent strings
let hasGDPR = defaults.object(forKey: "IABTCF_TCString") != nil
let hasCCPA = defaults.object(forKey: "IABUSPrivacy_String") != nil
let hasGPP = defaults.object(forKey: "IABGPP_HDR_GppString") != nil
return hasGDPR || hasCCPA || hasGPP
}
// MARK: - Manual Configuration
private func configureManualConsent() {
// Determine user location
let userLocation = determineUserLocation()
switch userLocation {
case .eu:
configureGDPR()
case .california:
configureCCPA()
case .other:
configureDefaultPrivacy()
}
}
private func configureGDPR() {
// Check if user has given consent
if let savedConsent = loadSavedGDPRConsent() {
privacy.setGDPRApplies(true)
privacy.setGDPRConsentString(savedConsent)
} else {
// Show consent dialog
showGDPRConsentDialog()
}
}
private func configureCCPA() {
// Check opt-out status
let optedOut = UserDefaults.standard.bool(forKey: "user_opted_out_ccpa")
let usPrivacyString = optedOut ? "1YYN" : "1YNN"
privacy.setUSPrivacyString(usPrivacyString)
}
private func configureDefaultPrivacy() {
// No specific privacy requirements
privacy.setGDPRApplies(false)
}
// MARK: - IDFA Management
private func requestIDFAIfAppropriate() {
// Only request if not determined
guard ATTrackingManager.trackingAuthorizationStatus == .notDetermined else {
updateIDFAStatus()
return
}
// Wait for appropriate moment
DispatchQueue.main.asyncAfter(deadline: .now() + 3.0) {
self.requestIDFAPermission()
}
}
private func requestIDFAPermission() {
ATTrackingManager.requestTrackingAuthorization { [weak self] status in
self?.updateIDFAStatus()
}
}
private func updateIDFAStatus() {
let authorized = ATTrackingManager.trackingAuthorizationStatus == .authorized
privacy.setSubjectToIDFAConsent(authorized)
if authorized {
let idfa = ASIdentifierManager.shared().advertisingIdentifier.uuidString
print("IDFA available: \(idfa)")
}
}
// MARK: - Consent Monitoring
private func observeConsentChanges() {
// Monitor UserDefaults for consent changes
NotificationCenter.default.addObserver(
self,
selector: #selector(consentDidChange),
name: UserDefaults.didChangeNotification,
object: nil
)
}
@objc private func consentDidChange() {
// Re-read consent values
initializePrivacy()
}
// MARK: - Consent UI
private func showGDPRConsentDialog() {
// Show your consent UI
ConsentViewController.present { [weak self] consentString in
self?.privacy.setGDPRApplies(true)
self?.privacy.setGDPRConsentString(consentString)
self?.saveGDPRConsent(consentString)
}
}
// MARK: - Persistence
private func saveGDPRConsent(_ consent: String) {
UserDefaults.standard.set(consent, forKey: "app_gdpr_consent")
}
private func loadSavedGDPRConsent() -> String? {
UserDefaults.standard.string(forKey: "app_gdpr_consent")
}
// MARK: - Location Detection
private enum UserLocation {
case eu, california, other
}
private func determineUserLocation() -> UserLocation {
// Implement location detection logic
// This is a simplified example
let locale = Locale.current
let regionCode = locale.regionCode ?? ""
let euCountries = ["AT", "BE", "BG", "HR", "CY", "CZ", "DK", "EE",
"FI", "FR", "DE", "GR", "HU", "IE", "IT", "LV",
"LT", "LU", "MT", "NL", "PL", "PT", "RO", "SK",
"SI", "ES", "SE"]
if euCountries.contains(regionCode) {
return .eu
} else if regionCode == "US" {
// Check if California (simplified)
return .california
} else {
return .other
}
}
}
Testing Privacy Compliance
Debug Privacy Settings
#if DEBUG
extension TeadsPrivacy {
func debugPrintPrivacyStatus() {
print("=== Privacy Status ===")
print("GDPR Applies: \(subjectToGDPR)")
print("GDPR Consent: \(gdprConsentString ?? "none")")
print("US Privacy: \(usPrivacyString ?? "none")")
print("GPP String: \(gppString ?? "none")")
print("IDFA Consent: \(subjectToIDFAConsent)")
print("===================")
}
}
// Usage
TeadsPrivacy.shared.debugPrintPrivacyStatus()
#endif
Privacy Checklist
Implementation Checklist
-
Consent Management
- Request user consent before loading the ad
- Implement or integrate CMP
- Handle GDPR consent
- Handle CCPA compliance
- Support GPP if applicable
-
iOS Specific
- Implement ATT for iOS 14+
- Update Info.plist privacy descriptions
- Handle IDFA availability
-
Testing
- Test with consent given
- Test with consent denied
- Test consent changes
- Test different geographic regions
Info.plist Requirements
Add these keys to your Info.plist:
<key>NSUserTrackingUsageDescription</key>
<string>This app uses your data to provide personalized ads that support our free content.</string>
<key>SKAdNetworkItems</key>
<array>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>teads-network-id.skadnetwork</string>
</dict>
<!-- Add other network IDs as needed -->
</array>
Best Practices
1. Early Initialization
Initialize privacy settings as early as possible:
@main
struct YourApp: App {
init() {
// Initialize privacy first
ComprehensivePrivacyManager.shared.initializePrivacy()
// Then initialize SDK
Teads.configure(with: "YOUR_PARTNER_KEY")
}
}
Additional Resources
- IAB TCF v2.0 Specification
- IAB CCPA Compliance Framework
- IAB Global Privacy Platform
- Apple App Tracking Transparency
Support
For privacy-related questions:
- Email: privacy@teads.com
- Legal: legal@teads.com
Privacy is fundamental to building trust with your users. The Teads SDK helps you maintain that trust while maximizing monetization opportunities.