Skip to content

Commit

Permalink
Add Audience Reset class to reset Audience settings across all users …
Browse files Browse the repository at this point in the history
…on Analytics property change.
  • Loading branch information
benbowler committed Sep 11, 2024
1 parent 36b8bcd commit a31e733
Show file tree
Hide file tree
Showing 4 changed files with 500 additions and 1 deletion.
11 changes: 11 additions & 0 deletions includes/Core/User/Audience_Settings.php
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,17 @@ function ( $value ) {
return $this->set( array_merge( $settings, $updated ) );
}

/**
* Reset the setting to their default values.
*
* @since n.e.x.t
*
* @return bool True on success, false on failure.
*/
public function reset() {
return $this->set( $this->get_default() );
}

/**
* Gets the callback for sanitizing the setting's value before saving.
*
Expand Down
4 changes: 3 additions & 1 deletion includes/Modules/Analytics_4.php
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@
use Google\Site_Kit\Modules\Analytics_4\Conversion_Reporting\Conversion_Reporting_Cron;
use Google\Site_Kit\Modules\Analytics_4\Conversion_Reporting\Conversion_Reporting_Events_Sync;
use Google\Site_Kit\Modules\Analytics_4\Conversion_Reporting\Conversion_Reporting_Provider;
use Google\Site_Kit\Modules\Analytics_4\Reset_Audiences;
use stdClass;
use WP_Error;

Expand Down Expand Up @@ -232,6 +233,8 @@ public function register() {

( new Advanced_Tracking( $this->context ) )->register();

( new Reset_Audiences( $this->user_options, $this ) )->register();

add_action( 'admin_init', array( $synchronize_property, 'maybe_schedule_synchronize_property' ) );
add_action( 'admin_init', array( $synchronize_adsense_linked, 'maybe_schedule_synchronize_adsense_linked' ) );
add_action( 'admin_init', array( $synchronize_ads_linked, 'maybe_schedule_synchronize_ads_linked' ) );
Expand Down Expand Up @@ -298,7 +301,6 @@ function ( $audience ) {
'adsLinked' => false,
'adsLinkedLastSyncedAt' => 0,
'detectedEvents' => array(),
'availableAudiencesLastSyncedAt' => 0,
)
);

Expand Down
175 changes: 175 additions & 0 deletions includes/Modules/Analytics_4/Reset_Audiences.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
<?php
/**
* Class Google\Site_Kit\Modules\Analytics_4\Reset_Audiences
*
* @package Google\Site_Kit\Modules\Analytics_4
* @copyright 2024 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_4;

use Google\Site_Kit\Core\Dismissals\Dismissed_Items;
use Google\Site_Kit\Core\Prompts\Dismissed_Prompts;
use Google\Site_Kit\Core\Storage\User_Options;
use Google\Site_Kit\Core\User\Audience_Settings;
use Google\Site_Kit\Modules\Analytics_4;

/**
* Class to reset Audience Segmentation Settings across multiple users.
*
* @since n.e.x.t
* @access private
* @ignore
*/
class Reset_Audiences {

/**
* User_Options instance.
*
* @since n.e.x.t
* @var User_Options
*/
protected $user_options;

/**
* Dismissed_Prompts instance.
*
* @since n.e.x.t
* @var Dismissed_Prompts
*/
protected $dismissed_prompts;

/**
* Dismissed_Items instance.
*
* @since n.e.x.t
* @var Dismissed_Items
*/
protected $dismissed_items;

/**
* Analytics_4 instance.
*
* @since n.e.x.t
* @var Analytics_4
*/
protected $analytics;

/**
* Audience Settings instance.
*
* @since n.e.x.t
* @var Audience_Settings
*/
protected $audience_settings;

const AUDIENCE_SEGMENTATION_DISMISSED_PROMPTS = array( 'audience_segmentation_setup_cta-notification' );

const AUDIENCE_SEGMENTATION_DISMISSED_ITEMS = array(
'audience-segmentation-add-group-notice',
'audience_segmentation_setup_success_notification',
'settings_visitor_groups_setup_success_notification',
'audience-segmentation-no-audiences-banner',
'audience-tile-*',
);

/**
* Constructor.
*
* @since n.e.x.t
*
* @param User_Options $user_options User option API.
* @param Analytics_4 $analytics Analytics_4 instance.
*/
public function __construct( User_Options $user_options = null, Analytics_4 $analytics ) {
$this->user_options = $user_options;
$this->dismissed_prompts = new Dismissed_Prompts( $this->user_options );
$this->dismissed_items = new Dismissed_Items( $this->user_options );
$this->audience_settings = new Audience_Settings( $this->user_options );
$this->analytics = $analytics;
}

/**
* Register on change actions.
*
* @since n.e.x.t
*/
public function register() {
$this->analytics->get_settings()->on_change(
function ( $old_value, $new_value ) {
// Reset Audience specific settings, only when the Analytics propertyID changes.
if ( $old_value['propertyID'] !== $new_value['propertyID'] ) {
$this->reset_audience_data();
}
}
);
}

/**
* Reset Audience specific settings for all SK users when propertyID changes.
*
* @since n.e.x.t
*/
public function reset_audience_data() {
global $wpdb;

// phpcs:ignore WordPress.DB.DirectDatabaseQuery
$users = $wpdb->get_col(
$wpdb->prepare(
"SELECT DISTINCT user_id
FROM $wpdb->usermeta
WHERE meta_key IN (%s, %s)
LIMIT 100 -- Arbitrary limit to avoid unbounded user iteration.",
$this->user_options->get_meta_key( Dismissed_Items::OPTION ),
$this->user_options->get_meta_key( Dismissed_Prompts::OPTION ),
)
);

if ( $users ) {
$backup_user_id = $this->user_options->get_user_id();

foreach ( $users as $user_id ) {
$this->user_options->switch_user( $user_id );

// Remove Audience Segmentation specific dismissed prompts.
foreach ( self::AUDIENCE_SEGMENTATION_DISMISSED_PROMPTS as $prompt ) {
$this->dismissed_prompts->remove( $prompt );
}

// Remove Audience Segmentation specific dismissed items.
foreach ( self::AUDIENCE_SEGMENTATION_DISMISSED_ITEMS as $item ) {
// Support wildcard matches, in order to delete all dismissed items prefixed with audience-tile-*.
if ( strpos( $item, '*' ) !== false ) {
$dismissed_items = $this->dismissed_items->get();

foreach ( array_keys( $dismissed_items ) as $existing_item ) {
if ( str_starts_with( $existing_item, rtrim( $item, '*' ) ) ) {
$this->dismissed_items->remove( $existing_item );
}
}
} else {
// For non-wildcard items, remove them directly.
$this->dismissed_items->remove( $item );
}
}

// Reset the users Audience Settings, such as configured audiences.
$this->audience_settings->reset();
}

// Restore original user.
$this->user_options->switch_user( $backup_user_id );
}

// Reset the main Analytics Module, Audience Segmentation settings.
$this->analytics->get_settings()->merge(
array(
'availableAudiences' => null,
'availableAudiencesLastSyncedAt' => 0,
'audienceSegmentationSetupComplete' => false,
)
);
}
}
Loading

0 comments on commit a31e733

Please sign in to comment.