diff --git a/burda_cmp.libraries.yml b/burda_cmp.libraries.yml index 85d51e1c..62dc4e05 100644 --- a/burda_cmp.libraries.yml +++ b/burda_cmp.libraries.yml @@ -1,25 +1,28 @@ -liveramp.conditional-content: +sourcepoint.conditional-content: version: VERSION js: - js/liveramp/burda-cmp.liveramp.conditional-content.js: {} + js/sourcepoint/burda-cmp.sourcepoint.conditional-content.js: { } dependencies: - core/drupal - core/drupalSettings - core/jquery + - core/once -liveramp.conditional-scripts: +sourcepoint.conditional-scripts: version: VERSION js: - js/liveramp/burda-cmp.liveramp.conditional-scripts.js: {} + js/sourcepoint/burda-cmp.sourcepoint.conditional-scripts.js: { } dependencies: - core/drupal - core/drupalSettings - core/jquery + - core/once -liveramp.open-privacy-manager: - version: VERSION +sourcepoint.open-privacy-manager: js: - js/liveramp/burda-cmp.liveramp.open-privacy-manager.js: {} + js/sourcepoint/burda-cmp.sourcepoint.open-privacy-manager.js: { } dependencies: - core/drupal + - core/drupalSettings - core/jquery + - core/once diff --git a/burda_cmp.module b/burda_cmp.module index 320cc05d..ae3a7453 100644 --- a/burda_cmp.module +++ b/burda_cmp.module @@ -6,6 +6,7 @@ */ use Drupal\Core\Cache\CacheableMetadata; +use Drupal\Core\Render\Markup; /** * Implements hook_module_implements_alter(). @@ -38,27 +39,30 @@ function burda_cmp_library_info_alter(&$libraries, $extension) { if (!empty($library['js'])) { foreach ($library['js'] as $js => &$definition) { if (isset($definition['burda_cmp'])) { - $parsed = _burda_cmp_parse_js_definition($js, $extension, $definition); - // Ensure numeric vendor ID. if (!empty($definition['burda_cmp']['vendor'])) { - if (!is_numeric($definition['burda_cmp']['vendor'])) { - $definition['burda_cmp']['vendor'] = $static_consent_data->getVendorId($definition['burda_cmp']['vendor']); - } + $definition['burda_cmp']['vendorId'] = $static_consent_data->getVendorId($definition['burda_cmp']['vendor']); } // Determine purposes by vendor (if empty). if (!empty($definition['burda_cmp']['vendor'])) { if (empty($definition['burda_cmp']['purposes'])) { - $definition['burda_cmp']['purposes'] = $static_consent_data->getPurposeIds($definition['burda_cmp']['vendor']); + $definition['burda_cmp']['purposeIds'] = $static_consent_data->getPurposeIds($definition['burda_cmp']['vendor']); } } - $script = \Drupal::service('file_url_generator')->generateString($parsed['data']); - $library['drupalSettings']['burdaCmp'][$extension][$script] = $definition['burda_cmp']; - - // Remove definition as it is loaded on demand now. - unset($library['js'][$js]); + if (!empty($definition['burda_cmp']['vendor'])) { + // Overwrite attribute text/javascript to text/plain + if (!isset($definition['attributes'])) { + $definition['attributes'] = []; + } + $definition['attributes']['type'] = 'text/plain'; + $definition['attributes']['data-burda-cmp-conditional-scripts'] = ''; + $definition['attributes']['data-burda-cmp-vendor'] = $definition['burda_cmp']['vendor']; + $definition['attributes']['data-burda-cmp-vendorId'] = $static_consent_data->getVendorId($definition['burda_cmp']['vendor']); + $definition['attributes']['data-burda-cmp-purposeIds'] = implode(',', + $static_consent_data->getPurposeIds($definition['burda_cmp']['vendor'])); + } } } } @@ -71,24 +75,57 @@ function burda_cmp_library_info_alter(&$libraries, $extension) { function burda_cmp_page_attachments(array &$page) { /** @var \Drupal\Core\Config\ImmutableConfig $config */ $config = \Drupal::config('burda_cmp.settings'); - $liveramp_script_url = $config->get('liveramp_script_url'); + $sourcepoint_script_url = $config->get('sourcepoint_script_url'); + $sourcepoint_shim_script = $config->get('sourcepoint_shim_script'); + $sourcepoint_config_code = $config->get('sourcepoint_config_code'); CacheableMetadata::createFromRenderArray($page) ->addCacheableDependency($config) ->applyTo($page); - // LiveRamp init script. - if ($liveramp_script_url) { + if ($sourcepoint_shim_script) { + $page['#attached']['html_head'][] = [ + [ + '#tag' => 'script', + '#attributes' => [ + 'type' => 'text/javascript', + 'data-sourcepoint' => 'shim-script', + ], + '#weight' => -102, + '#value' => Markup::create($sourcepoint_shim_script), + ], + 'burda_cmp_init_shim', + ]; + } + + if ($sourcepoint_config_code) { + $page['#attached']['html_head'][] = [ + [ + '#type' => 'html_tag', + '#tag' => 'script', + '#attributes' => [ + 'type' => 'text/javascript', + 'data-sourcepoint' => 'config-code', + ], + '#weight' => -101, + '#value' => Markup::create($sourcepoint_config_code), + ], + 'burda_cmp_init_config', + ]; + } + + if ($sourcepoint_script_url) { $page['#attached']['html_head'][] = [ [ '#tag' => 'script', '#attributes' => [ 'type' => 'text/javascript', - 'src' => $liveramp_script_url, + 'src' => $sourcepoint_script_url, + 'data-sourcepoint' => 'script-url', ], '#weight' => -100, ], - 'burda_cmp_init', + 'burda_cmp_init_script', ]; } } @@ -116,76 +153,3 @@ function burda_cmp_theme($existing, $type, $theme, $path) { return $items; } - -/** - * Parse a library's JavaScript definition. - * - * This is a verbatim copy of LibraryDiscoveryParser::buildByExtension() to have - * the same logic for when the $options['data'] array item is set. - * - * @param string $source - * The script file path/URI. - * @param string $extension - * The name of the extension that registered a library. - * @param array $options - * The definition options for the JavaScript file. - * - * @see \Drupal\Core\Asset\LibraryDiscoveryParser::buildByExtension() - */ -function _burda_cmp_parse_js_definition($source, $extension, array $options) { - if ($extension === 'core') { - $path = 'core'; - } - else { - if (\Drupal::moduleHandler()->moduleExists($extension)) { - $extension_type = 'module'; - } - else { - $extension_type = 'theme'; - } - $path = \Drupal::service('extension.path.resolver')->getPath($extension_type, $extension); - } - - if (!empty($options['type']) && $options['type'] === 'external') { - $options['data'] = $source; - } - - // Determine the file asset URI. - else { - /** @var \Drupal\Core\StreamWrapper\StreamWrapperManagerInterface $stream_wrapper_manager */ - $stream_wrapper_manager = \Drupal::service('stream_wrapper_manager'); - - if ($source[0] === '/') { - // An absolute path maps to DRUPAL_ROOT / base_path(). - if ($source[1] !== '/') { - $options['data'] = substr($source, 1); - } - - // A protocol-free URI (e.g., //cdn.com/example.js) is external. - else { - $options['type'] = 'external'; - $options['data'] = $source; - } - } - - // A stream wrapper URI (e.g., public://generated_js/example.js). - elseif ($stream_wrapper_manager->isValidUri($source)) { - $options['data'] = $source; - } - - // A regular URI (e.g., http://example.com/example.js) without - // 'external' explicitly specified, which may happen if, e.g. - // libraries-override is used. - elseif (count(explode('://', $source)) === 2) { - $options['type'] = 'external'; - $options['data'] = $source; - } - - // By default, file paths are relative to the registering extension. - else { - $options['data'] = $path . '/' . $source; - } - } - - return $options; -} diff --git a/burda_cmp.theme.inc b/burda_cmp.theme.inc index b1930c2a..20e0225b 100644 --- a/burda_cmp.theme.inc +++ b/burda_cmp.theme.inc @@ -54,6 +54,4 @@ function template_preprocess_burda_cmp_conditional_content(&$variables) { return trim($item); }, $variables['purposes']); - // Sort purpose IDs. - sort($variables['purposes']); } diff --git a/config/schema/burda_cmp.schema.yml b/config/schema/burda_cmp.schema.yml index 26e52006..ad392837 100644 --- a/config/schema/burda_cmp.schema.yml +++ b/config/schema/burda_cmp.schema.yml @@ -1,6 +1,6 @@ -block.settings.burda_cmp_liveramp_open_privacy_manager:*: +block.settings.burda_cmp_sourcepoint_open_privacy_manager:*: type: block_settings - label: 'Open privacy manager block (LiveRamp)' + label: 'Open privacy manager block (Sourcepoint)' mapping: link_text: type: label @@ -10,6 +10,6 @@ burda_cmp.settings: type: config_object label: 'Consent management platform settings' mapping: - liveramp_script_url: + sourcepoint_script_url: type: string - label: 'LiveRamp script URL' + label: 'Sourcepoint script URL' diff --git a/js/liveramp/burda-cmp.liveramp.conditional-scripts.js b/js/liveramp/burda-cmp.liveramp.conditional-scripts.js deleted file mode 100644 index 4c6610a4..00000000 --- a/js/liveramp/burda-cmp.liveramp.conditional-scripts.js +++ /dev/null @@ -1,111 +0,0 @@ -/** - * Conditional behavior for scripts that are only loaded when consent is given. - */ - -(function ($, Drupal, drupalSettings) { - - 'use strict'; - - /** - * Array bag for all loaded scripts. - * - * @type {Array} - */ - var alreadyLoaded = []; - - /** - * Enables the 'Conditional scripts' functionality. - * - * @type {Drupal~behavior} - * - * @prop {Drupal~behaviorAttach} attach - * Attaches the 'Conditional scripts' behavior. - */ - Drupal.behaviors.burdaCmpLiveRampConditionalScripts = { - attach: function attach(context) { - var self = this; - - // Initialize when CMP library is ready. - __tcfapi('addEventListener', null, function () { - $('body', context).once('burdaCmpLiveRampConditionalScripts').each(function () { - if (typeof drupalSettings.burdaCmp !== 'undefined') { - for (var extension in drupalSettings.burdaCmp) { - if (drupalSettings.burdaCmp.hasOwnProperty(extension)) { - var files = drupalSettings.burdaCmp[extension]; - - for (var url in files) { - if (files.hasOwnProperty(url)) { - self.checkConsent(url, files[url]); - } - } - } - } - } - }); - }, 'cmpReady'); - }, - - /** - * Checks if a consent is given for the conditional script. - * - * @param {String} url - * The url of the JavaScript to load. - * @param {Object} options - * The options for the JavaScript to load (should have a 'vendor' property - * at least). - */ - checkConsent: function(url, options) { - var self = this; - - // Prepare consent check data. - var consentData = self.getData(options); - - if (consentData.vendorId) { - // Check consent based on vendor/purpose(s). - __tcfapi('checkConsent', null, function (data, success) { - // Load script? - if (data) { - if (alreadyLoaded.indexOf(url) === -1) { - $.getScript(url, function () { - alreadyLoaded.push(url); - }); - } - } - }, { - data: [consentData], - recheckConsentOnChange: true - }); - } - }, - - /** - * Returns the consent data associated with the conditional script. - * - * @param {Object} options - * A definition object containing information about associated vendor and - * purpose(s). - * - * @return {Object} - * An object containing all related consent data: - * - vendorId: Associated vendor ID. - * - purposeIds: Array of associated purpose ID(s). - */ - getData: function getData(options) { - // Determine required vendor/purpose(s). - var vendorId = typeof options.vendor !== 'undefined' ? options.vendor : null; - var purposeIds = typeof options.purposes !== 'undefined' ? options.purposes : null; - - // Prepare consent check data. - var data = { - vendorId: vendorId - }; - - if (purposeIds) { - data.purposeIds = purposeIds; - } - - return data; - } - }; - -})(jQuery, Drupal, drupalSettings); diff --git a/js/liveramp/burda-cmp.liveramp.open-privacy-manager.js b/js/liveramp/burda-cmp.liveramp.open-privacy-manager.js deleted file mode 100644 index 8996ff6d..00000000 --- a/js/liveramp/burda-cmp.liveramp.open-privacy-manager.js +++ /dev/null @@ -1,35 +0,0 @@ -/** - * Behavior for 'Open privacy manager (LiveRamp)' links. - */ - -(function ($, Drupal) { - - 'use strict'; - - /** - * Enables the 'Open privacy manager (LiveRamp)' link functionality. - * - * @type {Drupal~behavior} - * - * @prop {Drupal~behaviorAttach} attach - * Attaches the 'Open privacy manager (LiveRamp)' behavior. - */ - Drupal.behaviors.burdaCmpLiveRampOpenPrivacyManager = { - attach: function attach(context) { - // Initialize 'Open privacy manager' link when CMP library is ready. - __tcfapi('addEventListener', null, function () { - $('[data-burda-cmp-open-privacy-manager]', context).once('burdaCmpLiveRampOpenPrivacyManager').each(function () { - $(this).on('click.burdaCmpLiveRampOpenPrivacyManager', function (e) { - e.preventDefault(); - e.stopPropagation(); - - // Open privacy manager. - __tcfapi('showConsentManager', null, function () { - }); - }) - }); - }, 'cmpReady'); - } - }; - -})(jQuery, Drupal); diff --git a/js/liveramp/burda-cmp.liveramp.conditional-content.js b/js/sourcepoint/burda-cmp.sourcepoint.conditional-content.js similarity index 61% rename from js/liveramp/burda-cmp.liveramp.conditional-content.js rename to js/sourcepoint/burda-cmp.sourcepoint.conditional-content.js index 39963fe8..0de9b22d 100644 --- a/js/liveramp/burda-cmp.liveramp.conditional-content.js +++ b/js/sourcepoint/burda-cmp.sourcepoint.conditional-content.js @@ -2,7 +2,7 @@ * Conditional behavior for content that is only loaded when consent is given. */ -(function ($, Drupal, drupalSettings) { +(function (Drupal, $, once, drupalSettings) { 'use strict'; @@ -14,34 +14,39 @@ * @prop {Drupal~behaviorAttach} attach * Attaches the 'Conditional content' behavior. */ - Drupal.behaviors.burdaCmpLiveRampConditionalContent = { + Drupal.behaviors.burdaCmpSourcepointConditionalContent = { attach: function attach(context) { var self = this; // Initialize when CMP library is ready. - __tcfapi('addEventListener', null, function () { - $('[data-burda-cmp-conditional-content]', context).once('burdaCmpLiveRampConditionalContent').each(function () { + __tcfapi('addEventListener', 2, function (tcData, success) { + $('[data-burda-cmp-conditional-content]', context).once('burdaCmpSourcepointConditionalContent').each(function () { var $self = $(this); - self.checkConsent($self); // Initialize toggle (if any). - $self.find('[data-burda-cmp-toggle]').on('click.burdaCmpLiveRampConditionalContent', function (e) { + $self.find('[data-burda-cmp-toggle]').on('click.burdaCmpSourcepointConditionalContent', function (e) { e.preventDefault(); e.stopPropagation(); - self.toggleConsent($self); }); // Initialize settings button (if any). - $self.find('[data-burda-cmp-show-consent-manager]').on('click.burdaCmpLiveRampConditionalContent', function (e) { + $self.find('[data-burda-cmp-show-consent-manager]').on('click.burdaCmpSourcepointConditionalContent', function (e) { e.preventDefault(); e.stopPropagation(); self.showConsentManager($self); }); }); - }, 'cmpReady'); + // In case user initially confirms CMP on this page. + if (success && tcData.eventStatus === 'useractioncomplete') { + $('[data-burda-cmp-conditional-content]').each(function () { + var $self = $(this); + self.checkConsent($self); + }); + } + }); }, /** @@ -50,34 +55,46 @@ * @param {jQuery} $element * A jQuery DOM fragment that represents the conditional content element. */ - checkConsent: function($element) { + checkConsent: function ($element) { var self = this; var $placeholder = self.getWrapperPlaceholder($element); var $injectedContent = self.getWrapperInjectedContent($element); // Prepare consent check data. var consentData = self.getData($element); - - if (consentData.vendorId) { + if (consentData.vendorId || consentData.purposeIds) { // Check consent based on vendor/purpose(s). - __tcfapi('checkConsent', null, function (data, success) { - if (data) { - if (!self.isContentInjected($element)) { - $injectedContent.append(self.getContent($element)); - $placeholder.hide(); - Drupal.attachBehaviors($injectedContent.get(0), drupalSettings); - $element.attr('aria-expanded', 'true'); + __tcfapi('getCustomVendorConsents', 2, function (data, success) { + if (success) { + let consentForVendorWasGiven = false; + let consentForPurposeWasGiven = false; + // Check for Vendor Consent. + if (Array.isArray(data.consentedVendors)) { + data.consentedVendors.forEach((vendor) => { + if (vendor._id === consentData.vendorId) { + consentForVendorWasGiven = true; + } + }); } - } - else { + // Check for Purpose Consent. + if (Array.isArray(data.consentedPurposes)) { + consentForPurposeWasGiven = data.consentedPurposes.some(item => consentData.purposeIds.includes(item._id)); + } + // If at least one of them was given, render injected content. + if (consentForVendorWasGiven || consentForPurposeWasGiven) { + if (!self.isContentInjected($element)) { + self.activateContent($element); + } + } else { + self.disableContent($element); + } + } else { + // Show placeholder in case there is no success in getCustomVendorConsents call. Drupal.detachBehaviors($injectedContent.get(0), drupalSettings); $injectedContent.html(''); $placeholder.show(); $element.attr('aria-expanded', 'false'); } - }, { - data: [consentData], - recheckConsentOnChange: true }); } }, @@ -114,7 +131,7 @@ // Prepare consent check data. var data = { - vendorId: vendorId + vendorId: vendorId, }; if (purposeIds) { @@ -130,11 +147,11 @@ * @param {jQuery} $element * A jQuery DOM fragment that represents the conditional content element. * - * @return {Number} + * @return {String} * The related vendor ID. */ getVendorId: function getVendorId($element) { - return Number($element.attr('data-burda-cmp-vendor')); + return $element.attr('data-burda-cmp-vendor'); }, /** @@ -148,11 +165,9 @@ */ getPurposeIds: function getPurposeIds($element) { var purposeIds = $element.attr('data-burda-cmp-purposes'); - purposeIds = !purposeIds ? null : purposeIds.split(',').map(function (item) { - return Number($.trim(item)); + return $.trim(item); }); - return purposeIds; }, @@ -205,7 +220,7 @@ * A jQuery DOM fragment that represents the conditional content element. */ showConsentManager: function showConsentManager($element) { - __tcfapi('showConsentManager', null, function () {}); + window._sp_.gdpr.loadPrivacyManagerModal(drupalSettings.burdaCmp.privacyManagerId); }, /** @@ -215,9 +230,9 @@ * A jQuery DOM fragment that represents the conditional content element. */ toggleConsent: function toggleConsent($element) { + var self = this; // Prepare consent check data. var consentData = this.getData($element); - if (consentData.vendorId) { // Rewrite consent data to have vendor ID as array. consentData.vendorIds = [consentData.vendorId]; @@ -227,15 +242,41 @@ // Remove purpose IDs to only reject specific vendor but not all of // its purposes. delete consentData.purposeIds; + // @TODO Remove given consent to sourcepoint. At which point can this + // be the case? Because when consent is given, the button will not + // be rendered. + // __tcfapi('reject', null, function () {}, consentData); + } else { + // Send given consent to sourcepoint. Only the vendor. + // See https://sourcepoint-public-api.readme.io/reference/postcustomconsent#command + // __tcfapi('postCustomConsent', 2, callback_fn, [vendorIds], [purposeIds], [legitimateInterestPurposeIds] ) + __tcfapi('postCustomConsent', 2, (data, success) => { + if (success) { + self.activateContent($element); + } + }, consentData.vendorIds, consentData.purposeIds, []); - __tcfapi('reject', null, function () {}, consentData); - } - - else { - __tcfapi('accept', null, function () {}, consentData); } } - } + }, + activateContent: function activateContent($element) { + var self = this; + var $placeholder = self.getWrapperPlaceholder($element); + var $injectedContent = self.getWrapperInjectedContent($element); + $injectedContent.append(self.getContent($element)); + $placeholder.hide(); + Drupal.attachBehaviors($injectedContent.get(0), drupalSettings); + $element.attr('aria-expanded', 'true'); + }, + disableContent: function disableContent($element) { + var self = this; + var $placeholder = self.getWrapperPlaceholder($element); + var $injectedContent = self.getWrapperInjectedContent($element); + Drupal.detachBehaviors($injectedContent.get(0), drupalSettings); + $injectedContent.html(''); + $placeholder.show(); + $element.attr('aria-expanded', 'false'); + }, }; -})(jQuery, Drupal, drupalSettings); +})(Drupal, jQuery, once, drupalSettings); diff --git a/js/sourcepoint/burda-cmp.sourcepoint.conditional-scripts.js b/js/sourcepoint/burda-cmp.sourcepoint.conditional-scripts.js new file mode 100644 index 00000000..c5da9690 --- /dev/null +++ b/js/sourcepoint/burda-cmp.sourcepoint.conditional-scripts.js @@ -0,0 +1,124 @@ +/** + * Conditional behavior for scripts that are only loaded when consent is given. + */ + +(function (Drupal, $, once, drupalSettings) { + + 'use strict'; + + /** + * Enables the 'Conditional scripts' functionality. + * + * @type {Drupal~behavior} + * + * @prop {Drupal~behaviorAttach} attach + * Attaches the 'Conditional scripts' behavior. + */ + Drupal.behaviors.burdaCmpSourcepointConditionalScripts = { + attach: function attach(context) { + var self = this; + // Initialize when CMP library is ready. + __tcfapi('addEventListener', 2, function (tcData, success) { + if (success) { + // Handles scripts which are attached as elements, e.g. + // inline scripts at page header and scripts attached as libraries. + $('[data-burda-cmp-conditional-scripts]', context).once('burdaCmpSourcepointConditionalScripts').each(function () { + var $self = $(this); + self.checkConsent({ vendorId: $self.data('burda-cmp-vendorid'), purposeIds: $self.data('burda-cmp-purposeids') }); + }); + // In case user initially confirms CMP on this page. + if (tcData.eventStatus === 'useractioncomplete') { + $('[data-burda-cmp-conditional-scripts]', context).each(function () { + var $self = $(this); + self.checkConsent({ vendorId: $self.data('burda-cmp-vendorid'), purposeIds: $self.data('burda-cmp-purposeids') }); + }); + } + } + }); + }, + + /** + * Checks if a consent is given for the conditional script. + * + * @param {Object} options + * The options for the JavaScript to load (should have a 'vendorId' property + * at least). + */ + checkConsent: function (options) { + var self = this; + + // Prepare consent check data. + var consentData = self.getData(options); + + if (consentData.vendorId) { + // Check consent based on vendor/purpose(s). + __tcfapi('getCustomVendorConsents', 2, function (data, success) { + if (success) { + let consentForVendorWasGiven = false; + let consentForPurposeWasGiven = false; + // Check for Vendor Consent. + if (Array.isArray(data.consentedVendors)) { + data.consentedVendors.forEach((vendor) => { + if (vendor._id === consentData.vendorId) { + consentForVendorWasGiven = true; + } + }); + } + // Check for Purpose Consent. + if (Array.isArray(data.consentedPurposes)) { + consentForPurposeWasGiven = data.consentedPurposes.some(item => consentData.purposeIds.includes(item._id)); + } + // If at least one of them was given, load script. + if (consentForVendorWasGiven || consentForPurposeWasGiven) { + self.loadVendorScript(consentData.vendorId); + } + } + }); + } + }, + + /** + * Returns the consent data associated with the conditional script. + * + * @param {Object} options + * A definition object containing information about associated vendorId and + * purposeId(s). + * + * @return {Object} + * An object containing all related consent data: + * - vendorId: Associated vendor ID. + * - purposeIds: Array of associated purpose ID(s). + */ + getData: function getData(options) { + // Determine required vendor/purpose(s). + var vendorId = typeof options.vendorId !== 'undefined' ? options.vendorId : null; + var purposeIds = typeof options.purposeIds !== 'undefined' ? options.purposeIds : null; + + // Prepare consent check data. + var data = { + vendorId: vendorId, + }; + + if (purposeIds) { + data.purposeIds = purposeIds; + } + + return data; + }, + + loadVendorScript: function loadVendorScript(vendorId) { + $('script[data-burda-cmp-vendorid="' + vendorId + '"]').each(function () { + const clone = this.cloneNode(true); + $(this).remove(); + const $el = $(clone); + const dataSrc = $el.data('src'); + if (dataSrc) { + $el.attr('src', dataSrc); + } + $el.attr('type', 'application/javascript'); + $el.appendTo($('body')); + }); + }, + }; + +})(Drupal, jQuery, once, drupalSettings); diff --git a/js/sourcepoint/burda-cmp.sourcepoint.open-privacy-manager.js b/js/sourcepoint/burda-cmp.sourcepoint.open-privacy-manager.js new file mode 100644 index 00000000..0ffcc24e --- /dev/null +++ b/js/sourcepoint/burda-cmp.sourcepoint.open-privacy-manager.js @@ -0,0 +1,23 @@ +/** + * @file + * Consent management platform behaviors. + */ + +(function (Drupal, $, once, drupalSettings) { + + 'use strict'; + + Drupal.behaviors.burdaCmpSourcepointOpenPrivacyManager = { + attach: function (context, settings) { + $('[data-burda-cmp-open-privacy-manager]', context).once('burdaCmpSourcepointOpenPrivacyManager').each(function () { + $(this).on('click.burdaCmpSourcepointOpenPrivacyManager', function (e) { + e.preventDefault(); + e.stopPropagation(); + // Open privacy manager. + window._sp_.gdpr.loadPrivacyManagerModal(drupalSettings.burdaCmp.privacyManagerId); + }); + }); + }, + }; + +})(Drupal, jQuery, once, drupalSettings); diff --git a/modules/burda_cmp_contribs/burda_cmp_contribs.info.yml b/modules/burda_cmp_contribs/burda_cmp_contribs.info.yml index 376d0a49..9a388262 100644 --- a/modules/burda_cmp_contribs/burda_cmp_contribs.info.yml +++ b/modules/burda_cmp_contribs/burda_cmp_contribs.info.yml @@ -4,4 +4,4 @@ description: Contains adjustments for CMP compliant usage of selected contrib ex core_version_requirement: ^9 || ^10 package: Burda dependencies: - burda_cmp:burda_cmp + - burda_cmp:burda_cmp diff --git a/modules/burda_cmp_contribs/burda_cmp_contribs.module b/modules/burda_cmp_contribs/burda_cmp_contribs.module index e8891166..da4e18d1 100644 --- a/modules/burda_cmp_contribs/burda_cmp_contribs.module +++ b/modules/burda_cmp_contribs/burda_cmp_contribs.module @@ -28,13 +28,44 @@ function burda_cmp_contribs_library_info_alter(&$libraries, $extension) { } foreach ($library_definition['js'] as &$js_definition) { - $js_definition['burda_cmp'] = $adjustment; + if ($adjustment) { + $js_definition['burda_cmp'] = $adjustment; + } } } } } } +/** + * Implements hook_page_attachments_alter(). + */ +function burda_cmp_contribs_page_attachments_alter(array &$attachments) { + // Set Google Analytics and Tag Manager. + $vendorAdjust = _contribs_attachments_adjust(); + foreach ($attachments['#attached']['html_head'] as &$lib) { + if (isset($lib[1])) { + $vendor = $lib[1]; + $script = &$lib[0]; + if (array_key_exists($vendor, $vendorAdjust)) { + if (!in_array('burda_cmp/sourcepoint.conditional-scripts', + $attachments['#attached']['library'])) { + $attachments['#attached']['library'][] = 'burda_cmp/sourcepoint.conditional-scripts'; + } + if (!isset($script['#attributes'])) { + $script['#attributes'] = []; + } + $script['#attributes']['type'] = 'text/plain'; + $script['#attributes']['data-burda-cmp-conditional-scripts'] = ''; + $script['#attributes']['data-burda-cmp-vendor'] = $vendorAdjust[$vendor]['vendorName']; + $script['#attributes']['data-burda-cmp-vendorId'] = $vendorAdjust[$vendor]['vendorId']; + $script['#attributes']['data-burda-cmp-purposeIds'] = implode(',', + $vendorAdjust[$vendor]['purposeIds']); + } + } + } +} + /** * Returns data about contribs needing adjustments for CMP compliant usage. * @@ -48,11 +79,6 @@ function burda_cmp_contribs_library_info_alter(&$libraries, $extension) { */ function _bnp_cmp_contribs_adjust() { $adjust = [ - 'riddle_marketplace' => [ - '*' => [ - 'vendor' => StaticConsentDataInterface::VENDOR_RIDDLE, - ], - ], 'media_entity_pinterest' => [ 'pinterest.widgets' => [ 'vendor' => StaticConsentDataInterface::VENDOR_PINTEREST, @@ -62,3 +88,15 @@ function _bnp_cmp_contribs_adjust() { return $adjust; } + +function _contribs_attachments_adjust() { + /** @var \Drupal\burda_cmp\StaticConsentDataInterface $static_consent_data */ + $static_consent_data = \Drupal::service('burda_cmp.static_consent_data'); + return [ + 'google_tag_script_tag__primary' => [ + 'vendorName' => $static_consent_data::VENDOR_GOOGLE_ANALYTICS, + 'vendorId' => $static_consent_data->getVendorId($static_consent_data::VENDOR_GOOGLE_ANALYTICS), + 'purposeIds' => $static_consent_data->getPurposeIds($static_consent_data::VENDOR_GOOGLE_ANALYTICS), + ], + ]; +} diff --git a/src/Form/SettingsForm.php b/src/Form/SettingsForm.php index 221f3bad..ba12f4df 100644 --- a/src/Form/SettingsForm.php +++ b/src/Form/SettingsForm.php @@ -32,10 +32,24 @@ public function getFormId() { public function buildForm(array $form, FormStateInterface $form_state) { $config = $this->config('burda_cmp.settings'); - $form['liveramp_script_url'] = [ + $form['sourcepoint_script_url'] = [ '#type' => 'url', - '#title' => $this->t('LiveRamp script URL'), - '#default_value' => $config->get('liveramp_script_url'), + '#title' => $this->t('Sourcepoint script URL'), + '#default_value' => $config->get('sourcepoint_script_url'), + '#required' => TRUE, + ]; + + $form['sourcepoint_shim_script'] = [ + '#type' => 'textarea', + '#title' => $this->t('Sourcepoint Shim URL'), + '#default_value' => $config->get('sourcepoint_shim_script'), + '#required' => TRUE, + ]; + + $form['sourcepoint_config_code'] = [ + '#type' => 'textarea', + '#title' => $this->t('Sourcepoint Config Code'), + '#default_value' => $config->get('sourcepoint_config_code'), '#required' => TRUE, ]; @@ -47,7 +61,9 @@ public function buildForm(array $form, FormStateInterface $form_state) { */ public function submitForm(array &$form, FormStateInterface $form_state) { $this->config('burda_cmp.settings') - ->set('liveramp_script_url', $form_state->getValue('liveramp_script_url')) + ->set('sourcepoint_script_url', $form_state->getValue('sourcepoint_script_url')) + ->set('sourcepoint_shim_script', $form_state->getValue('sourcepoint_shim_script')) + ->set('sourcepoint_config_code', $form_state->getValue('sourcepoint_config_code')) ->save(); parent::submitForm($form, $form_state); diff --git a/src/Plugin/Block/LiveRamp/OpenPrivacyManagerBlock.php b/src/Plugin/Block/Sourcepoint/OpenPrivacyManagerBlock.php similarity index 63% rename from src/Plugin/Block/LiveRamp/OpenPrivacyManagerBlock.php rename to src/Plugin/Block/Sourcepoint/OpenPrivacyManagerBlock.php index 9f70f3ec..c774bc9e 100644 --- a/src/Plugin/Block/LiveRamp/OpenPrivacyManagerBlock.php +++ b/src/Plugin/Block/Sourcepoint/OpenPrivacyManagerBlock.php @@ -1,16 +1,16 @@ get('privacy_manager_id'); $build = [ 'link' => [ '#type' => 'html_tag', @@ -37,7 +38,12 @@ public function build() { ], '#attached' => [ 'library' => [ - 'burda_cmp/liveramp.open-privacy-manager', + 'burda_cmp/sourcepoint.open-privacy-manager', + ], + 'drupalSettings' => [ + 'burdaCmp' => [ + 'privacyManagerId' => $privacyManagerId, + ], ], ], ], @@ -49,14 +55,18 @@ public function build() { /** * {@inheritdoc} */ - public function buildConfigurationForm(array $form, FormStateInterface $form_state) { + public function buildConfigurationForm( + array $form, + FormStateInterface $form_state + ) { $form = parent::buildConfigurationForm($form, $form_state); $form['link_text'] = [ '#title' => $this->t('Link text'), - '#description' => $this->t('The text of the link (defaults to %link_text)', [ - '%link_text' => $this->t('Open privacy manager'), - ]), + '#description' => $this->t('The text of the link (defaults to %link_text)', + [ + '%link_text' => $this->t('Open privacy manager'), + ]), '#type' => 'textfield', '#default_value' => $this->configuration['link_text'], ]; diff --git a/src/Plugin/Filter/CmpCompliantIFrameFilter.php b/src/Plugin/Filter/CmpCompliantIFrameFilter.php index c3110d85..87f6d652 100644 --- a/src/Plugin/Filter/CmpCompliantIFrameFilter.php +++ b/src/Plugin/Filter/CmpCompliantIFrameFilter.php @@ -124,7 +124,7 @@ public function process($text, $langcode) { $result->setProcessedText(Html::serialize($dom)) ->addAttachments([ 'library' => [ - 'burda_cmp/liveramp.conditional-content', + 'burda_cmp/sourcepoint.conditional-content', ], ]); } diff --git a/src/StaticConsentData.php b/src/StaticConsentData.php index 9eac05b2..b0175c6b 100644 --- a/src/StaticConsentData.php +++ b/src/StaticConsentData.php @@ -26,124 +26,131 @@ public function getAll() { $this->data = [ // Facebook. static::VENDOR_FACEBOOK => [ - 'id' => 10007, + 'id' => '5e716fc09a0b5040d575080f', 'label' => $this->t('Facebook', [], ['context' => 'Cookie consent provider']), // @todo Toggle label should be translatable for Facebook posts. 'toggle_label' => 'Facebook-Posts anzeigen', 'purposes' => [ - 29, + static::PURPOSE_STORE_AND_OR_ACCESS_INFORMATION_ON_A_DEVICE, + static::PURPOSE_FUNCTIONAL, + static::PURPOSE_SOCIAL_MEDIA, ], ], // Google Maps. static::VENDOR_GOOGLE_MAPS => [ - 'id' => 10219, + 'id' => '5eb97b265852312e6a9fbf31', 'label' => $this->t('Google Maps', [], ['context' => 'Cookie consent provider']), // @todo Toggle label should be translatable for Google Maps. 'toggle_label' => 'Google Maps anzeigen', 'purposes' => [ - 26, + static::PURPOSE_STORE_AND_OR_ACCESS_INFORMATION_ON_A_DEVICE, + static::PURPOSE_SOCIAL_MEDIA, + ], + ], + + // Google Analytics. + static::VENDOR_GOOGLE_ANALYTICS => [ + 'id' => '5e542b3a4cd8884eb41b5a72', + 'label' => $this->t('Google Analytics', [], ['context' => 'Cookie consent provider']), + // @todo Toggle label should be translatable for Google Maps. + 'toggle_label' => 'Google Analytics nutzen', + 'purposes' => [ + static::PURPOSE_STORE_AND_OR_ACCESS_INFORMATION_ON_A_DEVICE, + static::PURPOSE_ANALYTIC, ], ], // Instagram. static::VENDOR_INSTAGRAM => [ - 'id' => 10019, + 'id' => '6054c53ca228639c6f285121', 'label' => $this->t('Instagram', [], ['context' => 'Cookie consent provider']), // @todo Toggle label should be translatable for Instagram posts. 'toggle_label' => 'Instagram-Posts anzeigen', 'purposes' => [ - 29, + static::PURPOSE_STORE_AND_OR_ACCESS_INFORMATION_ON_A_DEVICE, + static::PURPOSE_FUNCTIONAL, + static::PURPOSE_SOCIAL_MEDIA, ], ], // Pinterest. static::VENDOR_PINTEREST => [ - 'id' => 10031, + 'id' => '5e839a38b8e05c4e491e738e', 'label' => $this->t('Pinterest', [], ['context' => 'Cookie consent provider']), // @todo Toggle label should be translatable for Pinterest posts. 'toggle_label' => 'Pinterest-Posts anzeigen', 'purposes' => [ - 29, - ], - ], - - // Retyp LLC (OptinMonster). - static::VENDOR_RETYP_LLC => [ - 'id' => 10195, - 'label' => $this->t('Retyp LLC', [], ['context' => 'Cookie consent provider']), - // @todo Toggle label for Retyp LLC / OptinMonster (if needed). - 'toggle_label' => NULL, - 'purposes' => [ - 26, - ], - ], - - // Riddle Technologies AG. - static::VENDOR_RIDDLE => [ - 'id' => 10196, - 'label' => $this->t('Riddle Technologies AG', [], ['context' => 'Cookie consent provider']), - // @todo Toggle label should be translatable for Riddle polls. - 'toggle_label' => 'Riddle-Umfragen anzeigen', - 'purposes' => [ - 26, - 27, + static::PURPOSE_STORE_AND_OR_ACCESS_INFORMATION_ON_A_DEVICE, + static::PURPOSE_FUNCTIONAL, + static::PURPOSE_SOCIAL_MEDIA, ], ], // TargetVideo GmbH. static::VENDOR_TARGETVIDEO_GMBH => [ - 'id' => 10200, + 'id' => '5f0838a5b8e05c065164a384', 'label' => $this->t('TargetVideo GmbH', [], ['context' => 'Cookie consent provider']), // @todo Toggle label for TargetVideo GmbH (if needed). 'toggle_label' => NULL, 'purposes' => [ - 28, + static::PURPOSE_MEASURE_CONTENT_PERFORMANCE ], ], - // Twitter. + // Twitter. / X Corp. static::VENDOR_TWITTER => [ - 'id' => 10006, + 'id' => '5fab0c31a22863611c5f8764', 'label' => $this->t('Twitter', [], ['context' => 'Cookie consent provider']), // @todo Toggle label should be translatable for Twitter posts. 'toggle_label' => 'Twitter-Posts anzeigen', 'purposes' => [ - 29, + static::PURPOSE_STORE_AND_OR_ACCESS_INFORMATION_ON_A_DEVICE, + static::PURPOSE_FUNCTIONAL, + static::PURPOSE_SOCIAL_MEDIA, ], ], // Vimeo. static::VENDOR_VIMEO => [ - 'id' => 10021, + 'id' => '5eac148d4bfee33e7280d13b', 'label' => $this->t('Vimeo', [], ['context' => 'Cookie consent provider']), // @todo Toggle label should be translatable for Vimeo videos. 'toggle_label' => 'Vimeo-Videos anzeigen', 'purposes' => [ - 26, - 29, + static::PURPOSE_STORE_AND_OR_ACCESS_INFORMATION_ON_A_DEVICE, + static::PURPOSE_FUNCTIONAL, + static::PURPOSE_SOCIAL_MEDIA, ], ], // Xandr, Inc. static::VENDOR_XANDR => [ - 'id' => 32, + 'id' => '5e7ced57b8e05c4854221bba', 'label' => $this->t('Xandr, Inc.', [], ['context' => 'Cookie consent provider']), // @todo Toggle label for Xandr, Inc. (if needed). 'toggle_label' => NULL, // @todo Still needs correct purpose IDs for Xandr, Inc. - 'purposes' => [], + 'purposes' => [ + static::PURPOSE_STORE_AND_OR_ACCESS_INFORMATION_ON_A_DEVICE, + static::PURPOSE_USE_LIMITED_DATA_TO_SELECT_ADVERTISING, + static::PURPOSE_CREATE_PROFILES_FOR_PERSONALISED_ADVERTISING, + static::PURPOSE_USE_PROFILES_TO_SELECT_PERSONALISED_ADVERTISING, + static::PURPOSE_MEASURE_ADVERTISING_PERFORMANCE, + static::PURPOSE_DEVELOP_AND_IMPROVE_SERVICES, + ], ], // YouTube. static::VENDOR_YOUTUBE => [ - 'id' => 10020, + 'id' => '5e7ac3fae30e7d1bc1ebf5e8', 'label' => $this->t('YouTube', [], ['context' => 'Cookie consent provider']), // @todo Toggle label should be translatable for YouTube videos. 'toggle_label' => 'YouTube-Videos anzeigen', 'purposes' => [ - 26, - 29, + static::PURPOSE_STORE_AND_OR_ACCESS_INFORMATION_ON_A_DEVICE, + static::PURPOSE_FUNCTIONAL, + static::PURPOSE_SOCIAL_MEDIA, ], ], ]; @@ -158,20 +165,20 @@ public function getAll() { public function getToggleLabel($vendor) { $data = $this->getAll(); - if (is_numeric($vendor)) { + if ($this->isVendorId($vendor)) { $vendor = $this->getVendorName($vendor); } - return isset($data[$vendor]['toggle_label']) ? $data[$vendor]['toggle_label'] : NULL; + return $data[$vendor]['toggle_label'] ?? NULL; } /** * {@inheritdoc} */ - public function getVendorId($vendor) { + public function getVendorId($vendorName) { $data = $this->getAll(); - return isset($data[$vendor]['id']) ? $data[$vendor]['id'] : NULL; + return $data[$vendorName]['id'] ?? NULL; } /** @@ -180,20 +187,20 @@ public function getVendorId($vendor) { public function getVendorLabel($vendor) { $data = $this->getAll(); - if (is_numeric($vendor)) { + if ($this->isVendorId($vendor)) { $vendor = $this->getVendorName($vendor); } - return isset($data[$vendor]['label']) ? $data[$vendor]['label'] : NULL; + return $data[$vendor]['label'] ?? NULL; } /** * {@inheritdoc} */ - public function getVendorName($vendor) { + public function getVendorName($vendorId) { $data = $this->getAll(); - if (($key = array_search($vendor, array_column($data, 'id'))) !== FALSE) { + if (($key = array_search($vendorId, array_column($data, 'id'))) !== FALSE) { return array_keys($data)[$key]; } @@ -203,25 +210,35 @@ public function getVendorName($vendor) { /** * {@inheritdoc} */ - public function getPurposeIds($vendor) { + public function getPurposeIds($vendor): array { $data = $this->getAll(); - if (is_numeric($vendor)) { + if ($this->isVendorId($vendor)) { $vendor = $this->getVendorName($vendor); } - $purposes = isset($data[$vendor]['purposes']) ? $data[$vendor]['purposes'] : []; - - // Ensure legitimate interest purpose. - $purposes[] = 1; + $purposes = $data[$vendor]['purposes'] ?? []; // Filter duplicates. $purposes = array_unique($purposes); - // Sort purposes. - sort($purposes); - return $purposes; } + /** + * {@inheritdoc} + */ + public function getAllVendorIds(): array { + $data = $this->getAll(); + return array_column($data, 'id'); + } + + /** + * {@inheritdoc} + */ + public function isVendorId(string $vendor): bool { + $vendorIds = $this->getAllVendorIds(); + return in_array($vendor, $vendorIds); + } + } diff --git a/src/StaticConsentDataInterface.php b/src/StaticConsentDataInterface.php index 96012b87..b9b131a8 100644 --- a/src/StaticConsentDataInterface.php +++ b/src/StaticConsentDataInterface.php @@ -17,6 +17,11 @@ interface StaticConsentDataInterface { */ const VENDOR_GOOGLE_MAPS = 'google_maps'; + /** + * Vendor name: Google Analytics. + */ + const VENDOR_GOOGLE_ANALYTICS = 'google_analytics'; + /** * Vendor name: Instagram. */ @@ -27,16 +32,6 @@ interface StaticConsentDataInterface { */ const VENDOR_PINTEREST = 'pinterest'; - /** - * Vendor name: Retyp LLC (OptinMonster). - */ - const VENDOR_RETYP_LLC = 'retyp_llc'; - - /** - * Vendor name: Riddle. - */ - const VENDOR_RIDDLE = 'riddle'; - /** * Vendor name: TargetVideo GmbH. */ @@ -62,6 +57,96 @@ interface StaticConsentDataInterface { */ const VENDOR_YOUTUBE = 'youtube'; + /** + * Purpose Name: Store and/or access information on a device. + */ + const PURPOSE_STORE_AND_OR_ACCESS_INFORMATION_ON_A_DEVICE = '6489861f44cf6406ddda4023'; + + /** + * Purpose Name: Use limited data to select advertising. + */ + const PURPOSE_USE_LIMITED_DATA_TO_SELECT_ADVERTISING = '6489861e44cf6406ddda28e9'; + + /** + * Purpose Name: Create profiles for personalised advertising. + */ + const PURPOSE_CREATE_PROFILES_FOR_PERSONALISED_ADVERTISING = '6489861e44cf6406ddda2c78'; + + /** + * Purpose Name: Use profiles to select personalised advertising. + */ + const PURPOSE_USE_PROFILES_TO_SELECT_PERSONALISED_ADVERTISING = '6489861e44cf6406ddda2fa3'; + + /** + * Purpose Name: Create profiles to personalise content. + */ + const PURPOSE_CREATE_PROFILES_TO_PERSONALISE_CONTENT = '6489861e44cf6406ddda32bb'; + + /** + * Purpose Name: Use profiles to select personalised content. + */ + const PURPOSE_USE_PROFILES_TO_SELECT_PERSONALISED_CONTENT = '6489861e44cf6406ddda33c5'; + + /** + * Purpose Name: Measure advertising performance. + */ + const PURPOSE_MEASURE_ADVERTISING_PERFORMANCE = '6489861e44cf6406ddda34a9'; + + /** + * Purpose Name: Measure content performance. + */ + const PURPOSE_MEASURE_CONTENT_PERFORMANCE = '6489861f44cf6406ddda38dc'; + + /** + * Purpose Name: Understand audiences through statistics or combinations ... + */ + const PURPOSE_UNDERSTAND_AUDIENCES_THROUGH_STATISTICS = '6489861f44cf6406ddda3a8c'; + + /** + * Develop and improve services. + */ + const PURPOSE_DEVELOP_AND_IMPROVE_SERVICES = '6489861f44cf6406ddda3cba'; + + /** + * Use limited data to select content. + */ + const PURPOSE_USE_LIMITED_DATA_TO_SELECT_CONTENT = '652692cc25bbd005067b4994'; + + /** + * Unbedingt erforderliche Cookies. + */ + const PURPOSE_ABSOLUTELY_REQUIRED_COOKIES = '6489861f44cf6406ddda4011'; + + /** + * Funktional. + */ + const PURPOSE_FUNCTIONAL = '6489861f44cf6406ddda4016'; + + /** + * Analytik. + */ + const PURPOSE_ANALYTIC = '6489861f44cf6406ddda401a'; + + /** + * Werbung (Nicht-IAB Anbieter). + */ + const PURPOSE_ADS_NON_IAB = '6489861f44cf6406ddda401d'; + + /** + * Soziale Medien. + */ + const PURPOSE_SOCIAL_MEDIA = '6489861f44cf6406ddda401f'; + + /** + * Direktes Marketing. + */ + const PURPOSE_DIRECT_MARKETING = '6493f84f36160804ecc46e5f'; + + /** + * Datenaustausch. + */ + const PURPOSE_DATA_EXCHANGE = '6493f84f36160804ecc46e64'; + /** * Return all static cookie consent data. * @@ -77,14 +162,23 @@ interface StaticConsentDataInterface { */ public function getAll(); + /** + * Return all vendor IDs from static cookie consent data. + * + * @return string[] + * An indexed array containing all vendor IDs from getAll() function as + * values. + */ + public function getAllVendorIds(): array; + /** * Return required purpose IDs for given vendor. * - * @param string|int $vendor + * @param string $vendor * Either a vendor ID or a vendor name as defined by the * StaticConsentDataInterface::VENDOR_* constants. * - * @return int[] + * @return string[] * An array of purpose IDs on success, otherwise an empty array. * * @see \Drupal\burda_cmp\StaticConsentDataInterface @@ -94,7 +188,7 @@ public function getPurposeIds($vendor); /** * Return toggle button label for given vendor. * - * @param string|int $vendor + * @param string $vendor * Either a vendor ID or a vendor name as defined by the * StaticConsentDataInterface::VENDOR_* constants. * @@ -108,21 +202,21 @@ public function getToggleLabel($vendor); /** * Return vendor ID for given vendor name. * - * @param string $vendor + * @param string $vendorName * A vendor name as defined by the * StaticConsentDataInterface::VENDOR_* constants. * - * @return int|null + * @return string|null * The vendor ID on success, otherwise NULL. * * @see \Drupal\burda_cmp\StaticConsentDataInterface */ - public function getVendorId($vendor); + public function getVendorId($vendorName); /** * Return human-readable label for given vendor. * - * @param string|int $vendor + * @param string $vendor * Either a vendor ID or a vendor name as defined by the * StaticConsentDataInterface::VENDOR_* constants. * @@ -136,7 +230,7 @@ public function getVendorLabel($vendor); /** * Return vendor name for given vendor ID. * - * @param int $vendor + * @param string $vendorId * A vendor ID. * * @return string|null @@ -145,6 +239,18 @@ public function getVendorLabel($vendor); * * @see \Drupal\burda_cmp\StaticConsentDataInterface */ - public function getVendorName($vendor); + public function getVendorName($vendorId); + + /** + * Checks if the param is a vendor ID from the static cookie consent data. + * + * @param string $vendor + * A vendor name or a vendor ID. + * + * @return bool + * TRUE, if the vendor value is found as an ID value in the static cookie + * consent data, otherwise FALSE. + */ + public function isVendorId(string $vendor): bool; } diff --git a/templates/burda-cmp-conditional-content.html.twig b/templates/burda-cmp-conditional-content.html.twig index 76d5feb6..87b318f5 100644 --- a/templates/burda-cmp-conditional-content.html.twig +++ b/templates/burda-cmp-conditional-content.html.twig @@ -1,5 +1,5 @@ {%- if content is not empty and vendor is not empty -%} - {{- attach_library('burda_cmp/liveramp.conditional-content') -}} + {{- attach_library('burda_cmp/sourcepoint.conditional-content') -}}