GDPR TCF and U.S. Multi-State Privacy (National) implementation guide (web)

Sourcepoint offers messaging capabilities for multiple regulatory and non-regulatory frameworks. These messages are surfaced to your end-users in accordance with the campaigns (and scenarios) that you enable for the property.

In this article, we will walk you through the essential steps necessary to launch your GDPR TCF and U.S. Multi-State Privacy (National) messaging campaigns on a single web property. 


Overview

Screenshot 2023-12-11 at 8.12.15 AM.png


Portal configuration

Use the table below to track the necessary configurations that need to be performed within the Sourcepoint portal before adding the required code onto the property and launching your GDPR TCF and U.S. Multi-State Privacy (National) campaign.

  Note: There are certain optional steps/configurations that are not represented in this tracker such as property groups, dynamic language support, etc...

Step Resource(s)
1 Create new property
2 Create GDPR TCF vendor list
3 Edit GDPR TCF vendor list
4 Create U.S. Multi-State Privacy (National) vendor list
5 Edit U.S. Multi-State (National) Privacy vendor list
6 Create GDPR TCF privacy manager
7 Create GDPR first layer message
8 Create U.S. Multi-State Privacy privacy manager
9 Create U.S. Multi-State Privacy first layer message
10 Create GDPR TCF scenario
11 Create U.S. Privacy (Legacy) scenario
  • See above
12 Create GDPR TCF partition set
13 Create U.S. Multi-State Privacy) partition set
  • See above

Install Sourcepoint implementation code on property

When you have completed the portal configuration for your property, click Properties on the left-hand panel and select Properties from the subsequent menu.

Screen_Shot_2021-10-25_at_9.26.56_AM.png

Click <> inline with the property name.

Screen_Shot_2023-01-23_at_10.17.49_AM.png

Use the Campaign Type dropdown menu to select GDPR Compliance and U.S. Multi-State Privacy. Next, select the GDPR IAB TCF and US IAB GPP radio buttons.  

The implementation code snippet will automatically populate in the provided space.

Click Copy Code and add the implementation code snippet to your property. 

  Note: Click here for best practices on how to implement the Sourcepoint implementation code snippet to optimize message loading time.

Screenshot 2024-11-11 at 9.47.52 AM.png

The Sourcepoint implementation code snippet for GDPR TCF and U.S. Multi-State Privacy (National) campaigns is comprised of four scripts. Review the sections below for additional information and possible configuration options to suit your organization's use cases.

Complete Example
//Example only. Please use stub file generated in Sourcepoint portal as it may have changed.
<script>
function _typeof(t){return(_typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}!function(){for(var t,e,o=[],n=window,r=n;r;){try{if(r.frames.__tcfapiLocator){t=r;break}}catch(t){}if(r===n.top)break;r=n.parent}t||(function t(){var e=n.document,o=!!n.frames.__tcfapiLocator;if(!o)if(e.body){var r=e.createElement("iframe");r.style.cssText="display:none",r.name="__tcfapiLocator",e.body.appendChild(r)}else setTimeout(t,5);return!o}(),n.__tcfapi=function(){for(var t=arguments.length,n=new Array(t),r=0;r<t;r++)n[r]=arguments[r];if(!n.length)return o;"setGdprApplies"===n[0]?n.length>3&&2===parseInt(n[1],10)&&"boolean"==typeof n[3]&&(e=n[3],"function"==typeof n[2]&&n[2]("set",!0)):"ping"===n[0]?"function"==typeof n[2]&&n[2]({gdprApplies:e,cmpLoaded:!1,cmpStatus:"stub"}):o.push(n)},n.addEventListener("message",(function(t){var e="string"==typeof t.data,o={};if(e)try{o=JSON.parse(t.data)}catch(t){}else o=t.data;var n="object"===_typeof(o)?o.__tcfapiCall:null;n&&window.__tcfapi(n.command,n.version,(function(o,r){var a={__tcfapiReturn:{returnValue:o,success:r,callId:n.callId}};t&&t.source&&t.source.postMessage&&t.source.postMessage(e?JSON.stringify(a):a,"*")}),n.parameter)}),!1))}();
</script>
//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>
<script> window._sp_queue = []; window._sp_ = { config: { accountId: 22, baseEndpoint: 'https://cdn.privacy-mgmt.com', gdpr: { }, usnat: { }, events: { onMessageChoiceSelect: function() { console.log('[event] onMessageChoiceSelect', arguments); }, onMessageReady: function() { console.log('[event] onMessageReady', arguments); }, onMessageChoiceError: function() { console.log('[event] onMessageChoiceError', arguments); }, onPrivacyManagerAction: function() { console.log('[event] onPrivacyManagerAction', arguments); }, onPMCancel: function() { console.log('[event] onPMCancel', arguments); }, onMessageReceiveData: function() { console.log('[event] onMessageReceiveData', arguments); }, onSPPMObjectReady: function() { console.log('[event] onSPPMObjectReady', arguments); }, onConsentReady: function (consentUUID, euconsent) { console.log('[event] onConsentReady', arguments); }, onError: function() { console.log('[event] onError', arguments); }, } } } </script>
<script src="https://cdn.privacy-mgmt.com/unified/wrapperMessagingWithoutDetection.js" async></script>

The first part of the implementation code snippet is comprised of two scripts and contains IAB stub functions. The stub functions set up the IAB privacy string object __tcfapi and __gpp, respectively. This makes it available on queue to be called and released when needed. It is important to have these script tags in the first position to avoid errors and failure of service.

//Example only. Please use stub file generated in Sourcepoint portal as it may have changed.
<script>
function _typeof(t){return(_typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}!function(){for(var t,e,o=[],n=window,r=n;r;){try{if(r.frames.__tcfapiLocator){t=r;break}}catch(t){}if(r===n.top)break;r=n.parent}t||(function t(){var e=n.document,o=!!n.frames.__tcfapiLocator;if(!o)if(e.body){var r=e.createElement("iframe");r.style.cssText="display:none",r.name="__tcfapiLocator",e.body.appendChild(r)}else setTimeout(t,5);return!o}(),n.__tcfapi=function(){for(var t=arguments.length,n=new Array(t),r=0;r<t;r++)n[r]=arguments[r];if(!n.length)return o;"setGdprApplies"===n[0]?n.length>3&&2===parseInt(n[1],10)&&"boolean"==typeof n[3]&&(e=n[3],"function"==typeof n[2]&&n[2]("set",!0)):"ping"===n[0]?"function"==typeof n[2]&&n[2]({gdprApplies:e,cmpLoaded:!1,cmpStatus:"stub"}):o.push(n)},n.addEventListener("message",(function(t){var e="string"==typeof t.data,o={};if(e)try{o=JSON.parse(t.data)}catch(t){}else o=t.data;var n="object"===_typeof(o)?o.__tcfapiCall:null;n&&window.__tcfapi(n.command,n.version,(function(o,r){var a={__tcfapiReturn:{returnValue:o,success:r,callId:n.callId}};t&&t.source&&t.source.postMessage&&t.source.postMessage(e?JSON.stringify(a):a,"*")}),n.parameter)}),!1))}();
</script>
//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>

Client configuration script

The client configuration script contains your organization's specific account configuration parameters. This configuration includes the necessary and optional parameters for your property to communicate with the Sourcepoint messaging platform and consent service libraries.

Currently, there are 5 required properties for this implementation:

  Note: Use either propertyHref or propertyId in your client configuration script. 

Required Property Date Type Description
accountId Number The accountId value associates the property with your organization's Sourcepoint account. Your organization's accountId can be retrieved by contacting your Sourcepoint Account Manager or via the My Account page in your Sourcepoint account.
baseEndpoint String

A single server endpoint that serves the messaging experience.

  • For GDPR TCF, U.S. Multi-State Privacy, U.S. Privacy (Legacy), GDPR Standard, and Custom Messaging, the baseEndpoint is https://cdn.privacy-mgmt.com.

  Note: The baseEndpoint can also be changed to a CNAME first-party subdomain in order to persist first-party cookies on Safari web browser (due to Safari’s ITP) by setting cookies through the server with set-cookie rather than using document.cookie on the page.

propertyHref String

Maps the implementation to a specific URL as set up in the Sourcepoint account dashboard. Use propertyHref to spoof messaging campaigns onto a local environment for testing or debugging.

  Note: When a campaign is ready to launch publicly to your end-users, we recommend that you replace propertyHref with the more efficient propertyId parameter. Click here for more information on working with propertyHref.

propertyId Number

Maps the message to a specific property set up in the Sourcepoint portal. Use propertyId instead of propertyHref when launching your campaign to end-users publicly.

gdpr Object

Campaigns are surfaced on your property by adding campaign objects to your configuration. 

usnat Object

Campaigns are surfaced on your property by adding campaign objects to your configuration. 

In addition to the required parameters (above), your organization can further implement additional parameters and customizations in the code snippet for different use cases. Follow the resources below for additional information

<script>
window._sp_queue = [];
window._sp_ = {
    config: {
        accountId: 12123,
        baseEndpoint: 'https://cdn.privacy-mgmt.com',
        propertyHref: 'https://testdemo.com',
        gdpr: {},
        usnat: {}
    }
}
</script>

URL to messaging library

The final script is a URL that points to Sourcepoint's messaging libraries. The default URL is as follows:

Campaign(s) Description
  • GDPR TCF
  • U.S. Multi-State Privacy

https://cdn.privacy-mgmt.com/unified/wrapperMessagingWithoutDetection.js'

This script only needs to be included once regardless of how many different types of messaging campaigns you run on the property.

  Note: If your organization has edited the baseEndpoint with a CNAME DNS record you will also need to edit the URL. Please follow the following format if necessary:

https://cname.subdomain/unified/wrapperMessagingWithoutDetection.js

In the developer console, the URL to the messaging library can return the following regardless of whether a message was shown to the user:

Console Description
Messaging without detection successfully executed The script, messaging without detection, has successfully fired. It does not indicate that a message was shown to the end-user.
interaction complete The interaction with our, messaging without detection script, has concluded. It does not indicate that an end-user interacted with a message.  

Screen_Shot_2022-02-03_at_9_09_55_AM.jpg


Install resurface privacy manager codes on property

Many organizations will want to add a button/link onto their web property that allows an end-user to resurface the privacy manager so they can manager their privacy choice preferences on an ongoing basis.

Typically, the JavaScript code on their page will attach the function to the onclick event of a page element. Click here for more information on how to retrieve the privacy manager ID and implement the JavaScript code.

  Note: Organizations who have implemented both GDPR TCF and U.S. Multi-State Privacy (National) campaigns on their property will only want end-users to interact with the correct privacy manager based upon the region to which the end-user belongs (e.g. an end-user who is currently in the U.S. and opted into privacy choices for U.S. Multi-State Privacy should only be able to manage their opt in status for U.S. Multi-State Privacy on an ongoing basis while in the U.S.). Click here for more information. 


APIs

In addition to the implementation code that is added to your property, your organization can leverage IAB and Sourcepoint designed APIs to further customize and test your implementation. Information on the commands available with the __tcfapi and __gpp call can be found in our developer hub:

GDPR TCF API

U.S. Multi-State Privacy API


Launch campaigns

With the property configured in the portal and Sourcepoint's implementation code snippet added to the web property, your organization can now launch a GDPR TCF and U.S. Multi-State Privacy campaign on the property and test the end-user flow.

Step Resources
Launch GDPR TCF campaign
Launch U.S. Multi-State Privacy campaign
  • See above
Test end-user consent flow for GDPR TCF 
Test end-user consent flow for U.S. Multi-State Privacy
Was this article helpful?
0 out of 0 found this helpful

Comments

0 comments

Article is closed for comments.