The IAB Tech Lab's Global Privacy Platform's (GPP) Multi-State Privacy String (MSPS) is a signal that notifies downstream partners that participating publishers have provided end-users with specific notice and choice over data processing activities on their properties.
Sourcepoint has collated a checklist for your organization to ensure the successful migration of your web and app properties' campaigns to the GPP specification.
- UI/UX updates
- Supportability
- Technical changes
- Transfer end-user opt-in/opt-out preferences
- GPP Multi-State Privacy String (MSPS) APIs
- GPP Multi-State Privacy String Sections
- Migration checklist
- Follow GPP Multi-State Privacy String (MSPS) - Transition readiness
Note: As a reminder, all framework participants must transition to GPP Multi-State Privacy String (MSPS) by January 31st, 2024.
UI/UX updates
Once your account is enabled for transition, your organization will experience the following changes in the Sourcepoint portal:
Before | → | After |
Click Vendor Management on the left-hand panel and select U.S. Multi-State Privacy from the subsequent menu.
Click New on the following page.
The U.S. Multi-State Privacy vendor list builder will guide you through the configuration process.
When viewing the campaign entities for a property, click Messages and select U.S. Multi-State Privacy Messages from the dropdown menu.
Click Web/Webview from the subsequent menu.
From the next page, select either the First Layer or Privacy Manager tab and click + New Message to access the U.S. Multi-State Privacy Message builder.
Supportability
Property type | Support |
Web |
Supported on web properties that utilize Soucepoint's Unified script in its implementation. |
iOS (mobile) | Supported on app properties that utilize Soucepoint's SDK 7.5.0 + |
Android (mobile) | Supported on app properties that utilize Soucepoint's SDK 7.6.0 + |
Technical changes
There are two different way to implement Sourcepoint's GPP MSPS solution for your property. In order to migrate your property to the GPP MSPS, your organization must choose one of the approach below and perform the technical changes on existing properties running a U.S. Privacy (Legacy) campaign:
In this section we will cover the technical changes necessary to replace an existing U.S. Privacy (Legacy) campaign with GPP MSPS.
-
Remove
U.S. privacy
stub file from the property.
<script>(function () { var e = false; var c = window; var t = document; function r() { if (!c.frames["__uspapiLocator"]) { if (t.body) { var a = t.body; var e = t.createElement("iframe"); e.style.cssText = "display:none"; e.name = "__uspapiLocator"; a.appendChild(e) } else { setTimeout(r, 5) } } } r(); function p() { var a = arguments; __uspapi.a = __uspapi.a || []; if (!a.length) { return __uspapi.a } else if (a[0] === "ping") { a[2]({ gdprAppliesGlobally: e, cmpLoaded: false }, true) } else { __uspapi.a.push([].slice.apply(a)) } } function l(t) { var r = typeof t.data === "string"; try { var a = r ? JSON.parse(t.data) : t.data; if (a.__cmpCall) { var n = a.__cmpCall; c.__uspapi(n.command, n.parameter, function (a, e) { var c = { __cmpReturn: { returnValue: a, success: e, callId: n.callId } }; t.source.postMessage(r ? JSON.stringify(c) : c, "*") }) } } catch (a) { } } if (typeof __uspapi !== "function") { c.__uspapi = p; __uspapi.msgHandler = l; c.addEventListener("message", l, false) } })(); </script>
-
Add
GPP
stub file to the property.
//Example only. Please use stub file generated in Sourcepoint portal as it may have changed
<script>
window.__gpp_addFrame=function(e){if(!window.frames[e])if(document.body){var t=document.createElement("iframe");t.style.cssText="display:none",t.name=e,document.body.appendChild(t)}else window.setTimeout(window.__gpp_addFrame,10,e)},window.__gpp_stub=function(){var e=arguments;if(__gpp.queue=__gpp.queue||[],__gpp.events=__gpp.events||[],!e.length||1==e.length&&"queue"==e[0])return __gpp.queue;if(1==e.length&&"events"==e[0])return __gpp.events;var t=e[0],p=e.length>1?e[1]:null,s=e.length>2?e[2]:null;if("ping"===t)p({gppVersion:"1.1",cmpStatus:"stub",cmpDisplayStatus:"hidden",signalStatus:"not ready",supportedAPIs:["2:tcfeuv2","5:tcfcav1","6:uspv1","7:usnat","8:usca","9:usva","10:usco","11:usut","12:usct"],cmpId:0,sectionList:[],applicableSections:[],gppString:"",parsedSections:{}},!0);else if("addEventListener"===t){"lastId"in __gpp||(__gpp.lastId=0),__gpp.lastId++;var n=__gpp.lastId;__gpp.events.push({id:n,callback:p,parameter:s}),p({eventName:"listenerRegistered",listenerId:n,data:!0,pingData:{gppVersion:"1.1",cmpStatus:"stub",cmpDisplayStatus:"hidden",signalStatus:"not ready",supportedAPIs:["2:tcfeuv2","5:tcfcav1","6:uspv1","7:usnat","8:usca","9:usva","10:usco","11:usut","12:usct"],cmpId:0,sectionList:[],applicableSections:[],gppString:"",parsedSections:{}}},!0)}else if("removeEventListener"===t){for(var a=!1,i=0;i<__gpp.events.length;i++)if(__gpp.events[i].id==s){__gpp.events.splice(i,1),a=!0;break}p({eventName:"listenerRemoved",listenerId:s,data:a,pingData:{gppVersion:"1.1",cmpStatus:"stub",cmpDisplayStatus:"hidden",signalStatus:"not ready",supportedAPIs:["2:tcfeuv2","5:tcfcav1","6:uspv1","7:usnat","8:usca","9:usva","10:usco","11:usut","12:usct"],cmpId:0,sectionList:[],applicableSections:[],gppString:"",parsedSections:{}}},!0)}else"hasSection"===t?p(!1,!0):"getSection"===t||"getField"===t?p(null,!0):__gpp.queue.push([].slice.apply(e))},window.__gpp_msghandler=function(e){var t="string"==typeof e.data;try{var p=t?JSON.parse(e.data):e.data}catch(e){p=null}if("object"==typeof p&&null!==p&&"__gppCall"in p){var s=p.__gppCall;window.__gpp(s.command,(function(p,n){var a={__gppReturn:{returnValue:p,success:n,callId:s.callId}};e.source.postMessage(t?JSON.stringify(a):a,"*")}),"parameter"in s?s.parameter:null,"version"in s?s.version:"1.1")}},"__gpp"in window&&"function"==typeof window.__gpp||(window.__gpp=window.__gpp_stub,window.addEventListener("message",window.__gpp_msghandler,!1),window.__gpp_addFrame("__gppLocator"));
</script> -
Remove
ccpa
object and any parameters it may contain from the configuration script.
window._sp_queue = []; window._sp_ = { config: { accountId: 0000, baseEndpoint: 'https://cdn.privacy-mgmt.com', propertyHref: 'https://demoacct.com',
ccpa: { targetingParams:{ darkmode: true } }, -
Add
usnat
object to the configuration script. Additionally, you may include targetingParams within the object to set key/value pairs that will be used to take a decision within the scenario builder.
window._sp_queue = []; window._sp_ = { config: { accountId: 0000, baseEndpoint: 'https://cdn.privacy-mgmt.com', propertyHref: 'https://demoacct.com', usnat: { targetingParams:{ darkmode: true } },
- If your organization has implemented a link/button on-page that resurfaces your privacy manager, replace the U.S. Privacy (Legacy) code snippet with the U.S. Multi-State Privacy code snippet.
window._sp_.ccpa.loadPrivacyManagerModal(USP_PM_ID)window._sp_.usnat.loadPrivacyManagerModal('USNAT_PM_ID')
- Remove
ccpa: SPCampaign()
fromcampaigns
parameter in theSPConsentManager
initializer.
lazy var consentManager: SPConsentManager = { SPConsentManager( accountId: 1584, propertyId: 12345, propertyName: try! SPPropertyName("example.demo"), campaigns: SPCampaigns(
ccpa: SPCampaign()), delegate: self )}() - Add
usnat: SPCampaign()
tocampaigns
parameter in theSPConsentManager
initializer.
lazy var consentManager: SPConsentManager = { SPConsentManager( accountId: 1584, propertyId: 12345, propertyName: try! SPPropertyName("example.demo"), campaigns: SPCampaigns( usnat: SPCampaign() ), delegate: self )}()
- If your organization has implemented a link/button that resurfaces your privacy manager, replace the U.S. Privacy (Legacy) code snippet with the U.S. Multi-State Privacy code snippet.
.loadCCPAPrivacyManager(withId: String, tab: SPPrivacyManagerTab = .Default).loadUSNATPrivacyManager(withId: String, tab: SPPrivacyManagerTab = .Default)
- Remove
CampaignType.CCPA
from the config object
val cmpConfig : SpConfig = config { accountId = 1584 propertyId = 12345 propertyName = "example.demo" messLanguage = MessageLanguage.ENGLISH // Optional, default ENGLISH campaignsEnv = CampaignsEnv.PUBLIC // Optional, default PUBLIC messageTimeout = 15000 // Optional, default 10000ms
+CampaignType.CCPA} - Add
CampaignType.USNAT
to the config object
val cmpConfig : SpConfig = config { accountId = 1584 propertyId = 12345 propertyName = "example.demo" messLanguage = MessageLanguage.ENGLISH // Optional, default ENGLISH campaignsEnv = CampaignsEnv.PUBLIC // Optional, default PUBLIC messageTimeout = 15000 // Optional, default 10000ms +CampaignType.USNAT }
- If your organization has implemented a link/button that resurfaces your privacy manager, replace
CampaignType.CCPA
withCampaignType.USNAT
in thespConsentLib.loadPrivacyManager
call.
//ORIGINAL
//... IMPLICIT message type selection spConsentLib.loadPrivacyManager( "<PM_ID>", PMTab.PURPOSES,CampaignType.CCPA) //... //... EXPLICIT message type selection spConsentLib.loadPrivacyManager( "<PM_ID>", PMTab.PURPOSES,CampaignType.CCPA,MOBILE ) //...
//NEW //... IMPLICIT message type selection spConsentLib.loadPrivacyManager( "<PM_ID>", PMTab.PURPOSES, CampaignType.USNAT ) //... //... EXPLICIT message type selection spConsentLib.loadPrivacyManager( "<PM_ID>", PMTab.PURPOSES, CampaignType.USNAT, MOBILE ) //...
In this section, we will cover the technical changes necessary to implement Sourcepoint's GPP MSPS solution on a property while still supporting the U.S. Privacy API (__uspapi)
commands and the setting of the uspString
.
Note: Since U.S. Privacy (Legacy) does not have support for sensitive data categories, any organization who requires sensitive data opt-ins should not use this approach and instead use the Replace U.S. Privacy (Legacy) with GPP Multi-State Privacy String (MSPS) approach.
Additionally, this method should not be used by organizations who only require Sharing of Personal Information/Targeted Advertising. A uspString
will only be set if you use either of the following privacy choices:
- Sale of Personal Information
- Sale or Sharing of Personal Information/Targeted Advertising
-
Keep
U.S. privacy
stub file on the property.
<script>(function () { var e = false; var c = window; var t = document; function r() { if (!c.frames["__uspapiLocator"]) { if (t.body) { var a = t.body; var e = t.createElement("iframe"); e.style.cssText = "display:none"; e.name = "__uspapiLocator"; a.appendChild(e) } else { setTimeout(r, 5) } } } r(); function p() { var a = arguments; __uspapi.a = __uspapi.a || []; if (!a.length) { return __uspapi.a } else if (a[0] === "ping") { a[2]({ gdprAppliesGlobally: e, cmpLoaded: false }, true) } else { __uspapi.a.push([].slice.apply(a)) } } function l(t) { var r = typeof t.data === "string"; try { var a = r ? JSON.parse(t.data) : t.data; if (a.__cmpCall) { var n = a.__cmpCall; c.__uspapi(n.command, n.parameter, function (a, e) { var c = { __cmpReturn: { returnValue: a, success: e, callId: n.callId } }; t.source.postMessage(r ? JSON.stringify(c) : c, "*") }) } } catch (a) { } } if (typeof __uspapi !== "function") { c.__uspapi = p; __uspapi.msgHandler = l; c.addEventListener("message", l, false) } })(); </script>
-
Add
GPP
stub file to the property.
//Example only. Please use stub file generated in Sourcepoint portal as it may have changed
<script>
window.__gpp_addFrame=function(e){if(!window.frames[e])if(document.body){var t=document.createElement("iframe");t.style.cssText="display:none",t.name=e,document.body.appendChild(t)}else window.setTimeout(window.__gpp_addFrame,10,e)},window.__gpp_stub=function(){var e=arguments;if(__gpp.queue=__gpp.queue||[],__gpp.events=__gpp.events||[],!e.length||1==e.length&&"queue"==e[0])return __gpp.queue;if(1==e.length&&"events"==e[0])return __gpp.events;var t=e[0],p=e.length>1?e[1]:null,s=e.length>2?e[2]:null;if("ping"===t)p({gppVersion:"1.1",cmpStatus:"stub",cmpDisplayStatus:"hidden",signalStatus:"not ready",supportedAPIs:["2:tcfeuv2","5:tcfcav1","6:uspv1","7:usnat","8:usca","9:usva","10:usco","11:usut","12:usct"],cmpId:0,sectionList:[],applicableSections:[],gppString:"",parsedSections:{}},!0);else if("addEventListener"===t){"lastId"in __gpp||(__gpp.lastId=0),__gpp.lastId++;var n=__gpp.lastId;__gpp.events.push({id:n,callback:p,parameter:s}),p({eventName:"listenerRegistered",listenerId:n,data:!0,pingData:{gppVersion:"1.1",cmpStatus:"stub",cmpDisplayStatus:"hidden",signalStatus:"not ready",supportedAPIs:["2:tcfeuv2","5:tcfcav1","6:uspv1","7:usnat","8:usca","9:usva","10:usco","11:usut","12:usct"],cmpId:0,sectionList:[],applicableSections:[],gppString:"",parsedSections:{}}},!0)}else if("removeEventListener"===t){for(var a=!1,i=0;i<__gpp.events.length;i++)if(__gpp.events[i].id==s){__gpp.events.splice(i,1),a=!0;break}p({eventName:"listenerRemoved",listenerId:s,data:a,pingData:{gppVersion:"1.1",cmpStatus:"stub",cmpDisplayStatus:"hidden",signalStatus:"not ready",supportedAPIs:["2:tcfeuv2","5:tcfcav1","6:uspv1","7:usnat","8:usca","9:usva","10:usco","11:usut","12:usct"],cmpId:0,sectionList:[],applicableSections:[],gppString:"",parsedSections:{}}},!0)}else"hasSection"===t?p(!1,!0):"getSection"===t||"getField"===t?p(null,!0):__gpp.queue.push([].slice.apply(e))},window.__gpp_msghandler=function(e){var t="string"==typeof e.data;try{var p=t?JSON.parse(e.data):e.data}catch(e){p=null}if("object"==typeof p&&null!==p&&"__gppCall"in p){var s=p.__gppCall;window.__gpp(s.command,(function(p,n){var a={__gppReturn:{returnValue:p,success:n,callId:s.callId}};e.source.postMessage(t?JSON.stringify(a):a,"*")}),"parameter"in s?s.parameter:null,"version"in s?s.version:"1.1")}},"__gpp"in window&&"function"==typeof window.__gpp||(window.__gpp=window.__gpp_stub,window.addEventListener("message",window.__gpp_msghandler,!1),window.__gpp_addFrame("__gppLocator"));
</script> -
Remove
ccpa
object and any parameters it may contain from the configuration script.
window._sp_queue = []; window._sp_ = { config: { accountId: 0000, baseEndpoint: 'https://cdn.privacy-mgmt.com', propertyHref: 'https://demoacct.com',
ccpa: { targetingParams:{ darkmode: true } }, -
Add
usnat
object to the configuration script. Additionally, you may include targetingParams within the object to set key/value pairs that will be used to take a decision within the scenario builder.
window._sp_queue = []; window._sp_ = { config: { accountId: 0000, baseEndpoint: 'https://cdn.privacy-mgmt.com', propertyHref: 'https://demoacct.com', usnat: { targetingParams:{ darkmode: true } },
-
Add
includeUspApi: true
flag to theusnat
object.
window._sp_queue = []; window._sp_ = { config: { accountId: 0000, baseEndpoint: 'https://cdn.privacy-mgmt.com', propertyHref: 'https://demoacct.com', usnat: { includeUspApi: true } },
- If your organization has implemented a link/button on-page that resurfaces your privacy manager, replace the U.S. Privacy (Legacy) code snippet with the U.S. Multi-State Privacy code snippet.
window._sp_.ccpa.loadPrivacyManagerModal(USP_PM_ID)window._sp_.usnat.loadPrivacyManagerModal('USNAT_PM_ID')
Transfer end-user opt-in/opt-out preferences
When migrating your web/app property from U.S. Privacy to GPP MSPS, Sourcepoint allows your organization to preserve your end-users' opt-in/out out preferences across your frameworks.
Note: If an end-user rejected a vendor or category for U.S. Privacy, Sourcepoint will set the Sharing of Personal Information Targeted Advertisting and Sale of Personal Information privacy choices or the Sale or Share of Personal Information/Targeted Advertising privacy choice (depending on your configuration) to opted-out when the preferences are transferred.
When migrating your web property from U.S. Privacy to GPP MSPS, Sourcepoint will automatically detect previous end-user opt-in/opt-out preferences for U.S. Privacy and persist those preferences across to GPP MSPS.
A key exception to this automation is if your organization used authenticated consent in your U.S. Privacy configuration.
If authenticated consent was used in your U.S. Privacy configuration you will need to set the transitionCCPAAuth
flag within the usnat
object. This flag, ensures Sourcepoint looks for authenticated consent within U.S. Privacy profiles and carry that over to GPP MSPS, even if the user current doesn't have U.S. Privacy local data.
window._sp_queue = [];
window._sp_ = {
config: {
accountId: 0000,
baseEndpoint: 'https://cdn.privacy-mgmt.com',
propertyHref: 'https://demoacct.com',
usnat: {
transitionCCPAAuth: true
}
},
When migrating your iOS app from U.S. Privacy to GPP MSPS, Sourcepoint's iOS SDK will automatically detect previous end-user opt-in/opt-out preferences for U.S. Privacy and persist those preferences across to GPP MSPS.
A key exception to this automation is if your organization used authenticated consent in your U.S. Privacy configuration.
If authenticated consent was used in your U.S. Privacy configuration you will need to set the transitionCCPAAuth
flag when configuring campaigns to be loaded by the SDK. This flag, ensures the SDK will look for authenticated consent within U.S. Privacy profiles and carry that over to GPP MSPS, even if the user current doesn't have U.S. Privacy local data (on a fresh install, for example).
var consentManager = SPConsentManager(
accountId: accId,
propertyId: propId,
propertyName: try! SPPropertyName(propName),
campaigns: SPCampaigns(usnat: SPCampaign(transitionCCPAAuth: true)),
delegate: self
)
When migrating your Android app from U.S. Privacy to GPP MSPS, Sourcepoint's Android SDK will automatically detect previous end-user opt-in/opt-out preferences for U.S. Privacy and persist those preferences across to GPP MSPS.
A key exception to this automation is if your organization used authenticated consent in your U.S. Privacy configuration.
If authenticated consent was used in your U.S. Privacy configuration you will need to set the ConfigOption.TRANSITION_CCPA_AUTH
flag in your configuration. This flag, ensures the SDK will look for authenticated consent within U.S. Privacy profiles and carry that over to GPP MSPS, even if the user current doesn't have U.S. Privacy local data (on a fresh install, for example).
private final SpConfig spConfig = new SpConfigDataBuilder()
.addAccountId(22)
.addPropertyName("automation-mobile-usnat")
.addPropertyId(34049)
.addMessageLanguage(MessageLanguage.ENGLISH)
.addMessageTimeout(5000)
.addCampaignsEnv(CampaignsEnv.PUBLIC)
.addCampaign(new SpCampaign(CampaignType.USNAT, Collections.emptyList(), Set.of(ConfigOption.TRANSITION_CCPA_AUTH)))
.addCampaign(CampaignType.GDPR)
.build();
GPP Multi-State Privacy String (MSPS) API
Information on the standard commands used with __gpp()
function can be found in our developer hub:
Note: Historically, organizations who have used U.S. Privacy (Legacy) campaigns have looked at the uspString
(e.g. 1YNN
) to determine the applicability of the framework to an end-user. When using U.S. Multi-State Privacy campaigns, the applicability of a section to an end-user within the Global Privacy Platform MSPS framework is determined by looking at the applicableSections
response in the ping
command.
GPP Multi-State Privacy String Sections
By default, Sourcepoint will set the respective U.S. State privacy section for each of the following U.S. states that are added to the framework territories of a property's vendor list: California, Colorado, Connecticut, Utah, and Virginia.
The U.S. National Privacy section will be set for all other states/regions added to the framework territories of a property's vendor list.
Migration checklist
In this section, we have broken down the components/entities that need to be created within the Sourcepoint portal before launching a campaign on a property that adheres to the GPP MSPS specification.
Note: In order to migrate your end-user's opt-in/opt-out preferences for a property, the siteId
for the migrating property must be the same. Sourcepoint does not support the transitioning of end-user's opt-in/opt-out preferences across different properties.
Step | Resource(s) | |
1 | Assign Permissions |
There are two new permissions related to Sourcepoint's GPP MSPS solution: Regulation Settings - USNat and Reporting USNat. These permissions control a user's ability to configure a U.S. Multi-State Privacy vendor list and configure scheduled reports for U.S. Multi-State Privacy in your account, respectively. |
2 | Create U.S. Multi-State Privacy vendor list | |
3 | Create U.S. Multi-State Privacy privacy manager/ OTT message | |
4 | Create U.S. Multi-State Privacy first layer message | |
5 | Create U.S. Multi-State Privacy scenario | |
6 | Create U.S. Multi-State Privacy partition set | |
7 | Update U.S. Multi-State Privacy code on property | |
8 | Launch U.S. Multi-State Privacy campaign | |
9 | Test GPP MSPS | |
10 | Reports |
Currently, Sourcepoint's U.S. Multi-State Privacy solution only supports scheduled reports. |
Follow GPP Multi-State Privacy String (MSPS) - Transition readiness
We strongly encourage all clients to follow this article in order to receive updates of how Sourcepoint is supporting your organization's enablement of GPP Multi-State Privacy String (MSPS).
We will regularly update this article with comments as our support for the transition evolves. By following this article, you will receive email notifications whenever these comments are posted.
Note: Only users with approved and valid Sourcepoint credentials can subscribe to articles in our help center. If your organization uses an email alias to forward emails to a group of internal users, you will need to create a Sourcepoint user account for that email address and follow the steps below using those credentials.
Comments
4 comments