diff --git a/ConsentViewController/Classes/LocalStorage/SPUserDefaults.swift b/ConsentViewController/Classes/LocalStorage/SPUserDefaults.swift index f1355d215..670838ca4 100644 --- a/ConsentViewController/Classes/LocalStorage/SPUserDefaults.swift +++ b/ConsentViewController/Classes/LocalStorage/SPUserDefaults.swift @@ -99,7 +99,10 @@ class SPUserDefaults: SPLocalStorage { Self.USER_DATA_KEY: userData, Self.US_PRIVACY_STRING_KEY: usPrivacyString, Self.LOCAL_STATE_KEY: localState - ].merging(tcfData ?? [:]) { item, _ in item }} + ] + .merging(tcfData ?? [:]) { item, _ in item } + .merging(gppData ?? [:]) { item, _ in item } + } func clear() { localState = nil diff --git a/ConsentViewController/Classes/SPCampaigns.swift b/ConsentViewController/Classes/SPCampaigns.swift index 280aabf2b..6b9520b0e 100644 --- a/ConsentViewController/Classes/SPCampaigns.swift +++ b/ConsentViewController/Classes/SPCampaigns.swift @@ -40,11 +40,17 @@ public typealias SPTargetingParams = [String: String] let GPPConfig: SPGPPConfig? /** - Used by usNat campaigns only. Set this flag only if your app used an SDK older than `7.6.0`, use authenticated consent + Used by USNat campaigns only. Set this flag only if your app used an SDK older than `7.6.0`, use authenticated consent and has a CCPA campaign. */ let transitionCCPAAuth: Bool? + /** + Used by USNat campaigns. Set this flag if you want to continue having the value `IABUSPrivacy_String` + stored in the `UserDefaults`. Useful during the transition between CCPA and USNat campaigns. + */ + let supportLegacyUSPString: Bool? + @objc override public var description: String { """ SPCampaign @@ -52,6 +58,7 @@ public typealias SPTargetingParams = [String: String] - groupPmId: \(groupPmId as Any) - GPPConfig: \(GPPConfig as Any) - transitionCCPAAuth: \(transitionCCPAAuth as Any) + - supportLegacyUSPString: \(supportLegacyUSPString as Any) """ } @@ -59,12 +66,14 @@ public typealias SPTargetingParams = [String: String] targetingParams: SPTargetingParams = [:], groupPmId: String? = nil, gppConfig: SPGPPConfig? = nil, - transitionCCPAAuth: Bool? = nil + transitionCCPAAuth: Bool? = nil, + supportLegacyUSPString: Bool? = nil ) { self.targetingParams = targetingParams self.groupPmId = groupPmId self.GPPConfig = gppConfig self.transitionCCPAAuth = transitionCCPAAuth + self.supportLegacyUSPString = supportLegacyUSPString } @available(swift, obsoleted: 1.0) @@ -76,6 +85,7 @@ public typealias SPTargetingParams = [String: String] self.groupPmId = groupPmId self.GPPConfig = nil self.transitionCCPAAuth = nil + self.supportLegacyUSPString = nil } @available(swift, obsoleted: 1.0) @@ -83,12 +93,14 @@ public typealias SPTargetingParams = [String: String] targetingParams: SPTargetingParams = [:], groupPmId: String? = nil, gppConfig: SPGPPConfig? = nil, - transitionCCPAAuth: SPOptinalBool = .unset + transitionCCPAAuth: SPOptinalBool = .unset, + supportLegacyUSPString: SPOptinalBool = .unset ) { self.targetingParams = targetingParams self.groupPmId = groupPmId self.GPPConfig = gppConfig self.transitionCCPAAuth = transitionCCPAAuth.boolValue + self.supportLegacyUSPString = supportLegacyUSPString.boolValue } } diff --git a/ConsentViewController/Classes/SPGPPConfig.swift b/ConsentViewController/Classes/SPGPPConfig.swift index 72c6cf6fc..34be74036 100644 --- a/ConsentViewController/Classes/SPGPPConfig.swift +++ b/ConsentViewController/Classes/SPGPPConfig.swift @@ -42,6 +42,8 @@ import Foundation let MspaOptOutOptionMode: SPMspaTernaryFlag? let MspaServiceProviderMode: SPMspaTernaryFlag? + let uspString: Bool? + public init( MspaCoveredTransaction: SPMspaBinaryFlag? = nil, MspaOptOutOptionMode: SPMspaTernaryFlag? = nil, @@ -50,6 +52,7 @@ import Foundation self.MspaCoveredTransaction = MspaCoveredTransaction self.MspaOptOutOptionMode = MspaOptOutOptionMode self.MspaServiceProviderMode = MspaServiceProviderMode + uspString = nil } public init( @@ -60,5 +63,13 @@ import Foundation self.MspaCoveredTransaction = MspaCoveredTransaction self.MspaOptOutOptionMode = MspaOptOutOptionMode self.MspaServiceProviderMode = MspaServiceProviderMode + uspString = nil + } + + init(uspString: Bool?) { + self.uspString = uspString + MspaCoveredTransaction = nil + MspaOptOutOptionMode = nil + MspaServiceProviderMode = nil } } diff --git a/ConsentViewController/Classes/SourcePointClient/SourcepointClientCoordinator.swift b/ConsentViewController/Classes/SourcePointClient/SourcepointClientCoordinator.swift index 86a42c7f2..a48daf3ff 100644 --- a/ConsentViewController/Classes/SourcePointClient/SourcepointClientCoordinator.swift +++ b/ConsentViewController/Classes/SourcePointClient/SourcepointClientCoordinator.swift @@ -324,7 +324,10 @@ class SourcepointClientCoordinator: SPClientCoordinator { self.propertyName = propertyName self.language = language self.campaigns = campaigns - self.includeData = IncludeData(gppConfig: campaigns.ccpa?.GPPConfig ?? SPGPPConfig()) + self.includeData = IncludeData( + gppConfig: campaigns.ccpa?.GPPConfig ?? + SPGPPConfig(uspString: campaigns.usnat?.supportLegacyUSPString) + ) self.storage = storage self.spClient = spClient ?? SourcePointClient( accountId: accountId, diff --git a/Example/ConsentViewController_ExampleTests/SPClientCoordinator/SPClientCoordinatorSpec.swift b/Example/ConsentViewController_ExampleTests/SPClientCoordinator/SPClientCoordinatorSpec.swift index 5ea1e3377..fe3167d72 100644 --- a/Example/ConsentViewController_ExampleTests/SPClientCoordinator/SPClientCoordinatorSpec.swift +++ b/Example/ConsentViewController_ExampleTests/SPClientCoordinator/SPClientCoordinatorSpec.swift @@ -498,6 +498,22 @@ class SPClientCoordinatorSpec: QuickSpec { coordinator = coordinatorFor(campaigns: SPCampaigns(usnat: SPCampaign())) } + it("can support legacy uspstring") { + coordinator = coordinatorFor( + campaigns: SPCampaigns( + usnat: SPCampaign(supportLegacyUSPString: true) + ) + ) + waitUntil { done in + coordinator.loadMessages(forAuthId: nil, pubData: nil) { _ in + expect( + coordinator.userData.usnat?.consents?.GPPData?["IABUSPrivacy_String"]?.stringValue + ).notTo(beEmpty()) + done() + } + } + } + describe("with authId") { it("persists consent even after cleaning all data") { waitUntil { done in diff --git a/Example/Pods/Local Podspecs/ConsentViewController.podspec.json b/Example/Pods/Local Podspecs/ConsentViewController.podspec.json index c8dd85812..0015892ba 100644 --- a/Example/Pods/Local Podspecs/ConsentViewController.podspec.json +++ b/Example/Pods/Local Podspecs/ConsentViewController.podspec.json @@ -39,7 +39,7 @@ }, "resources": "ConsentViewController/**/*.{js,json,png}", "info_plist": { - "SPEnv": "prod" + "SPEnv": "preprod" }, "swift_version": "5.1" } diff --git a/Example/Pods/Target Support Files/ConsentViewController-iOS/ConsentViewController-iOS-Info.plist b/Example/Pods/Target Support Files/ConsentViewController-iOS/ConsentViewController-iOS-Info.plist index 1214ed669..119ad4579 100644 --- a/Example/Pods/Target Support Files/ConsentViewController-iOS/ConsentViewController-iOS-Info.plist +++ b/Example/Pods/Target Support Files/ConsentViewController-iOS/ConsentViewController-iOS-Info.plist @@ -2,27 +2,27 @@ - CFBundleDevelopmentRegion - ${PODS_DEVELOPMENT_LANGUAGE} - CFBundleExecutable - ${EXECUTABLE_NAME} - CFBundleIdentifier - ${PRODUCT_BUNDLE_IDENTIFIER} - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - ${PRODUCT_NAME} - CFBundlePackageType - FMWK - CFBundleShortVersionString - 7.6.1 - CFBundleSignature - ???? - CFBundleVersion - ${CURRENT_PROJECT_VERSION} - NSPrincipalClass - - SPEnv - prod + CFBundleDevelopmentRegion + ${PODS_DEVELOPMENT_LANGUAGE} + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 7.6.1 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + SPEnv + prod diff --git a/Example/Pods/Target Support Files/ConsentViewController-tvOS/ConsentViewController-tvOS-Info.plist b/Example/Pods/Target Support Files/ConsentViewController-tvOS/ConsentViewController-tvOS-Info.plist index 1214ed669..119ad4579 100644 --- a/Example/Pods/Target Support Files/ConsentViewController-tvOS/ConsentViewController-tvOS-Info.plist +++ b/Example/Pods/Target Support Files/ConsentViewController-tvOS/ConsentViewController-tvOS-Info.plist @@ -2,27 +2,27 @@ - CFBundleDevelopmentRegion - ${PODS_DEVELOPMENT_LANGUAGE} - CFBundleExecutable - ${EXECUTABLE_NAME} - CFBundleIdentifier - ${PRODUCT_BUNDLE_IDENTIFIER} - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - ${PRODUCT_NAME} - CFBundlePackageType - FMWK - CFBundleShortVersionString - 7.6.1 - CFBundleSignature - ???? - CFBundleVersion - ${CURRENT_PROJECT_VERSION} - NSPrincipalClass - - SPEnv - prod + CFBundleDevelopmentRegion + ${PODS_DEVELOPMENT_LANGUAGE} + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 7.6.1 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + SPEnv + prod diff --git a/README.md b/README.md index c81074c2a..cc3950b4f 100644 --- a/README.md +++ b/README.md @@ -491,6 +491,17 @@ var consentManager = SPConsentManager( ) ``` +## Support U.S. Privacy (Legacy) with U.S. Multi-State Privacy + +If you're transitioning from U.S. Privacy (Legacy) to U.S. Multi-State Privacy, you may want to continue supporting the legacy US privacy string (`IABUSPrivacy_String`). +To do so, when instantiating the SDK, make sure to set the flag `.supportLegacyUSPString` to true. Example: +```swift +var consentManager = SPConsentManager( + ... + campaigns: SPCampaigns(usnat: SPCampaign(supportLegacyUSPString: true)), // <== here + delegate: self +) +``` ## Configuring the Message/Consents timeout