Skip to content

Commit

Permalink
feat(analytics): automatically link GA4 with Site Kit (#1698)
Browse files Browse the repository at this point in the history
  • Loading branch information
adekbadek authored Jun 10, 2022
1 parent d08d666 commit 266135f
Show file tree
Hide file tree
Showing 5 changed files with 229 additions and 53 deletions.
37 changes: 0 additions & 37 deletions includes/class-analytics.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ class Analytics {
public function __construct() {
add_filter( 'googlesitekit_amp_gtag_opt', [ __CLASS__, 'read_amp_analytics_config' ] );
add_action( 'wp_footer', [ __CLASS__, 'insert_gtag_amp_analytics' ], 99 ); // This has to be run after the filter above steals the analytics config.
add_action( 'wp_footer', [ __CLASS__, 'insert_ga4_analytics' ] );

add_action( 'wp_enqueue_scripts', [ __CLASS__, 'handle_custom_dimensions_reporting' ] );
add_action( 'wp_footer', [ __CLASS__, 'inject_non_amp_events' ] );
Expand Down Expand Up @@ -839,41 +838,5 @@ protected static function output_js_ini_load_event( $event ) {
</script>
<?php
}

/**
* Add GA4 analytics support to AMP pages.
*/
public static function insert_ga4_analytics() {
if ( ! function_exists( 'is_amp_endpoint' ) || ! is_amp_endpoint() ) {
return;
}
$sitekit_ga4_settings = false;
if ( class_exists( '\Google\Site_Kit\Modules\Analytics_4\Settings' ) ) {
$sitekit_ga4_settings = get_option( \Google\Site_Kit\Modules\Analytics_4\Settings::OPTION, false );
}
if ( false === $sitekit_ga4_settings ) {
return;
}
if ( ! $sitekit_ga4_settings['useSnippet'] || ! isset( $sitekit_ga4_settings['measurementID'] ) ) {
return;
}
$ga4_measurement_id = $sitekit_ga4_settings['measurementID'];
// See https://github.com/analytics-debugger/google-analytics-4-for-amp.
$config_path = Newspack::plugin_url() . '/includes/raw_assets/ga4.json';

?>
<amp-analytics type="googleanalytics" config="<?php echo esc_attr( $config_path ); ?>" data-credentials="include">
<script type="application/json">
{
"vars": {
"GA4_MEASUREMENT_ID": "<?php echo esc_attr( $ga4_measurement_id ); ?>",
"DEFAULT_PAGEVIEW_ENABLED": true,
"GOOGLE_CONSENT_ENABLED": false
}
}
</script>
</amp-analytics>
<?php
}
}
new Analytics();
1 change: 1 addition & 0 deletions includes/class-newspack.php
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ private function includes() {
// Integrations w/ third-party plugins.
include_once NEWSPACK_ABSPATH . 'includes/plugins/class-jetpack.php';
include_once NEWSPACK_ABSPATH . 'includes/plugins/class-gravityforms.php';
include_once NEWSPACK_ABSPATH . 'includes/plugins/google-site-kit/class-googlesitekit.php';

include_once NEWSPACK_ABSPATH . 'includes/class-patches.php';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,22 +70,6 @@ public function is_module_configured( $module ) {
return ! empty( $module_info['setupComplete'] );
}

/**
* Get whether the current user is connected.
*
* @return bool Whether the user is connected to Google through Site Kit.
*/
public function is_user_connected() {
global $wpdb;

$user_id = get_current_user_id();
if ( ! $user_id ) {
return false;
}

return ! empty( get_user_meta( $user_id, $wpdb->prefix . 'googlesitekit_site_verified_meta', true ) );
}

/**
* Check if module is active.
*
Expand Down
144 changes: 144 additions & 0 deletions includes/plugins/google-site-kit/class-googlesitekit.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
<?php
/**
* Google Site Kit integration class.
*
* @package Newspack
*/

namespace Newspack;

use Google\Site_Kit\Context;

defined( 'ABSPATH' ) || exit;

/**
* Main class.
*/
class GoogleSiteKit {
const GA4_SETUP_DONE_OPTION_NAME = 'newspack_analytics_has_set_up_ga4';

/**
* Initialize hooks and filters.
*/
public static function init() {
add_action( 'admin_init', [ __CLASS__, 'setup_sitekit_ga4' ] );
add_action( 'wp_footer', [ __CLASS__, 'insert_ga4_analytics' ] );
}

/**
* Add GA4 analytics pageview reporting to AMP pages.
*/
public static function insert_ga4_analytics() {
if ( ! function_exists( 'is_amp_endpoint' ) || ! is_amp_endpoint() ) {
return;
}
$sitekit_ga4_settings = self::get_sitekit_ga4_settings();
if ( false === $sitekit_ga4_settings || ! $sitekit_ga4_settings['useSnippet'] || ! isset( $sitekit_ga4_settings['measurementID'] ) ) {
return;
}
$ga4_measurement_id = $sitekit_ga4_settings['measurementID'];
// See https://github.com/analytics-debugger/google-analytics-4-for-amp.
$config_path = Newspack::plugin_url() . '/includes/raw_assets/ga4.json';

?>
<amp-analytics type="googleanalytics" config="<?php echo esc_attr( $config_path ); ?>" data-credentials="include">
<script type="application/json">
{
"vars": {
"GA4_MEASUREMENT_ID": "<?php echo esc_attr( $ga4_measurement_id ); ?>",
"DEFAULT_PAGEVIEW_ENABLED": true,
"GOOGLE_CONSENT_ENABLED": false
}
}
</script>
</amp-analytics>
<?php
}

/**
* Get whether the current user is connected.
*
* @return bool Whether the user is connected to Google through Site Kit.
*/
private static function is_user_connected() {
global $wpdb;

$user_id = get_current_user_id();
if ( ! $user_id ) {
return false;
}

return ! empty( get_user_meta( $user_id, $wpdb->prefix . 'googlesitekit_site_verified_meta', true ) );
}

/**
* Get the name of the option under which Site Kit's GA4 settings are stored.
*/
private static function get_sitekit_ga4_settings_option_name() {
if ( class_exists( '\Google\Site_Kit\Modules\Analytics_4\Settings' ) ) {
return \Google\Site_Kit\Modules\Analytics_4\Settings::OPTION;
}
return false;
}

/**
* Get Site Kit's GA4 settings.
*/
private static function get_sitekit_ga4_settings() {
$option_name = self::get_sitekit_ga4_settings_option_name();
if ( false === $option_name ) {
return false;
}
return get_option( $option_name, false );
}

/**
* Fetch data for the GA account data and set up GA4.
*/
public static function setup_sitekit_ga4() {
if ( ! class_exists( 'Google\Site_Kit\Core\Modules\Module' ) ) {
return;
}
require_once NEWSPACK_ABSPATH . 'includes/plugins/google-site-kit/class-googlesitekitanalytics.php';

if ( ! self::is_user_connected() ) {
return;
}
if ( get_option( self::GA4_SETUP_DONE_OPTION_NAME, false ) ) {
return;
}

$sitekit_ga4_settings = self::get_sitekit_ga4_settings();
if ( false !== $sitekit_ga4_settings && $sitekit_ga4_settings['useSnippet'] && isset( $sitekit_ga4_settings['measurementID'] ) ) {
return;
}

if ( ! defined( 'GOOGLESITEKIT_PLUGIN_MAIN_FILE' ) ) {
return;
}

$sitekit_ga_settings = get_option( \Google\Site_Kit\Modules\Analytics\Settings::OPTION, false );
if ( false === $sitekit_ga_settings || ! isset( $sitekit_ga_settings['accountID'] ) ) {
return;
}
$account_id = $sitekit_ga_settings['accountID'];

try {
$newspack_ga = new GoogleSiteKitAnalytics( new Context( GOOGLESITEKIT_PLUGIN_MAIN_FILE ) );
$ga4_settings = $newspack_ga->get_ga4_settings( $account_id );
if ( false === $ga4_settings ) {
return;
}
$ga4_settings['ownerID'] = get_current_user_id();
$ga4_settings['useSnippet'] = true;

$sitekit_ga4_option_name = self::get_sitekit_ga4_settings_option_name();
Logger::log( 'Updating Site Kit GA4 settings option.' );
update_option( self::GA4_SETUP_DONE_OPTION_NAME, true, true );
update_option( $sitekit_ga4_option_name, $ga4_settings, true );
} catch ( \Throwable $e ) {
Logger::log( 'Failed updating Site Kit GA4 settings option: ' . $e->getMessage() );
}
}
}
GoogleSiteKit::init();
84 changes: 84 additions & 0 deletions includes/plugins/google-site-kit/class-googlesitekitanalytics.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
<?php
/**
* Google Site Kit integration class.
*
* @package Newspack
*/

namespace Newspack;

use Google\Site_Kit\Context;
use Google\Site_Kit\Modules\Analytics_4;
use Google\Site_Kit\Modules\Analytics_4\Settings;
use Google\Site_Kit\Core\Modules\Module;
use Google\Site_Kit\Core\Authentication\Clients\Google_Site_Kit_Client;
use Google\Site_Kit_Dependencies\Google\Service\GoogleAnalyticsAdmin as Google_Service_GoogleAnalyticsAdmin;

defined( 'ABSPATH' ) || exit;

/**
* Class extending Site Kit's Module, in order to easily access GA data via
* Site Kit's Analytics Admin service.
*/
class GoogleSiteKitAnalytics extends Module {
public function register() { // phpcs:ignore Squiz.Commenting.FunctionComment.Missing
return true;
}
public function setup_info() { // phpcs:ignore Squiz.Commenting.FunctionComment.Missing
return true;
}

/**
* Set up the Analytics Admin service, so the module can use it.
*
* @param Google_Site_Kit_Client $client Google client instance.
*/
protected function setup_services( Google_Site_Kit_Client $client ) {
return array(
'analyticsadmin' => new Google_Service_GoogleAnalyticsAdmin( $client ),
);
}

/**
* Return data needed to set up Site Kit's GA4 settings.
*
* @param string $account_id Account ID.
*/
public function get_ga4_settings( $account_id ) {
$analyticsadmin = $this->get_service( 'analyticsadmin' );
$properties_response = $analyticsadmin->properties->listProperties(
array(
'filter' => 'parent:accounts/' . $account_id,
)
);
// Only proceed if there is exactly one GA4 property - otherwise we don't
// know which to pick.
if ( 1 !== count( $properties_response['properties'] ) ) {
return false;
}
$property = $properties_response['properties'][0];
$datastreams_response = $analyticsadmin
->properties_dataStreams // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
->listPropertiesDataStreams(
$property['name']
);
// Only proceed if there is one GA4 data stream - otherwise we don't
// know which to pick.
if ( 1 !== count( $datastreams_response['dataStreams'] ) ) {
return false;
}
$datastream = $datastreams_response['dataStreams'][0];
preg_match( '/\d+$/', $property['name'], $property_id_matches );
$property_id = $property_id_matches[0];
preg_match( '/\d+$/', $datastream['name'], $webstreamdata_id_matches );
$webstreamdata_id = $webstreamdata_id_matches[0];
if ( ! $property_id || ! $webstreamdata_id ) {
return false;
}
return [
'propertyID' => $property_id,
'webDataStreamID' => $webstreamdata_id,
'measurementID' => $datastream['webStreamData']['measurementId'],
];
}
}

0 comments on commit 266135f

Please sign in to comment.