Skip to content

Commit d0dddde

Browse files
Alameen688cphilleo
andauthored
WordAds: Enable A8C CMP banner support (#35165)
* Load CMP scripts from WPCOM public API * Override cookie consent block when CMP is enabled * Allow ad privacy link to resurface the CMP --------- Co-authored-by: Collyn Philleo <[email protected]>
1 parent a359c0f commit d0dddde

File tree

5 files changed

+169
-1
lines changed

5 files changed

+169
-1
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Significance: minor
2+
Type: enhancement
3+
4+
Privacy: Add preliminary support for WordAds Consent Management Provider

projects/plugins/jetpack/extensions/blocks/cookie-consent/cookie-consent.php

+5
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,11 @@ function load_assets( $attr, $content ) {
7474
// and we should send fresh HTML with the cookie block in it.
7575
notify_batcache_that_content_changed();
7676

77+
// Filters the display of the Cookie-consent Block e.g by GDPR CMP banner on WordAds sites.
78+
if ( apply_filters( 'jetpack_disable_cookie_consent_block', false ) ) {
79+
return '';
80+
}
81+
7782
// If the user has already accepted the cookie consent, don't show the block.
7883
if ( isset( $_COOKIE[ COOKIE_NAME ] ) ) {
7984
return '';

projects/plugins/jetpack/modules/wordads/class-wordads.php

+9-1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
require_once WORDADS_ROOT . '/php/class-wordads-cron.php';
2020
require_once WORDADS_ROOT . '/php/class-wordads-california-privacy.php';
2121
require_once WORDADS_ROOT . '/php/class-wordads-ccpa-do-not-sell-link-widget.php';
22+
require_once WORDADS_ROOT . '/php/class-wordads-consent-management-provider.php';
2223

2324
/**
2425
* Primary WordAds class.
@@ -179,6 +180,7 @@ public function __construct() {
179180

180181
if ( is_admin() ) {
181182
WordAds_California_Privacy::init_ajax_actions();
183+
WordAds_Consent_Management_Provider::init_ajax_actions();
182184
}
183185
}
184186

@@ -207,6 +209,11 @@ public function init() {
207209
WordAds_California_Privacy::init();
208210
}
209211

212+
// Initialize CMP if enabled.
213+
if ( isset( $this->params->options['wordads_cmp_enabled'] ) && $this->params->options['wordads_cmp_enabled'] ) {
214+
WordAds_Consent_Management_Provider::init();
215+
}
216+
210217
if ( isset( $_SERVER['REQUEST_URI'] ) && '/ads.txt' === $_SERVER['REQUEST_URI'] ) {
211218

212219
$ads_txt_transient = get_transient( 'wordads_ads_txt' );
@@ -363,7 +370,7 @@ public function insert_head_meta() {
363370
$is_logged_in = is_user_logged_in() ? '1' : '0';
364371
?>
365372
<script<?php echo esc_attr( $data_tags ); ?> type="text/javascript">
366-
var __ATA_PP = { pt: <?php echo esc_js( $pagetype ); ?>, ht: <?php echo esc_js( $hosting_type ); ?>, tn: '<?php echo esc_js( get_stylesheet() ); ?>', uloggedin: <?php echo esc_js( $is_logged_in ); ?>, amp: false, siteid: <?php echo esc_js( $site_id ); ?>, consent: <?php echo esc_js( $consent ); ?>, ad: { label: { text: '<?php echo esc_js( __( 'Advertisements', 'jetpack' ) ); ?>' }, reportAd: { text: '<?php echo esc_js( __( 'Report this ad', 'jetpack' ) ); ?>' } } };
373+
var __ATA_PP = { pt: <?php echo esc_js( $pagetype ); ?>, ht: <?php echo esc_js( $hosting_type ); ?>, tn: '<?php echo esc_js( get_stylesheet() ); ?>', uloggedin: <?php echo esc_js( $is_logged_in ); ?>, amp: false, siteid: <?php echo esc_js( $site_id ); ?>, consent: <?php echo esc_js( $consent ); ?>, ad: { label: { text: '<?php echo esc_js( __( 'Advertisements', 'jetpack' ) ); ?>' }, reportAd: { text: '<?php echo esc_js( __( 'Report this ad', 'jetpack' ) ); ?>' }, privacySettings: { text: '<?php echo esc_js( __( 'Privacy', 'jetpack' ) ); ?>', onClick: function() { window.__tcfapi && window.__tcfapi('showUi'); } } } };
367374
var __ATA = __ATA || {};
368375
__ATA.cmd = __ATA.cmd || [];
369376
__ATA.criteo = __ATA.criteo || {};
@@ -742,6 +749,7 @@ public function get_dynamic_ad_snippet( $section_id, $form_factor = 'square', $l
742749
},
743750
privacySettings: {
744751
text: '{$privacy_settings_text}',
752+
onClick: function() { window.__tcfapi && window.__tcfapi('showUi'); },
745753
}
746754
}
747755
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// eslint-disable-next-line no-unused-vars
2+
function a8c_cmp_callback( data ) {
3+
if ( data && data.scripts && Array.isArray( data.scripts ) ) {
4+
if ( data.config ) {
5+
let configurationScript = document.createElement( 'script' );
6+
configurationScript.id = 'cmp-configuration';
7+
configurationScript.type = 'application/configuration';
8+
configurationScript.innerHTML = JSON.stringify( data.config );
9+
10+
// Add the cmp-configuration script element to the document's body
11+
document.head.appendChild( configurationScript );
12+
}
13+
14+
// Load each cmp script
15+
data.scripts.forEach( function ( scriptUrl ) {
16+
let script = document.createElement( 'script' );
17+
script.src = scriptUrl;
18+
document.head.appendChild( script );
19+
} );
20+
}
21+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
<?php
2+
/**
3+
* WordAds Consent Management Provider
4+
*
5+
* @package automattic/jetpack
6+
*/
7+
8+
use Automattic\Jetpack\Assets;
9+
10+
/**
11+
* Class WordAds_Consent_Management_Provider
12+
*
13+
* This is an integration with the GDPR Consent Management Provider
14+
* to comply with GDPR requirements for privacy and transparency related to advertising.
15+
*/
16+
class WordAds_Consent_Management_Provider {
17+
18+
/**
19+
* IAB specified cookie name for storing the consent string.
20+
*/
21+
const COOKIE_NAME = 'euconsent-v2';
22+
23+
/**
24+
* Initializes loading of the frontend framework.
25+
*/
26+
public static function init() {
27+
// Prevent Cookies & Consent banner from displaying when the CMP is active.
28+
add_filter( 'jetpack_disable_eu_cookie_law_widget', '__return_true' );
29+
add_filter( 'jetpack_disable_cookie_consent_block', '__return_true' );
30+
31+
// Enqueue scripts.
32+
add_action( 'wp_enqueue_scripts', array( __CLASS__, 'enqueue_frontend_scripts' ) );
33+
}
34+
35+
/**
36+
* AJAX handlers for fetching purposes and vendor data and setting the cookie serverside.
37+
*
38+
* Serverside cookie used so that the expiration can be longer than one week.
39+
* This function is called from: /mu-plugins/wordads-ajax.php to ensure they run on all
40+
* requests including admin requests.
41+
*/
42+
public static function init_ajax_actions() {
43+
add_action( 'wp_ajax_gdpr_set_consent', array( __CLASS__, 'handle_set_consent_request' ) );
44+
add_action( 'wp_ajax_nopriv_gdpr_set_consent', array( __CLASS__, 'handle_set_consent_request' ) );
45+
}
46+
47+
/**
48+
* Handler for setting consent cookie AJAX request.
49+
*/
50+
public static function handle_set_consent_request() {
51+
52+
// phpcs:disable WordPress.Security.NonceVerification.Missing
53+
if ( ! isset( $_POST['consent'] ) ) {
54+
wp_send_json_error();
55+
}
56+
57+
// TODO: Is there better sanitizing we can do here?
58+
$consent = trim( wp_unslash( $_POST['consent'] ) ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
59+
60+
setcookie( self::COOKIE_NAME, $consent, time() + YEAR_IN_SECONDS, '/', self::get_cookie_domain(), is_ssl(), false ); // phpcs:ignore Jetpack.Functions.SetCookie -- Client side CMP needs to be able to read this value.
61+
62+
wp_send_json_success( true );
63+
64+
// phpcs:enable WordPress.Security.NonceVerification.Missing
65+
}
66+
67+
/**
68+
* Enqueues the main frontend Javascript.
69+
*/
70+
public static function enqueue_frontend_scripts() {
71+
wp_enqueue_script(
72+
'cmp_script_loader',
73+
Assets::get_file_url_for_environment(
74+
'__inc/build/wordads/js/cmp-loader.min.js',
75+
'modules/wordads/js/cmp-loader.js'
76+
),
77+
array(),
78+
JETPACK__VERSION,
79+
false
80+
);
81+
82+
$request_url = self::get_config_url();
83+
wp_enqueue_script(
84+
'cmp_config_script',
85+
Assets::get_file_url_for_environment(
86+
$request_url,
87+
$request_url
88+
),
89+
array(),
90+
JETPACK__VERSION,
91+
false
92+
);
93+
}
94+
95+
/**
96+
* Gets the value to be used when an opt-in cookie is set.
97+
*
98+
* @return string The value to store in the opt-in cookie.
99+
*/
100+
private static function get_config_url() {
101+
$locale = strtolower( get_locale() ); // Defaults to en_US not en.
102+
$request_url = 'https://public-api.wordpress.com/wpcom/v2/sites/' . self::get_blog_id() . '/cmp/configuration/' . $locale . '/?_jsonp=a8c_cmp_callback';
103+
return $request_url;
104+
}
105+
106+
/**
107+
* Get the blog ID.
108+
*
109+
* @return Object current blog id.
110+
*/
111+
private static function get_blog_id() {
112+
return Jetpack_Options::get_option( 'id' );
113+
}
114+
115+
/**
116+
* Gets the domain to be used for the opt-out cookie.
117+
* Use the site's custom domain, or if the site has a wordpress.com subdomain, use .wordpress.com to share the cookie.
118+
*
119+
* @return string The domain to set for the opt-out cookie.
120+
*/
121+
public static function get_cookie_domain() {
122+
$host = 'localhost';
123+
124+
if ( isset( $_SERVER['HTTP_HOST'] ) ) {
125+
$host = filter_var( wp_unslash( $_SERVER['HTTP_HOST'] ) );
126+
}
127+
128+
return '.wordpress.com' === substr( $host, -strlen( '.wordpress.com' ) ) ? '.wordpress.com' : '.' . $host;
129+
}
130+
}

0 commit comments

Comments
 (0)