diff --git a/includes/Core/Consent_Mode/Consent_Mode.php b/includes/Core/Consent_Mode/Consent_Mode.php index 8db7c528b6b..2d973335a1b 100644 --- a/includes/Core/Consent_Mode/Consent_Mode.php +++ b/includes/Core/Consent_Mode/Consent_Mode.php @@ -12,6 +12,8 @@ use Google\Site_Kit\Context; use Google\Site_Kit\Core\Storage\Options; +use Google\Site_Kit\Core\Util\Feature_Flags; +use Google\Site_Kit\Core\Util\Method_Proxy_Trait; /** * Class for handling Consent Mode. @@ -21,6 +23,7 @@ * @ignore */ class Consent_Mode { + use Method_Proxy_Trait; /** * Consent_Mode_Settings instance. @@ -60,5 +63,37 @@ public function __construct( Context $context, Options $options = null ) { public function register() { $this->consent_mode_settings->register(); $this->rest_controller->register(); + + if ( Feature_Flags::enabled( 'consentMode' ) && $this->consent_mode_settings->is_consent_mode_enabled() ) { + // The `wp_head` action is used to ensure the snippets are printed in the head on the front-end only, not admin pages. + add_action( + 'wp_head', + $this->get_method_proxy( 'render_gtag_consent_snippet' ), + 1 // Set priority to 1 to ensure the snippet is printed with top priority in the head. + ); + } + } + + /** + * Prints the gtag consent snippet. + * + * @since n.e.x.t + */ + protected function render_gtag_consent_snippet() { + $consent_defaults = array( + 'ad_personalization' => 'denied', + 'ad_storage' => 'denied', + 'ad_user_data' => 'denied', + 'analytics_storage' => 'denied', + 'regions' => $this->consent_mode_settings->get_regions(), + ); + ?> + + + + get()['enabled']; + } + + /** + * Accessor for the `regions` setting. + * + * @since n.e.x.t + * + * @return array Array of ISO 3166-2 region codes. + */ + public function get_regions() { + return $this->get()['regions']; + } } diff --git a/tests/e2e/specs/front-end/consent-mode.test.js b/tests/e2e/specs/front-end/consent-mode.test.js new file mode 100644 index 00000000000..cd16dc30a62 --- /dev/null +++ b/tests/e2e/specs/front-end/consent-mode.test.js @@ -0,0 +1,103 @@ +/** + * Consent Mode test. + * + * Site Kit by Google, Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * WordPress dependencies + */ +import { activatePlugin, createURL } from '@wordpress/e2e-test-utils'; + +/** + * Internal dependencies + */ +import { + setSiteVerification, + setSearchConsoleProperty, + enableFeature, + wpApiFetch, +} from '../../utils'; + +const eeaRegions = [ + 'AT', + 'BE', + 'BG', + 'CH', + 'CY', + 'CZ', + 'DE', + 'DK', + 'EE', + 'ES', + 'FI', + 'FR', + 'GR', + 'HR', + 'HU', + 'IE', + 'IS', + 'IT', + 'LI', + 'LT', + 'LU', + 'LV', + 'MT', + 'NL', + 'NO', + 'PL', + 'PT', + 'RO', + 'SE', + 'SI', + 'SK', + 'UK', +]; + +describe( 'Consent Mode snippet', () => { + beforeAll( async () => { + await activatePlugin( 'e2e-tests-proxy-auth-plugin' ); + await setSiteVerification(); + await setSearchConsoleProperty(); + await enableFeature( 'consentMode' ); + await wpApiFetch( { + path: 'google-site-kit/v1/core/site/data/consent-mode', + method: 'post', + data: { data: { settings: { enabled: true } } }, + } ); + } ); + + beforeEach( async () => { + await page.goto( createURL( '/hello-world' ), { waitUntil: 'load' } ); + } ); + + it( 'configures the Consent Mode defaults', async () => { + const dataLayer = await page.evaluate( () => window.dataLayer ); + + expect( dataLayer ).toEqual( [ + { + 0: 'consent', + 1: 'default', + 2: { + ad_personalization: 'denied', + ad_storage: 'denied', + ad_user_data: 'denied', + analytics_storage: 'denied', + regions: eeaRegions, + }, + }, + ] ); + } ); +} ); diff --git a/tests/phpunit/integration/Core/Consent_Mode/Consent_ModeTest.php b/tests/phpunit/integration/Core/Consent_Mode/Consent_ModeTest.php new file mode 100644 index 00000000000..bcfb2ded15b --- /dev/null +++ b/tests/phpunit/integration/Core/Consent_Mode/Consent_ModeTest.php @@ -0,0 +1,67 @@ +enable_feature( 'consentMode' ); + + $this->context = new Context( GOOGLESITEKIT_PLUGIN_MAIN_FILE ); + $this->options = new Options( $this->context ); + } + + public function test_renders_consent_mode_snippet_when_enabled() { + remove_all_actions( 'wp_head' ); + + ( new Consent_Mode_Settings( $this->options ) )->set( array( 'enabled' => true ) ); + + $consent_mode = new Consent_Mode( $this->context, $this->options ); + $consent_mode->register(); + + $output = $this->capture_action( 'wp_head' ); + + $this->assertStringContainsString( 'Google tag (gtag.js) Consent Mode snippet added by Site Kit', $output ); + } + + public function test_does_not_render_consent_mode_snippet_when_disabled() { + remove_all_actions( 'wp_head' ); + + $consent_mode = new Consent_Mode( $this->context, $this->options ); + $consent_mode->register(); + + $output = $this->capture_action( 'wp_head' ); + + $this->assertStringNotContainsString( 'Google tag (gtag.js) Consent Mode snippet added by Site Kit', $output ); + } +} diff --git a/tests/phpunit/integration/Core/Consent_Mode/Consent_Mode_SettingsTest.php b/tests/phpunit/integration/Core/Consent_Mode/Consent_Mode_SettingsTest.php index a0180631b41..51d61b65f0c 100644 --- a/tests/phpunit/integration/Core/Consent_Mode/Consent_Mode_SettingsTest.php +++ b/tests/phpunit/integration/Core/Consent_Mode/Consent_Mode_SettingsTest.php @@ -150,4 +150,22 @@ public function test_get_sanitize_callback( $input, $expected ) { $this->settings->set( $input ); $this->assertEqualSetsWithIndex( $expected, $this->settings->get() ); } + + public function test_is_consent_mode_enabled() { + $this->assertFalse( $this->settings->is_consent_mode_enabled() ); + + $this->settings->set( array( 'enabled' => true ) ); + $this->assertTrue( $this->settings->is_consent_mode_enabled() ); + + $this->settings->set( array( 'enabled' => false ) ); + $this->assertFalse( $this->settings->is_consent_mode_enabled() ); + } + + public function test_get_regions() { + $this->assertEquals( Regions::EEA, $this->settings->get_regions() ); + + $regions = array( 'SG', 'UA-AS' ); + $this->settings->set( array( 'regions' => $regions ) ); + $this->assertEquals( $regions, $this->settings->get_regions() ); + } }