From 166a687c89a2e430bd29f2e45ca8a551a072a0cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Herculano?= Date: Wed, 7 Feb 2024 19:40:45 +0100 Subject: [PATCH 1/8] add supportLegacyUSPString flag --- .../Classes/LocalStorage/SPUserDefaults.swift | 4 +++- .../Classes/SPCampaigns.swift | 18 +++++++++++++++--- .../Classes/SPGPPConfig.swift | 11 +++++++++++ .../SourcepointClientCoordinator.swift | 5 ++++- .../SPClientCoordinatorSpec.swift | 12 ++++++++++++ 5 files changed, 45 insertions(+), 5 deletions(-) diff --git a/ConsentViewController/Classes/LocalStorage/SPUserDefaults.swift b/ConsentViewController/Classes/LocalStorage/SPUserDefaults.swift index f1355d215..8d20b3470 100644 --- a/ConsentViewController/Classes/LocalStorage/SPUserDefaults.swift +++ b/ConsentViewController/Classes/LocalStorage/SPUserDefaults.swift @@ -99,7 +99,9 @@ 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..8c5013928 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.ccpa?.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..8843f1e7f 100644 --- a/Example/ConsentViewController_ExampleTests/SPClientCoordinator/SPClientCoordinatorSpec.swift +++ b/Example/ConsentViewController_ExampleTests/SPClientCoordinator/SPClientCoordinatorSpec.swift @@ -498,6 +498,18 @@ class SPClientCoordinatorSpec: QuickSpec { coordinator = coordinatorFor(campaigns: SPCampaigns(usnat: SPCampaign())) } + it("can support legacy uspstring") { + coordinator = coordinatorFor( + campaigns: SPCampaigns( + usnat: SPCampaign(supportLegacyUSPString: true) + ) + ) + coordinator.loadMessages(forAuthId: nil, pubData: nil) { _ in + expect(UserDefaults.standard.string(forKey: "IABUSPrivacy_String")).notTo(beNil()) + done() + } + } + describe("with authId") { it("persists consent even after cleaning all data") { waitUntil { done in From b3fd865b145b146f9430e7d96420036bea299b71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Herculano?= Date: Wed, 7 Feb 2024 19:46:29 +0100 Subject: [PATCH 2/8] update README about supportLegacyUSPString --- README.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/README.md b/README.md index c81074c2a..4094d659a 100644 --- a/README.md +++ b/README.md @@ -491,6 +491,17 @@ var consentManager = SPConsentManager( ) ``` +## Keeping support to legacy CCPA privacy string + +If you're transitioning from CCPA to USNat, odds are you want to keep supporting the legacy CCPA 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 From c751ce453e6ca14d6d5799bad902c025abd5c007 Mon Sep 17 00:00:00 2001 From: tom-win87 <76440079+tom-win87@users.noreply.github.com> Date: Thu, 8 Feb 2024 10:15:51 -0500 Subject: [PATCH 3/8] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 4094d659a..cc3950b4f 100644 --- a/README.md +++ b/README.md @@ -491,9 +491,9 @@ var consentManager = SPConsentManager( ) ``` -## Keeping support to legacy CCPA privacy string +## Support U.S. Privacy (Legacy) with U.S. Multi-State Privacy -If you're transitioning from CCPA to USNat, odds are you want to keep supporting the legacy CCPA privacy string (`IABUSPrivacy_String`). +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( From daaa510b48fa86ef352fc5676926018c96a39878 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Herculano?= Date: Fri, 9 Feb 2024 11:59:21 +0100 Subject: [PATCH 4/8] point SDK to preprod --- ConsentViewController.podspec | 2 +- Example/Pods/Local Podspecs/ConsentViewController.podspec.json | 2 +- .../ConsentViewController-iOS-Info.plist | 2 +- .../ConsentViewController-tvOS-Info.plist | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ConsentViewController.podspec b/ConsentViewController.podspec index e137f0e3c..64edf6f42 100644 --- a/ConsentViewController.podspec +++ b/ConsentViewController.podspec @@ -16,6 +16,6 @@ Pod::Spec.new do |s| s.resource_bundles = { 'ConsentViewController' => ['ConsentViewController/Assets/**/*', 'Pod/Classes/**/*.{storyboard,xib,xcassets,json,imageset,png,js}'] } s.resources = "ConsentViewController/**/*.{js,json,png}" s.info_plist = { - 'SPEnv' => 'prod' + 'SPEnv' => 'preprod' } end 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..7ee2cb743 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 @@ -23,6 +23,6 @@ NSPrincipalClass SPEnv - prod + preprod 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..7ee2cb743 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 @@ -23,6 +23,6 @@ NSPrincipalClass SPEnv - prod + preprod From bf75bfe20f5d5a092174415ac19aadf69b7ecdf6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Herculano?= Date: Fri, 9 Feb 2024 11:59:47 +0100 Subject: [PATCH 5/8] fix typo --- .../Classes/LocalStorage/SPUserDefaults.swift | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ConsentViewController/Classes/LocalStorage/SPUserDefaults.swift b/ConsentViewController/Classes/LocalStorage/SPUserDefaults.swift index 8d20b3470..670838ca4 100644 --- a/ConsentViewController/Classes/LocalStorage/SPUserDefaults.swift +++ b/ConsentViewController/Classes/LocalStorage/SPUserDefaults.swift @@ -100,8 +100,9 @@ class SPUserDefaults: SPLocalStorage { Self.US_PRIVACY_STRING_KEY: usPrivacyString, Self.LOCAL_STATE_KEY: localState ] - .merging(tcfData ?? [:]) { item, _ in item }} - .merging(gppData ?? [:]) { item, _ in item }} + .merging(tcfData ?? [:]) { item, _ in item } + .merging(gppData ?? [:]) { item, _ in item } + } func clear() { localState = nil From 4fa3c0528dca95a1b5ca9d1da821633c7294a898 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Herculano?= Date: Fri, 9 Feb 2024 12:00:12 +0100 Subject: [PATCH 6/8] set GPPConfig on spclientcoordinator --- .../SourcePointClient/SourcepointClientCoordinator.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ConsentViewController/Classes/SourcePointClient/SourcepointClientCoordinator.swift b/ConsentViewController/Classes/SourcePointClient/SourcepointClientCoordinator.swift index 8c5013928..a48daf3ff 100644 --- a/ConsentViewController/Classes/SourcePointClient/SourcepointClientCoordinator.swift +++ b/ConsentViewController/Classes/SourcePointClient/SourcepointClientCoordinator.swift @@ -326,7 +326,7 @@ class SourcepointClientCoordinator: SPClientCoordinator { self.campaigns = campaigns self.includeData = IncludeData( gppConfig: campaigns.ccpa?.GPPConfig ?? - SPGPPConfig(uspString: campaigns.ccpa?.supportLegacyUSPString) + SPGPPConfig(uspString: campaigns.usnat?.supportLegacyUSPString) ) self.storage = storage self.spClient = spClient ?? SourcePointClient( From c19461b4954ce841701c57b6e45b06dad2ee6c0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Herculano?= Date: Fri, 9 Feb 2024 12:00:23 +0100 Subject: [PATCH 7/8] implement test for legacy uspstring --- .../SPClientCoordinator/SPClientCoordinatorSpec.swift | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/Example/ConsentViewController_ExampleTests/SPClientCoordinator/SPClientCoordinatorSpec.swift b/Example/ConsentViewController_ExampleTests/SPClientCoordinator/SPClientCoordinatorSpec.swift index 8843f1e7f..fe3167d72 100644 --- a/Example/ConsentViewController_ExampleTests/SPClientCoordinator/SPClientCoordinatorSpec.swift +++ b/Example/ConsentViewController_ExampleTests/SPClientCoordinator/SPClientCoordinatorSpec.swift @@ -504,9 +504,13 @@ class SPClientCoordinatorSpec: QuickSpec { usnat: SPCampaign(supportLegacyUSPString: true) ) ) - coordinator.loadMessages(forAuthId: nil, pubData: nil) { _ in - expect(UserDefaults.standard.string(forKey: "IABUSPrivacy_String")).notTo(beNil()) - done() + waitUntil { done in + coordinator.loadMessages(forAuthId: nil, pubData: nil) { _ in + expect( + coordinator.userData.usnat?.consents?.GPPData?["IABUSPrivacy_String"]?.stringValue + ).notTo(beEmpty()) + done() + } } } From 270de6bf31e0de7cb8d9cf948122fe2b414a7523 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Herculano?= Date: Fri, 23 Feb 2024 17:27:51 +0100 Subject: [PATCH 8/8] point SDK back to prod --- ConsentViewController.podspec | 2 +- .../ConsentViewController-iOS-Info.plist | 44 +++++++++---------- .../ConsentViewController-tvOS-Info.plist | 44 +++++++++---------- 3 files changed, 45 insertions(+), 45 deletions(-) diff --git a/ConsentViewController.podspec b/ConsentViewController.podspec index 64edf6f42..e137f0e3c 100644 --- a/ConsentViewController.podspec +++ b/ConsentViewController.podspec @@ -16,6 +16,6 @@ Pod::Spec.new do |s| s.resource_bundles = { 'ConsentViewController' => ['ConsentViewController/Assets/**/*', 'Pod/Classes/**/*.{storyboard,xib,xcassets,json,imageset,png,js}'] } s.resources = "ConsentViewController/**/*.{js,json,png}" s.info_plist = { - 'SPEnv' => 'preprod' + 'SPEnv' => 'prod' } end 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 7ee2cb743..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 - preprod + 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 7ee2cb743..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 - preprod + 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