initial commit

This commit is contained in:
2024-04-29 13:12:44 +05:45
commit 34887303c5
19300 changed files with 5268802 additions and 0 deletions

View File

@@ -0,0 +1,166 @@
<?php
/**
* Class Google\Site_Kit\Modules\Analytics\AMP_Tag
*
* @package Google\Site_Kit\Modules\Analytics
* @copyright 2021 Google LLC
* @license https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
* @link https://sitekit.withgoogle.com
*/
namespace Google\Site_Kit\Modules\Analytics;
use Google\Site_Kit\Core\Modules\Tags\Module_AMP_Tag;
use Google\Site_Kit\Core\Util\Method_Proxy_Trait;
/**
* Class for AMP tag.
*
* @since 1.24.0
* @access private
* @ignore
*/
class AMP_Tag extends Module_AMP_Tag implements Tag_Interface {
use Method_Proxy_Trait;
/**
* Home domain name.
*
* @since 1.24.0
* @var string
*/
private $home_domain;
/**
* Ads conversion ID.
*
* @since 1.32.0
* @var string
*/
private $ads_conversion_id;
/**
* Sets the current home domain.
*
* @since 1.24.0
*
* @param string $domain Domain name.
*/
public function set_home_domain( $domain ) {
$this->home_domain = $domain;
}
/**
* Sets whether or not to anonymize IP addresses.
*
* @since 1.32.0
*
* @param bool $anonymize_ip Whether to anonymize IP addresses or not.
*/
public function set_anonymize_ip( $anonymize_ip ) {
// Data from AMP documents is always IP anonymized.
// See https://support.google.com/analytics/answer/6343176.
}
/**
* Sets the ads conversion ID.
*
* @since 1.32.0
*
* @param string $ads_conversion_id Ads ID.
*/
public function set_ads_conversion_id( $ads_conversion_id ) {
$this->ads_conversion_id = $ads_conversion_id;
}
/**
* Registers tag hooks.
*
* @since 1.24.0
*/
public function register() {
$render = $this->get_method_proxy_once( 'render' );
// Which actions are run depends on the version of the AMP Plugin
// (https://amp-wp.org/) available. Version >=1.3 exposes a
// new, `amp_print_analytics` action.
// For all AMP modes, AMP plugin version >=1.3.
add_action( 'amp_print_analytics', $render );
// For AMP Standard and Transitional, AMP plugin version <1.3.
add_action( 'wp_footer', $render, 20 );
// For AMP Reader, AMP plugin version <1.3.
add_action( 'amp_post_template_footer', $render, 20 );
// For Web Stories plugin.
add_action( 'web_stories_print_analytics', $render );
// Load amp-analytics component for AMP Reader.
$this->enqueue_amp_reader_component_script( 'amp-analytics', 'https://cdn.ampproject.org/v0/amp-analytics-0.1.js' );
$this->do_init_tag_action();
}
/**
* Outputs gtag <amp-analytics> tag.
*
* @since 1.24.0
*/
protected function render() {
$config = array(
$this->tag_id => array(
'groups' => 'default',
'linker' => array(
'domains' => array( $this->home_domain ),
),
),
);
if ( ! empty( $this->ads_conversion_id ) ) {
$config[ $this->ads_conversion_id ] = array(
'groups' => 'default',
);
}
$gtag_amp_opt = array(
'optoutElementId' => '__gaOptOutExtension',
'vars' => array(
'gtag_id' => $this->tag_id,
'config' => $config,
),
);
/**
* Filters the gtag configuration options for the amp-analytics tag.
*
* You can use the {@see 'googlesitekit_gtag_opt'} filter to do the same for gtag in non-AMP.
*
* @since 1.24.0
* @see https://developers.google.com/gtagjs/devguide/amp
*
* @param array $gtag_amp_opt gtag config options for AMP.
*/
$gtag_amp_opt_filtered = apply_filters( 'googlesitekit_amp_gtag_opt', $gtag_amp_opt );
// Ensure gtag_id is set to the correct value.
if ( ! is_array( $gtag_amp_opt_filtered ) ) {
$gtag_amp_opt_filtered = $gtag_amp_opt;
}
if ( ! isset( $gtag_amp_opt_filtered['vars'] ) || ! is_array( $gtag_amp_opt_filtered['vars'] ) ) {
$gtag_amp_opt_filtered['vars'] = $gtag_amp_opt['vars'];
}
$gtag_amp_opt_filtered['vars']['gtag_id'] = $this->tag_id;
printf( "\n<!-- %s -->\n", esc_html__( 'Google Analytics AMP snippet added by Site Kit', 'google-site-kit' ) );
printf(
'<amp-analytics type="gtag" data-credentials="include"%s><script type="application/json">%s</script></amp-analytics>',
$this->get_tag_blocked_on_consent_attribute(), // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
wp_json_encode( $gtag_amp_opt_filtered )
);
printf( "\n<!-- %s -->\n", esc_html__( 'End Google Analytics AMP snippet added by Site Kit', 'google-site-kit' ) );
}
}

View File

@@ -0,0 +1,167 @@
<?php
/**
* Class Google\Site_Kit\Modules\Analytics\Advanced_Tracking
*
* @package Google\Site_Kit\Modules\Analytics
* @copyright 2021 Google LLC
* @license https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
* @link https://sitekit.withgoogle.com
*/
namespace Google\Site_Kit\Modules\Analytics;
use Google\Site_Kit\Context;
use Google\Site_Kit\Modules\Analytics\Advanced_Tracking\Event_List;
use Google\Site_Kit\Modules\Analytics\Advanced_Tracking\Script_Injector;
use Google\Site_Kit\Modules\Analytics\Advanced_Tracking\AMP_Config_Injector;
use Google\Site_Kit\Modules\Analytics\Advanced_Tracking\Event_List_Registry;
use Google\Site_Kit\Modules\Analytics\Advanced_Tracking\Event;
/**
* Class for Google Analytics Advanced Event Tracking.
*
* @since 1.18.0.
* @access private
* @ignore
*/
final class Advanced_Tracking {
/**
* Plugin context.
*
* @since 1.18.0.
* @var Context
*/
protected $context;
/**
* Map of events to be tracked.
*
* @since 1.18.0.
* @var array Map of Event instances, keyed by their unique ID.
*/
private $events;
/**
* Main class event list registry instance.
*
* @since 1.18.0.
* @var Event_List_Registry
*/
private $event_list_registry;
/**
* Advanced_Tracking constructor.
*
* @since 1.18.0.
*
* @param Context $context Plugin context.
*/
public function __construct( Context $context ) {
$this->context = $context;
$this->event_list_registry = new Event_List_Registry();
}
/**
* Registers functionality through WordPress hooks.
*
* @since 1.18.0.
*/
public function register() {
add_action(
'googlesitekit_analytics_init_tag',
function() {
$this->register_event_lists();
add_action(
'wp_footer',
function() {
$this->set_up_advanced_tracking();
}
);
}
);
add_action(
'googlesitekit_analytics_init_tag_amp',
function() {
$this->register_event_lists();
add_filter(
'googlesitekit_amp_gtag_opt',
function( $gtag_amp_opt ) {
return $this->set_up_advanced_tracking_amp( $gtag_amp_opt );
}
);
}
);
}
/**
* Returns the map of unique events.
*
* @since 1.18.0.
*
* @return array Map of Event instances, keyed by their unique ID.
*/
public function get_events() {
return $this->events;
}
/**
* Injects javascript to track active events.
*
* @since 1.18.0.
*/
private function set_up_advanced_tracking() {
$this->compile_events();
( new Script_Injector( $this->context ) )->inject_event_script( $this->events );
}
/**
* Adds triggers to AMP configuration.
*
* @since 1.18.0.
*
* @param array $gtag_amp_opt gtag config options for AMP.
* @return array Filtered $gtag_amp_opt.
*/
private function set_up_advanced_tracking_amp( $gtag_amp_opt ) {
$this->compile_events();
return ( new AMP_Config_Injector() )->inject_event_configurations( $gtag_amp_opt, $this->events );
}
/**
* Instantiates and registers event lists.
*
* @since 1.18.0.
*/
private function register_event_lists() {
/**
* Fires when the Advanced_Tracking class is ready to receive event lists.
*
* This means that Advanced_Tracking class stores the event lists in the Event_List_Registry instance.
*
* @since 1.18.0.
*
* @param Event_List_Registry $event_list_registry
*/
do_action( 'googlesitekit_analytics_register_event_lists', $this->event_list_registry );
foreach ( $this->event_list_registry->get_lists() as $event_list ) {
$event_list->register();
}
}
/**
* Compiles the list of Event objects.
*
* @since 1.18.0.
*/
private function compile_events() {
$this->events = array_reduce(
$this->event_list_registry->get_lists(),
function ( $events, Event_List $event_list ) {
return array_merge( $events, $event_list->get_events() );
},
array()
);
}
}

View File

@@ -0,0 +1,64 @@
<?php
/**
* Class Google\Site_Kit\Modules\Analytics\Advanced_Tracking\AMP_Config_Injector
*
* @package Google\Site_Kit\Modules\Analytics
* @copyright 2021 Google LLC
* @license https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
* @link https://sitekit.withgoogle.com
*/
namespace Google\Site_Kit\Modules\Analytics\Advanced_Tracking;
/**
* Class for injecting JavaScript based on the registered event configurations.
*
* @since 1.18.0.
* @access private
* @ignore
*/
final class AMP_Config_Injector {
/**
* Creates list of measurement event configurations and javascript to inject.
*
* @since 1.18.0.
*
* @param array $gtag_amp_opt gtag config options for AMP.
* @param array $events The map of Event objects, keyed by their unique ID.
* @return array Filtered $gtag_amp_opt.
*/
public function inject_event_configurations( $gtag_amp_opt, $events ) {
if ( empty( $events ) ) {
return $gtag_amp_opt;
}
if ( ! array_key_exists( 'triggers', $gtag_amp_opt ) ) {
$gtag_amp_opt['triggers'] = array();
}
foreach ( $events as $amp_trigger_key => $event ) {
$event_config = $event->get_config();
$amp_trigger = array();
if ( 'DOMContentLoaded' === $event_config['on'] ) {
$amp_trigger['on'] = 'visible';
} else {
$amp_trigger['on'] = $event_config['on'];
$amp_trigger['selector'] = $event_config['selector'];
}
$amp_trigger['vars'] = array();
$amp_trigger['vars']['event_name'] = $event_config['action'];
if ( is_array( $event_config['metadata'] ) ) {
foreach ( $event_config['metadata'] as $key => $value ) {
$amp_trigger['vars'][ $key ] = $value;
}
}
$gtag_amp_opt['triggers'][ $amp_trigger_key ] = $amp_trigger;
}
return $gtag_amp_opt;
}
}

View File

@@ -0,0 +1,109 @@
<?php
/**
* Class Google\Site_Kit\Modules\Analytics\Advanced_Tracking\Event
*
* @package Google\Site_Kit
* @copyright 2021 Google LLC
* @license https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
* @link https://sitekit.withgoogle.com
*/
namespace Google\Site_Kit\Modules\Analytics\Advanced_Tracking;
use Exception;
/**
* Class for representing a single tracking event that Advanced_Tracking tracks.
*
* @since 1.18.0.
* @access private
* @ignore
*/
final class Event implements \JsonSerializable {
/**
* The measurement event's configuration.
*
* @since 1.18.0.
* @var array
*/
private $config;
/**
* Event constructor.
*
* @since 1.18.0.
*
* @param array $config {
* The event's configuration.
*
* @type string $action Required. The event action / event name to send.
* @type string $on Required. The DOM event to send the event for.
* @type string $selector Required, unless $on is 'DOMContentLoaded'. The DOM selector on which to listen
* to the $on event.
* @type array|null $metadata Optional. Associative array of event metadata to send, such as 'event_category',
* 'event_label' etc, or null to not send any extra event data.
* }
* @throws Exception Thrown when config param is undefined.
*/
public function __construct( $config ) {
$this->config = $this->validate_config( $config );
}
/**
* Returns an associative event containing the event attributes.
*
* @since 1.18.0.
*
* @return array The configuration in JSON-serializable format.
*/
public function jsonSerialize() {
return $this->config;
}
/**
* Returns the measurement event configuration.
*
* @since 1.18.0.
*
* @return array The config.
*/
public function get_config() {
return $this->config;
}
/**
* Validates the configuration keys and value types.
*
* @since 1.18.0.
*
* @param array $config The event's configuration.
* @return array The event's configuration.
* @throws Exception Thrown when invalid keys or value type.
*/
private function validate_config( $config ) {
$valid_keys = array(
'action',
'selector',
'on',
'metadata',
);
foreach ( $config as $key => $value ) {
if ( ! in_array( $key, $valid_keys, true ) ) {
throw new Exception( 'Invalid configuration parameter: ' . $key );
}
}
if ( ! array_key_exists( 'metadata', $config ) ) {
$config['metadata'] = null;
}
if ( array_key_exists( 'on', $config ) && 'DOMContentLoaded' === $config['on'] ) {
$config['selector'] = '';
}
foreach ( $valid_keys as $key ) {
if ( ! array_key_exists( $key, $config ) ) {
throw new Exception( 'Missed configuration parameter: ' . $key );
}
}
return $config;
}
}

View File

@@ -0,0 +1,62 @@
<?php
/**
* Class Google\Site_Kit\Modules\Analytics\Advanced_Tracking\Event_List
*
* @package Google\Site_Kit
* @copyright 2021 Google LLC
* @license https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
* @link https://sitekit.withgoogle.com
*/
namespace Google\Site_Kit\Modules\Analytics\Advanced_Tracking;
/**
* Base class representing a tracking event list.
*
* @since 1.18.0.
* @access private
* @ignore
*/
abstract class Event_List {
/**
* Container for events.
*
* @since 1.18.0.
* @var array Map of events for this list, keyed by their unique ID.
*/
private $events = array();
/**
* Adds events or registers WordPress hook callbacks to add events.
*
* Children classes should extend this to add their events, either generically or by dynamically collecting
* metadata through WordPress hooks.
*
* @since 1.18.0.
*/
abstract public function register();
/**
* Adds a measurement event to the measurement events array.
*
* @since 1.18.0.
*
* @param Event $event The measurement event object.
*/
protected function add_event( Event $event ) {
$hash = md5( wp_json_encode( $event ) );
$this->events[ $hash ] = $event;
}
/**
* Gets the measurement events array.
*
* @since 1.18.0.
*
* @return array The map of events for this list, keyed by their unique ID.
*/
public function get_events() {
return $this->events;
}
}

View File

@@ -0,0 +1,51 @@
<?php
/**
* Class Google\Site_Kit\Modules\Analytics\Advanced_Tracking\Event_List_Registry
*
* @package Google\Site_Kit\Modules\Analytics
* @copyright 2021 Google LLC
* @license https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
* @link https://sitekit.withgoogle.com
*/
namespace Google\Site_Kit\Modules\Analytics\Advanced_Tracking;
/**
* Class for registering third party event lists.
*
* @since 1.18.0.
* @access private
* @ignore
*/
class Event_List_Registry {
/**
* The list of registered event lists.
*
* @since 1.18.0.
* @var Event_List[]
*/
private $event_lists = array();
/**
* Registers an event list.
*
* @since 1.18.0.
*
* @param Event_List $event_list The event list to be registered.
*/
public function register_list( Event_List $event_list ) {
$this->event_lists[] = $event_list;
}
/**
* Gets the list of registered event lists.
*
* @since 1.18.0.
*
* @return Event_List[] The list of registered event lists.
*/
public function get_lists() {
return $this->event_lists;
}
}

View File

@@ -0,0 +1,78 @@
<?php
/**
* Class Google\Site_Kit\Modules\Analytics\Advanced_Tracking\Script_Injector
*
* @package Google\Site_Kit\Modules\Analytics
* @copyright 2021 Google LLC
* @license https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
* @link https://sitekit.withgoogle.com
*/
namespace Google\Site_Kit\Modules\Analytics\Advanced_Tracking;
use Google\Site_Kit\Context;
use Google\Site_Kit\Core\Assets\Manifest;
use Google\Site_Kit\Core\Util\BC_Functions;
/**
* Class for injecting JavaScript based on the registered event configurations.
*
* @since 1.18.0.
* @access private
* @ignore
*/
final class Script_Injector {
/**
* Plugin context.
*
* @since 1.18.0.
* @var Context
*/
protected $context;
/**
* Constructor.
*
* @since 1.18.0.
*
* @param Context $context Plugin context.
*/
public function __construct( Context $context ) {
$this->context = $context;
}
/**
* Creates list of measurement event configurations and javascript to inject.
*
* @since 1.18.0.
*
* @param array $events The map of Event objects, keyed by their unique ID.
*/
public function inject_event_script( $events ) {
if ( empty( $events ) ) {
return;
}
list( $filename ) = Manifest::get( 'analytics-advanced-tracking' );
if ( ! $filename ) {
// Get file contents of script and add it to the page, injecting event configurations into it.
$filename = 'analytics-advanced-tracking.js';
}
$script_path = $this->context->path( "dist/assets/js/{$filename}" );
// phpcs:ignore WordPress.WP.AlternativeFunctions, WordPressVIPMinimum.Performance.FetchingRemoteData
$script_content = file_get_contents( $script_path );
if ( ! $script_content ) {
return;
}
$data_var = sprintf(
'var _googlesitekitAnalyticsTrackingData = %s;',
wp_json_encode( array_values( $events ) )
);
BC_Functions::wp_print_inline_script_tag( $data_var . "\n" . $script_content );
}
}

View File

@@ -0,0 +1,49 @@
<?php
/**
* Class Google\Site_Kit\Modules\Analytics\Google_Service_AnalyticsProvisioning
*
* @package Google\Site_Kit\Modules\Analytics
* @copyright 2021 Google LLC
* @license https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
* @link https://sitekit.withgoogle.com
*/
namespace Google\Site_Kit\Modules\Analytics;
use Google\Site_Kit_Dependencies\Google_Service_Analytics;
use Google\Site_Kit_Dependencies\Google_Client;
/**
* Class for Analytics Provisioning service.
*
* @since 1.9.0
* @access private
* @ignore
*/
class Google_Service_AnalyticsProvisioning extends Google_Service_Analytics {
/**
* Constructs the internal representation of the Analytics service.
*
* @since 1.9.0
*
* @param Google_Client $client The client used to deliver requests.
* @param string $rootUrl The root URL used for requests to the service.
*/
public function __construct( Google_Client $client, $rootUrl = null ) { // phpcs:ignore WordPress.NamingConventions.ValidVariableName
parent::__construct( $client, $rootUrl ); // phpcs:ignore WordPress.NamingConventions.ValidVariableName
$this->provisioning = new Proxy_Provisioning(
$this,
$this->serviceName, // phpcs:ignore WordPress.NamingConventions.ValidVariableName
'provisioning',
array(
'methods' => array(
'createAccountTicket' => array(
'path' => 'provisioning/createAccountTicket',
'httpMethod' => 'POST',
'parameters' => array(),
),
),
)
);
}
}

View File

@@ -0,0 +1,79 @@
<?php
/**
* Class Google\Site_Kit\Modules\Analytics\Proxy_AccountTicket
*
* @package Google\Site_Kit\Modules\Analytics
* @copyright 2021 Google LLC
* @license https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
* @link https://sitekit.withgoogle.com
*/
namespace Google\Site_Kit\Modules\Analytics;
use Google\Site_Kit_Dependencies\Google\Service\Analytics\AccountTicket as Google_Service_Analytics_AccountTicket;
/**
* Class for the Analytics provisioning Account Ticket object.
*
* @since 1.9.0
* @access private
* @ignore
*/
class Proxy_AccountTicket extends Google_Service_Analytics_AccountTicket {
/**
* The site ID.
*
* @since 1.9.0
* @var String
*/
public $site_id = '';
/**
* The site secret.
*
* @since 1.9.0
* @var String
*/
public $site_secret = '';
/**
* Gets the site ID.
*
* @since 1.9.0
*/
public function getSiteId() {
return $this->site_id;
}
/**
* Sets the site ID.
*
* @since 1.9.0
*
* @param string $id The site id.
*/
public function setSiteId( $id ) {
$this->site_id = $id;
}
/**
* Gets the site secret.
*
* @since 1.9.0
*/
public function getSiteSecret() {
return $this->site_secret;
}
/**
* Sets the site secret.
*
* @since 1.9.0
*
* @param string $secret The site secret.
*/
public function setSiteSecret( $secret ) {
$this->site_secret = $secret;
}
}

View File

@@ -0,0 +1,40 @@
<?php
/**
* Class Google\Site_Kit\Modules\Analytics\Proxy_Provisioning
*
* @package Google\Site_Kit\Modules\Analytics
* @copyright 2021 Google LLC
* @license https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
* @link https://sitekit.withgoogle.com
*/
namespace Google\Site_Kit\Modules\Analytics;
use Google\Site_Kit\Core\Modules\Module_Settings;
use Google\Site_Kit\Core\Storage\Setting_With_Legacy_Keys_Trait;
use Google\Site_Kit\Modules\Analytics\Proxy_AccountTicket;
use \Google\Site_Kit_Dependencies\Google_Service_Resource;
/**
* Class for Analytics provisioning.
*
* @since 1.9.0
* @access private
* @ignore
*/
class Proxy_Provisioning extends Google_Service_Resource {
/**
* Creates an account ticket. (provisioning.createAccountTicket)
*
* @since 1.9.0
*
* @param Proxy_AccountTicket $post_body The post body to send.
* @param array $opt_params Optional parameters. Pass site_id and site_secret here.
* @return Google_Service_Analytics_AccountTicket
*/
public function createAccountTicket( Proxy_AccountTicket $post_body, $opt_params = array() ) {
$params = array( 'postBody' => $post_body );
$params = array_merge( $params, $opt_params );
return $this->call( 'createAccountTicket', array( $params ), 'Google\Site_Kit_Dependencies\Google_Service_Analytics_AccountTicket' );
}
}

View File

@@ -0,0 +1,222 @@
<?php
/**
* Class Google\Site_Kit\Modules\Analytics\Settings
*
* @package Google\Site_Kit\Modules\Analytics
* @copyright 2021 Google LLC
* @license https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
* @link https://sitekit.withgoogle.com
*/
namespace Google\Site_Kit\Modules\Analytics;
use Google\Site_Kit\Core\Modules\Module_Settings;
use Google\Site_Kit\Core\Storage\Setting_With_Legacy_Keys_Trait;
use Google\Site_Kit\Core\Storage\Setting_With_Owned_Keys_Interface;
use Google\Site_Kit\Core\Storage\Setting_With_Owned_Keys_Trait;
/**
* Class for Analytics settings.
*
* @since 1.2.0
* @access private
* @ignore
*/
class Settings extends Module_Settings implements Setting_With_Owned_Keys_Interface {
use Setting_With_Legacy_Keys_Trait, Setting_With_Owned_Keys_Trait;
const OPTION = 'googlesitekit_analytics_settings';
/**
* Registers the setting in WordPress.
*
* @since 1.2.0
*/
public function register() {
parent::register();
$this->register_legacy_keys_migration(
array(
'accountId' => 'accountID',
'profileId' => 'profileID',
'propertyId' => 'propertyID',
'internalWebPropertyId' => 'internalWebPropertyID',
)
);
$this->register_owned_keys();
// Backwards compatibility with previous dedicated option.
add_filter(
'default_option_' . self::OPTION,
function ( $default ) {
// Only fallback to the legacy option if the linked state is not filtered.
// This filter is documented below.
if ( is_null( apply_filters( 'googlesitekit_analytics_adsense_linked', null ) ) ) {
$default['adsenseLinked'] = (bool) $this->options->get( 'googlesitekit_analytics_adsense_linked' );
}
// `canUseSnippet` is a computed setting, so this sets the value if settings have not been saved yet.
// This filter is documented below.
$can_use_snippet = apply_filters( 'googlesitekit_analytics_can_use_snippet', true );
if ( is_bool( $can_use_snippet ) ) {
$default['canUseSnippet'] = $can_use_snippet;
}
return $default;
}
);
add_filter(
'option_' . self::OPTION,
function ( $option ) {
/**
* Filters the Google Analytics account ID to use.
*
* @since 1.0.0
*
* @param string $account_id Empty by default, will fall back to the option value if not set.
*/
$account_id = apply_filters( 'googlesitekit_analytics_account_id', '' );
if ( ! empty( $account_id ) ) {
$option['accountID'] = $account_id;
}
/**
* Filters the Google Analytics property ID to use.
*
* @since 1.0.0
*
* @param string $property_id Empty by default, will fall back to the option value if not set.
*/
$property_id = apply_filters( 'googlesitekit_analytics_property_id', '' );
if ( ! empty( $property_id ) ) {
$option['propertyID'] = $property_id;
}
/**
* Filters the Google Analytics internal web property ID to use.
*
* @since 1.0.0
*
* @param string $internal_web_property_id Empty by default, will fall back to the option value if not set.
*/
$internal_web_property_id = apply_filters( 'googlesitekit_analytics_internal_web_property_id', '' );
if ( ! empty( $internal_web_property_id ) ) {
$option['internalWebPropertyID'] = $internal_web_property_id;
}
/**
* Filters the Google Analytics profile / view ID to use.
*
* @since 1.0.0
*
* @param string $profile_id Empty by default, will fall back to the option value if not set.
*/
$profile_id = apply_filters( 'googlesitekit_analytics_view_id', '' );
if ( ! empty( $profile_id ) ) {
$option['profileID'] = $profile_id;
}
/**
* Filters the linked state of AdSense with Analytics.
*
* This filter exists so that adsenseLinked can only be truthy if the AdSense module is active,
* regardless of the saved setting.
*
* @since 1.3.0
* @param bool $adsense_linked Null by default, will fallback to the option value if not set.
*/
$adsense_linked = apply_filters( 'googlesitekit_analytics_adsense_linked', null );
if ( is_bool( $adsense_linked ) ) {
$option['adsenseLinked'] = $adsense_linked;
}
/**
* Filters the state of the can use snipped setting.
*
* This filter exists so that useSnippet can be restored to true when the Tag Manager module
* is disconnected, ensuring the Analytics snippet is always included.
*
* @since 1.28.0
* @param bool $can_use_snippet Whether or not `useSnippet` can control snippet output. Default: `true`.
*/
$can_use_snippet = apply_filters( 'googlesitekit_analytics_can_use_snippet', true );
if ( is_bool( $can_use_snippet ) ) {
$option['canUseSnippet'] = $can_use_snippet;
}
return $option;
}
);
}
/**
* Returns keys for owned settings.
*
* @since 1.16.0
*
* @return array An array of keys for owned settings.
*/
public function get_owned_keys() {
return array(
'accountID',
'internalWebPropertyID',
'profileID',
'propertyID',
);
}
/**
* Gets the default value.
*
* @since 1.2.0
*
* @return array
*/
protected function get_default() {
return array(
'ownerID' => 0,
'accountID' => '',
'adsenseLinked' => false,
'adsConversionID' => '',
'anonymizeIP' => true,
'internalWebPropertyID' => '',
'profileID' => '',
'propertyID' => '',
'trackingDisabled' => array( 'loggedinUsers' ),
'useSnippet' => true,
'canUseSnippet' => true,
);
}
/**
* Gets the callback for sanitizing the setting's value before saving.
*
* @since 1.6.0
*
* @return callable|null
*/
protected function get_sanitize_callback() {
return function( $option ) {
if ( is_array( $option ) ) {
if ( isset( $option['useSnippet'] ) ) {
$option['useSnippet'] = (bool) $option['useSnippet'];
}
if ( isset( $option['canUseSnippet'] ) ) {
$option['canUseSnippet'] = (bool) $option['canUseSnippet'];
}
if ( isset( $option['anonymizeIP'] ) ) {
$option['anonymizeIP'] = (bool) $option['anonymizeIP'];
}
if ( isset( $option['trackingDisabled'] ) ) {
$option['trackingDisabled'] = (array) $option['trackingDisabled'];
}
if ( isset( $option['adsenseLinked'] ) ) {
$option['adsenseLinked'] = (bool) $option['adsenseLinked'];
}
}
return $option;
};
}
}

View File

@@ -0,0 +1,36 @@
<?php
/**
* Class Google\Site_Kit\Modules\Analytics\Tag_Guard
*
* @package Google\Site_Kit\Modules\Analytics
* @copyright 2021 Google LLC
* @license https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
* @link https://sitekit.withgoogle.com
*/
namespace Google\Site_Kit\Modules\Analytics;
use Google\Site_Kit\Core\Modules\Tags\Module_Tag_Guard;
/**
* Class for the Analytics tag guard.
*
* @since 1.24.0
* @access private
* @ignore
*/
class Tag_Guard extends Module_Tag_Guard {
/**
* Determines whether the guarded tag can be activated or not.
*
* @since 1.24.0
*
* @return bool|WP_Error TRUE if guarded tag can be activated, otherwise FALSE or an error.
*/
public function can_activate() {
$settings = $this->settings->get();
return $settings['canUseSnippet'] && ! empty( $settings['useSnippet'] ) && ! empty( $settings['propertyID'] );
}
}

View File

@@ -0,0 +1,47 @@
<?php
/**
* Class Google\Site_Kit\Modules\Analytics\Tag_Interface
*
* @package Google\Site_Kit\Modules\Analytics
* @copyright 2021 Google LLC
* @license https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
* @link https://sitekit.withgoogle.com
*/
namespace Google\Site_Kit\Modules\Analytics;
/**
* Interface for an Analytics tag.
*
* @since 1.32.0
* @access private
* @ignore
*/
interface Tag_Interface {
/**
* Sets the current home domain.
*
* @since 1.32.0
*
* @param string $domain Domain name.
*/
public function set_home_domain( $domain );
/**
* Sets whether or not to anonymize IP addresses.
*
* @since 1.32.0
*
* @param bool $anonymize_ip Whether to anonymize IP addresses or not.
*/
public function set_anonymize_ip( $anonymize_ip );
/**
* Sets the ads conversion ID.
*
* @since 1.32.0
*
* @param string $ads_conversion_id Ads ID.
*/
public function set_ads_conversion_id( $ads_conversion_id );
}

View File

@@ -0,0 +1,218 @@
<?php
/**
* Class Google\Site_Kit\Modules\Analytics\Web_Tag
*
* @package Google\Site_Kit\Modules\Analytics
* @copyright 2021 Google LLC
* @license https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
* @link https://sitekit.withgoogle.com
*/
namespace Google\Site_Kit\Modules\Analytics;
use Google\Site_Kit\Core\Modules\Tags\Module_Web_Tag;
use Google\Site_Kit\Core\Util\Method_Proxy_Trait;
use Google\Site_Kit\Core\Tags\Tag_With_DNS_Prefetch_Trait;
/**
* Class for Web tag.
*
* @since 1.24.0
* @access private
* @ignore
*/
class Web_Tag extends Module_Web_Tag implements Tag_Interface {
use Method_Proxy_Trait, Tag_With_DNS_Prefetch_Trait;
/**
* Home domain name.
*
* @since 1.24.0
* @var string
*/
private $home_domain;
/**
* Whether or not to anonymize IP addresses.
*
* @since 1.24.0
* @var bool
*/
private $anonymize_ip;
/**
* Ads conversion ID.
*
* @since 1.32.0
* @var string
*/
private $ads_conversion_id;
/**
* Sets the current home domain.
*
* @since 1.24.0
*
* @param string $domain Domain name.
*/
public function set_home_domain( $domain ) {
$this->home_domain = $domain;
}
/**
* Sets whether or not to anonymize IP addresses.
*
* @since 1.24.0
*
* @param bool $anonymize_ip Whether to anonymize IP addresses or not.
*/
public function set_anonymize_ip( $anonymize_ip ) {
$this->anonymize_ip = (bool) $anonymize_ip;
}
/**
* Sets the ads conversion ID.
*
* @since 1.32.0
*
* @param string $ads_conversion_id Ads ID.
*/
public function set_ads_conversion_id( $ads_conversion_id ) {
$this->ads_conversion_id = $ads_conversion_id;
}
/**
* Registers tag hooks.
*
* @since 1.24.0
*/
public function register() {
add_action( 'wp_enqueue_scripts', $this->get_method_proxy( 'enqueue_gtag_script' ) );
add_filter(
'wp_resource_hints',
$this->get_dns_prefetch_hints_callback( '//www.googletagmanager.com' ),
10,
2
);
$this->do_init_tag_action();
}
/**
* Outputs gtag snippet.
*
* @since 1.24.0
*/
protected function render() {
// Do nothing, gtag script is enqueued.
}
/**
* Enqueues gtag script.
*
* @since 1.24.0
*/
protected function enqueue_gtag_script() {
$gtag_opt = array();
$gtag_src = 'https://www.googletagmanager.com/gtag/js?id=' . rawurlencode( $this->tag_id );
// phpcs:ignore WordPress.WP.EnqueuedResourceParameters.MissingVersion
wp_enqueue_script( 'google_gtagjs', $gtag_src, false, null, false );
wp_script_add_data( 'google_gtagjs', 'script_execution', 'async' );
wp_add_inline_script( 'google_gtagjs', 'window.dataLayer = window.dataLayer || [];function gtag(){dataLayer.push(arguments);}' );
if ( ! empty( $this->home_domain ) ) {
$gtag_opt['linker'] = array( 'domains' => array( $this->home_domain ) );
}
if ( $this->anonymize_ip ) {
// See https://developers.google.com/analytics/devguides/collection/gtagjs/ip-anonymization.
$gtag_opt['anonymize_ip'] = true;
}
/**
* Filters the gtag configuration options for the Analytics snippet.
*
* You can use the {@see 'googlesitekit_amp_gtag_opt'} filter to do the same for gtag in AMP.
*
* @since 1.24.0
*
* @see https://developers.google.com/gtagjs/devguide/configure
*
* @param array $gtag_opt gtag config options.
*/
$gtag_opt = apply_filters( 'googlesitekit_gtag_opt', $gtag_opt );
if ( ! empty( $gtag_opt['linker'] ) ) {
$linker = wp_json_encode( $gtag_opt['linker'] );
$linker = sprintf( "gtag('set', 'linker', %s );", $linker );
wp_add_inline_script( 'google_gtagjs', $linker );
}
unset( $gtag_opt['linker'] );
wp_add_inline_script( 'google_gtagjs', 'gtag("js", new Date());' );
wp_add_inline_script( 'google_gtagjs', 'gtag("set", "developer_id.dZTNiMT", true);' ); // Site Kit developer ID.
if ( empty( $gtag_opt ) ) {
$config = sprintf( 'gtag("config", "%s");', esc_js( $this->tag_id ) );
wp_add_inline_script( 'google_gtagjs', $config );
} else {
$config = sprintf( 'gtag("config", "%s", %s);', esc_js( $this->tag_id ), wp_json_encode( $gtag_opt ) );
wp_add_inline_script( 'google_gtagjs', $config );
}
$this->add_inline_ads_conversion_id_config();
$block_on_consent_attrs = $this->get_tag_blocked_on_consent_attribute();
$filter_google_gtagjs = function ( $tag, $handle ) use ( $block_on_consent_attrs, $gtag_src ) {
if ( 'google_gtagjs' !== $handle ) {
return $tag;
}
$snippet_comment_begin = sprintf( "\n<!-- %s -->\n", esc_html__( 'Google Analytics snippet added by Site Kit', 'google-site-kit' ) );
$snippet_comment_end = sprintf( "\n<!-- %s -->\n", esc_html__( 'End Google Analytics snippet added by Site Kit', 'google-site-kit' ) );
if ( $block_on_consent_attrs ) {
$tag = str_replace(
array(
"<script src='$gtag_src'", // phpcs:ignore WordPress.WP.EnqueuedResources.NonEnqueuedScript
"<script src=\"$gtag_src\"", // phpcs:ignore WordPress.WP.EnqueuedResources.NonEnqueuedScript
"<script type='text/javascript' src='$gtag_src'", // phpcs:ignore WordPress.WP.EnqueuedResources.NonEnqueuedScript
"<script type=\"text/javascript\" src=\"$gtag_src\"", // phpcs:ignore WordPress.WP.EnqueuedResources.NonEnqueuedScript
),
array( // `type` attribute intentionally excluded in replacements.
"<script{$block_on_consent_attrs} src='$gtag_src'", // phpcs:ignore WordPress.WP.EnqueuedResources.NonEnqueuedScript
"<script{$block_on_consent_attrs} src=\"$gtag_src\"", // phpcs:ignore WordPress.WP.EnqueuedResources.NonEnqueuedScript
"<script{$block_on_consent_attrs} src='$gtag_src'", // phpcs:ignore WordPress.WP.EnqueuedResources.NonEnqueuedScript
"<script{$block_on_consent_attrs} src=\"$gtag_src\"", // phpcs:ignore WordPress.WP.EnqueuedResources.NonEnqueuedScript
),
$tag
);
}
return $snippet_comment_begin . $tag . $snippet_comment_end;
};
add_filter( 'script_loader_tag', $filter_google_gtagjs, 10, 2 );
}
/**
* Adds an inline script to configure ads conversion tracking.
*
* @since 1.32.0
*/
protected function add_inline_ads_conversion_id_config() {
if ( $this->ads_conversion_id ) {
wp_add_inline_script(
'google_gtagjs',
sprintf( 'gtag("config", "%s");', esc_js( $this->ads_conversion_id ) )
);
}
}
}