Web Implementation

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 cover how to implement multiple campaigns on your property in order to surface different messaging experiences.

Retrieve Implementation Code Snippet for Property

With a web property created, click Dialogue from the top navigation bar and click <> inline with the property name.

Use the provided dropdown menu to select the messaging campaigns that will be implemented on the property. The implementation code snippet will automatically update as more messaging frameworks are added.

Note: To implement a GDPR non-TCFv2 campaign in addition to other messaging campaigns (i.e. CCPA or Anti-Adblock), select GDPR Compliance from the dropdown menu and select the checkbox for non tcfv2.

Copy the code from the generator and add to your property.

Implementation Code Snippet Overview

In this section, we will cover the various elements that you may find in the implementation code snippet. A complete example can be found below and can be divided into three sections:

//Example of implementation code snippet.
<script>!function(t){var e={};function n(r){if(e[r])return e[r].exports;var o=e[r]={i:r,l:!1,exports:{}};return t[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=t,n.c=e,n.d=function(t,e,r){n.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:r})},n.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},n.t=function(t,e){if(1&e&&(t=n(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var o in t)n.d(r,o,function(e){return t[e]}.bind(null,o));return r},n.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return n.d(e,"a",e),e},n.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},n.p="",n(n.s=3)}([function(t,e,n){var r=n(2);t.exports=!r((function(){return 7!=Object.defineProperty({},"a",{get:function(){return 7}}).a}))},function(t,e){t.exports=function(t){return"object"==typeof t?null!==t:"function"==typeof t}},function(t,e){t.exports=function(t){try{return!!t()}catch(t){return!0}}},function(t,e,n){n(4),function(){if("function"!=typeof window.__tcfapi){var t,e=[],n=window,r=n.document;!n.__tcfapi&&function t(){var e=!!n.frames.__tcfapiLocator;if(!e)if(r.body){var o=r.createElement("iframe");o.style.cssText="display:none",o.name="__tcfapiLocator",r.body.appendChild(o)}else setTimeout(t,5);return!e}()&&(n.__tcfapi=function(){for(var n=arguments.length,r=new Array(n),o=0;o<n;o++)r[o]=arguments[o];if(!r.length)return e;if("setGdprApplies"===r[0])r.length>3&&2===parseInt(r[1],10)&&"boolean"==typeof r[3]&&(t=r[3],"function"==typeof r[2]&&r[2]("set",!0));else if("ping"===r[0]){var i={gdprApplies:t,cmpLoaded:!1,apiVersion:"2.0"};"function"==typeof r[2]&&r[2](i,!0)}else e.push(r)},n.addEventListener("message",(function(t){var e="string"==typeof t.data,r={};try{r=e?JSON.parse(t.data):t.data}catch(t){}var o=r.__tcfapiCall;o&&n.__tcfapi(o.command,o.parameter,o.version,(function(n,r){var i={__tcfapiReturn:{returnValue:n,success:r,callId:o.callId}};e&&(i=JSON.stringify(i)),t.source.postMessage(i,"*")}))}),!1))}}()},function(t,e,n){var r=n(0),o=n(5).f,i=Function.prototype,c=i.toString,u=/^s*function ([^ (]*)/;r&&!("name"in i)&&o(i,"name",{configurable:!0,get:function(){try{return c.call(this).match(u)[1]}catch(t){return""}}})},function(t,e,n){var r=n(0),o=n(6),i=n(10),c=n(11),u=Object.defineProperty;e.f=r?u:function(t,e,n){if(i(t),e=c(e,!0),i(n),o)try{return u(t,e,n)}catch(t){}if("get"in n||"set"in n)throw TypeError("Accessors not supported");return"value"in n&&(t[e]=n.value),t}},function(t,e,n){var r=n(0),o=n(2),i=n(7);t.exports=!r&&!o((function(){return 7!=Object.defineProperty(i("div"),"a",{get:function(){return 7}}).a}))},function(t,e,n){var r=n(8),o=n(1),i=r.document,c=o(i)&&o(i.createElement);t.exports=function(t){return c?i.createElement(t):{}}},function(t,e,n){(function(e){var n=function(t){return t&&t.Math==Math&&t};t.exports=n("object"==typeof globalThis&&globalThis)||n("object"==typeof window&&window)||n("object"==typeof self&&self)||n("object"==typeof e&&e)||Function("return this")()}).call(this,n(9))},function(t,e){var n;n=function(){return this}();try{n=n||new Function("return this")()}catch(t){"object"==typeof window&&(n=window)}t.exports=n},function(t,e,n){var r=n(1);t.exports=function(t){if(!r(t))throw TypeError(String(t)+" is not an object");return t}},function(t,e,n){var r=n(1);t.exports=function(t,e){if(!r(t))return t;var n,o;if(e&&"function"==typeof(n=t.toString)&&!r(o=n.call(t)))return o;if("function"==typeof(n=t.valueOf)&&!r(o=n.call(t)))return o;if(!e&&"function"==typeof(n=t.toString)&&!r(o=n.call(t)))return o;throw TypeError("Can't convert object to primitive value")}}]);
</script>
<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>
<script>
window._sp_queue = [];
window._sp_ = {
config: {
accountId: 22,
baseEndpoint: 'https://cdn.privacy-mgmt.com',
ccpa: { },
gdpr: { }
}
}
</script>
<script src="https://cdn.privacy-mgmt.com/unified/wrapperMessagingWithoutDetection.js" async></script>

Stub File

Your implementation code snippet will include a stub file only if you are implementing either GDPR TCF v2 or CCPA as one of the messaging campaigns used on the property.

The first part of the implementation code snippet contains the IAB Stub functions. The Stub functions set up the IAB privacy string object __uspapi and/or __tcfapi. 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.

//GDPR TCF v2 Stub file
<script>!function(t){var e={};function n(r){if(e[r])return e[r].exports;var o=e[r]={i:r,l:!1,exports:{}};return t[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=t,n.c=e,n.d=function(t,e,r){n.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:r})},n.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},n.t=function(t,e){if(1&e&&(t=n(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var o in t)n.d(r,o,function(e){return t[e]}.bind(null,o));return r},n.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return n.d(e,"a",e),e},n.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},n.p="",n(n.s=3)}([function(t,e,n){var r=n(2);t.exports=!r((function(){return 7!=Object.defineProperty({},"a",{get:function(){return 7}}).a}))},function(t,e){t.exports=function(t){return"object"==typeof t?null!==t:"function"==typeof t}},function(t,e){t.exports=function(t){try{return!!t()}catch(t){return!0}}},function(t,e,n){n(4),function(){if("function"!=typeof window.__tcfapi){var t,e=[],n=window,r=n.document;!n.__tcfapi&&function t(){var e=!!n.frames.__tcfapiLocator;if(!e)if(r.body){var o=r.createElement("iframe");o.style.cssText="display:none",o.name="__tcfapiLocator",r.body.appendChild(o)}else setTimeout(t,5);return!e}()&&(n.__tcfapi=function(){for(var n=arguments.length,r=new Array(n),o=0;o<n;o++)r[o]=arguments[o];if(!r.length)return e;if("setGdprApplies"===r[0])r.length>3&&2===parseInt(r[1],10)&&"boolean"==typeof r[3]&&(t=r[3],"function"==typeof r[2]&&r[2]("set",!0));else if("ping"===r[0]){var i={gdprApplies:t,cmpLoaded:!1,apiVersion:"2.0"};"function"==typeof r[2]&&r[2](i,!0)}else e.push(r)},n.addEventListener("message",(function(t){var e="string"==typeof t.data,r={};try{r=e?JSON.parse(t.data):t.data}catch(t){}var o=r.__tcfapiCall;o&&n.__tcfapi(o.command,o.parameter,o.version,(function(n,r){var i={__tcfapiReturn:{returnValue:n,success:r,callId:o.callId}};e&&(i=JSON.stringify(i)),t.source.postMessage(i,"*")}))}),!1))}}()},function(t,e,n){var r=n(0),o=n(5).f,i=Function.prototype,c=i.toString,u=/^s*function ([^ (]*)/;r&&!("name"in i)&&o(i,"name",{configurable:!0,get:function(){try{return c.call(this).match(u)[1]}catch(t){return""}}})},function(t,e,n){var r=n(0),o=n(6),i=n(10),c=n(11),u=Object.defineProperty;e.f=r?u:function(t,e,n){if(i(t),e=c(e,!0),i(n),o)try{return u(t,e,n)}catch(t){}if("get"in n||"set"in n)throw TypeError("Accessors not supported");return"value"in n&&(t[e]=n.value),t}},function(t,e,n){var r=n(0),o=n(2),i=n(7);t.exports=!r&&!o((function(){return 7!=Object.defineProperty(i("div"),"a",{get:function(){return 7}}).a}))},function(t,e,n){var r=n(8),o=n(1),i=r.document,c=o(i)&&o(i.createElement);t.exports=function(t){return c?i.createElement(t):{}}},function(t,e,n){(function(e){var n=function(t){return t&&t.Math==Math&&t};t.exports=n("object"==typeof globalThis&&globalThis)||n("object"==typeof window&&window)||n("object"==typeof self&&self)||n("object"==typeof e&&e)||Function("return this")()}).call(this,n(9))},function(t,e){var n;n=function(){return this}();try{n=n||new Function("return this")()}catch(t){"object"==typeof window&&(n=window)}t.exports=n},function(t,e,n){var r=n(1);t.exports=function(t){if(!r(t))throw TypeError(String(t)+" is not an object");return t}},function(t,e,n){var r=n(1);t.exports=function(t,e){if(!r(t))return t;var n,o;if(e&&"function"==typeof(n=t.toString)&&!r(o=n.call(t)))return o;if("function"==typeof(n=t.valueOf)&&!r(o=n.call(t)))return o;if(!e&&"function"==typeof(n=t.toString)&&!r(o=n.call(t)))return o;throw TypeError("Can't convert object to primitive value")}}]);
</script>
//CCPA Stub file
<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>

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 two required parameters to successfully deliver an end-user notification:

  • AccountId

  • baseEndpoint

In addition to the required parameters (example above), your organization can implement additional parameters in the code snippet to allow for Javascript callbacks that can be triggered for different customization purposes.

Follow the resources below for additional parameters your organization can utilize to customize your implementation:

Required parameter

Description

accountId

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

A single server endpoint that serves the messaging experience. For GDPR TCF v2, CCPA, and GDPR non-TCF, the baseEndpoint is https://cdn.privacy-mgmt.com. For Anti-Adblock, the baseEndpoint is https://d3fkv551xkjrmm.cloudfront.net.

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.

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

URL to Messaging Library

The final scripts are URL(s) that points to Sourcepoint's messaging libraries. The default URLs are as follows:

Campaign(s)

URL

CCPA, GDPR TCF v2, GDPR non-TCF

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

Note: You only need to include this script once regardless of how many different types of messaging campaigns you run on the property.

Anti-Adblock

https://d3fkv551xkjrmm.cloudfront.net/js/messaging.js

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

CCPA, GDPR TCF v2, GDPR non-TCF v2 https://client.domain.com/unified/wrapperMessagingWithoutDetection.js

//GDPR TCF v2, non-TCF v2, CCPA
<script src='https://cdn.privacy-mgmt.com/unified/wrapperMessagingWithoutDetection.js' async></script>
//Anti-Adblock
<script src='https://d3fkv551xkjrmm.cloudfront.net/js/messaging.js'></script>

De-risk Anti-Adblock Endpoint

If you intend to run an Anti-Adblock campaign, we recommend performing the following configurations to de-risk the Anti-Adblock endpoint from being blocked.

  • Configure a CNAME DNS record so the javascript file appears to come from your domain rather than Sourcepoint's 3rd-party domain.

  • Integrate wrapper javascript into a critical piece of the property's javascript so that if it is blocked than a critical function for the property will also be blocked. This option still allows end-users to block the Anti-Adblock script but will protect the CMP endpoints from being blocked.