Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Infrastructure/#7458 - Create API endpoints and Redux store infrastructure for "Enable enhanced measurement" feature #7561

Merged
merged 60 commits into from
Sep 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
60 commits
Select commit Hold shift + click to select a range
f3266ca
Add support for enhanced measurement settings endpoints.
techanvil Aug 16, 2023
9891a86
Add "Enable enhanced measurement" switch that takes its value from th…
techanvil Aug 17, 2023
f5c8796
Refactor & enable the switch.
techanvil Aug 17, 2023
b084b7c
Add edit scope for POST endpoint.
techanvil Aug 18, 2023
581ebf7
Update EnhancedMeasurementToggle copy.
techanvil Aug 18, 2023
35369e3
Fix typo.
techanvil Aug 22, 2023
74fa59b
Merge branch 'develop' into infrastructure/#7458-enhanced-measurement.
hussain-t Sep 6, 2023
3ab782f
Rename file
hussain-t Sep 6, 2023
96f7c69
Add line break between methods
hussain-t Sep 6, 2023
90faac5
Update renamed class instance
hussain-t Sep 6, 2023
b1a3463
Update class name
hussain-t Sep 6, 2023
e22f9e0
Rename PropertiesEnhancedMeasurementService class
hussain-t Sep 6, 2023
e09e97e
Add enhancedMeasurementSettings fields validation.
hussain-t Sep 6, 2023
55d5640
Rename datastore file.
hussain-t Sep 6, 2023
347b0b7
Rename enhancedMeasurements state to enhancedMeasurement.
hussain-t Sep 6, 2023
28ec938
Add object shape validation.
hussain-t Sep 6, 2023
c53d26f
Fix import after renaming.
hussain-t Sep 6, 2023
887c263
Add actions.
hussain-t Sep 7, 2023
aa7fce0
Add selectors.
hussain-t Sep 7, 2023
20f6ff9
Add tests for EM selectors.
hussain-t Sep 8, 2023
6b56e4b
Merge branch 'develop' into infrastructure/#7458-enhanced-measurement.
hussain-t Sep 8, 2023
e02f74c
Add validations for the action params.
hussain-t Sep 10, 2023
fb0797f
Add tests for setEnhancedMeasurementSettings action.
hussain-t Sep 10, 2023
e418fab
Fix destructure params from validateParams.
hussain-t Sep 10, 2023
5cd4a66
Fix post method path.
hussain-t Sep 10, 2023
86a7b78
Add setEnhancedMeasurementsStreamEnabled tests.
hussain-t Sep 10, 2023
a2421e0
Add updateEnhancedMeasurementSettings tests.
hussain-t Sep 10, 2023
1edc666
Rename variable.
hussain-t Sep 11, 2023
d29db92
Add resetEnhancedMeasurementSettings tests.
hussain-t Sep 11, 2023
febcf12
Add enhanced-measurement-settings endpoint in test_get_datapoints.
hussain-t Sep 11, 2023
d221d1b
FDix lint error
hussain-t Sep 11, 2023
a9f3de8
Fix PHP lint errors
hussain-t Sep 11, 2023
cc9cc5d
Revert to developt changes in the setup form.
hussain-t Sep 11, 2023
491b7e9
Remove EnhancedMeasurementToggle file.
hussain-t Sep 11, 2023
579fa56
Add JSDoc comment for setEnhancedMeasurementStreamEnabled.
hussain-t Sep 11, 2023
22ace94
Add break instead of return statements.
hussain-t Sep 11, 2023
ece6fab
Avoid mutating the state in the selector.
hussain-t Sep 11, 2023
9e75cab
Merge branch 'develop' into infrastructure/#7458-enhanced-measurement.
hussain-t Sep 12, 2023
70d5302
Add get enhanced-measurement-settings PHP tests.
hussain-t Sep 12, 2023
a9d6dc1
Add fields.
hussain-t Sep 12, 2023
4d09b4c
Add validation fields.
hussain-t Sep 12, 2023
8363449
Add enhanced_mesurement_settings post tests.
hussain-t Sep 12, 2023
a36e970
Fix PHP lint errors
hussain-t Sep 12, 2023
5d719f4
Add EnhancedMeasurementSettingsModel class.
hussain-t Sep 12, 2023
7e37aaf
Use EnhancedMeasurementSettingsModel class.
hussain-t Sep 12, 2023
162bdaf
Remove old API properties
hussain-t Sep 12, 2023
13b9cf5
php ignore file the api client class
hussain-t Sep 13, 2023
623d00b
Merge branch 'develop' into infrastructure/#7458-enhanced-measurement.
hussain-t Sep 13, 2023
29688ce
Fix php lint errors.
hussain-t Sep 13, 2023
0d519e8
Use EnhancedMeasurementSettingsModel class.
hussain-t Sep 13, 2023
64d9574
Merge branch 'develop' into infrastructure/#7458-enhanced-measurement.
hussain-t Sep 13, 2023
0884d53
Shallow clone the state.
hussain-t Sep 13, 2023
6c3d7fb
Extract logic to a utility function.
hussain-t Sep 13, 2023
8b9b60a
Update error message assertions in the tests.
hussain-t Sep 13, 2023
7e65d52
Move enhancedMeasurementSettingsMock to beforeEach.
hussain-t Sep 13, 2023
1de7e90
Pass the mock copy instead of the original object.
hussain-t Sep 13, 2023
67c6958
Fix var name.
hussain-t Sep 13, 2023
c79affd
Fix typo and grammatical errors.
hussain-t Sep 13, 2023
9708121
Add create_enhanced_measurement_fake_http_handler method.
hussain-t Sep 13, 2023
11b20fe
Update PHP tests to mock em data field.
hussain-t Sep 13, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
452 changes: 452 additions & 0 deletions assets/js/modules/analytics-4/datastore/enhanced-measurement.js

Large diffs are not rendered by default.

494 changes: 494 additions & 0 deletions assets/js/modules/analytics-4/datastore/enhanced-measurement.test.js

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions assets/js/modules/analytics-4/datastore/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import accounts from './accounts';
import baseModuleStore from './base';
import containers from './containers';
import conversionEvents from './conversion-events';
import enhancedMeasurement from './enhanced-measurement';
import properties from './properties';
import report from './report';
import service from './service';
Expand All @@ -38,6 +39,7 @@ const store = Data.combineStores(
containers,
conversionEvents,
createSnapshotStore( MODULES_ANALYTICS_4 ),
enhancedMeasurement,
properties,
report,
service,
Expand Down
6 changes: 3 additions & 3 deletions assets/js/modules/analytics-4/datastore/webdatastreams.js
Original file line number Diff line number Diff line change
Expand Up @@ -444,8 +444,7 @@ const baseSelectors = {
? measurements
: [ measurements ];

const summaries =
select( MODULES_ANALYTICS_4 ).getAccountSummaries();
let summaries = select( MODULES_ANALYTICS_4 ).getAccountSummaries();
if ( ! Array.isArray( summaries ) ) {
return undefined;
}
Expand All @@ -454,7 +453,8 @@ const baseSelectors = {
// so we can check it first because its more likely that the current
// account will contain a measurement ID that we are looking for.
const currentAccountID = select( MODULES_ANALYTICS ).getAccountID();
summaries.sort( ( { _id: accountID } ) =>
// Clone summaries to avoid mutating the original array.
summaries = [ ...summaries ].sort( ( { _id: accountID } ) =>
accountID === currentAccountID ? -1 : 0
);

Expand Down
154 changes: 137 additions & 17 deletions includes/Modules/Analytics_4.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
use Google\Site_Kit\Modules\Analytics\Settings as Analytics_Settings;
use Google\Site_Kit\Modules\Analytics_4\AMP_Tag;
use Google\Site_Kit\Modules\Analytics_4\GoogleAnalyticsAdmin\AccountProvisioningService;
use Google\Site_Kit\Modules\Analytics_4\GoogleAnalyticsAdmin\PropertiesEnhancedMeasurementService;
use Google\Site_Kit\Modules\Analytics_4\GoogleAnalyticsAdmin\Proxy_GoogleAnalyticsAdminProvisionAccountTicketRequest;
use Google\Site_Kit\Modules\Analytics_4\Report\Request as Analytics_4_Report_Request;
use Google\Site_Kit\Modules\Analytics_4\Report\Response as Analytics_4_Report_Response;
Expand All @@ -56,6 +57,7 @@
use Google\Site_Kit_Dependencies\Google\Model as Google_Model;
use Google\Site_Kit_Dependencies\Google\Service\AnalyticsData as Google_Service_AnalyticsData;
use Google\Site_Kit_Dependencies\Google\Service\GoogleAnalyticsAdmin as Google_Service_GoogleAnalyticsAdmin;
use Google\Site_Kit\Modules\Analytics_4\GoogleAnalyticsAdmin\EnhancedMeasurementSettingsModel;
use Google\Site_Kit_Dependencies\Google\Service\GoogleAnalyticsAdmin\GoogleAnalyticsAdminV1betaAccount;
use Google\Site_Kit_Dependencies\Google\Service\GoogleAnalyticsAdmin\GoogleAnalyticsAdminV1betaDataStream;
use Google\Site_Kit_Dependencies\Google\Service\GoogleAnalyticsAdmin\GoogleAnalyticsAdminV1betaDataStreamWebStreamData;
Expand Down Expand Up @@ -295,49 +297,55 @@ protected function get_datapoint_definitions() {
}

$datapoints = array(
'GET:account-summaries' => array( 'service' => 'analyticsadmin' ),
'GET:accounts' => array( 'service' => 'analyticsadmin' ),
'GET:container-lookup' => array(
'GET:account-summaries' => array( 'service' => 'analyticsadmin' ),
'GET:accounts' => array( 'service' => 'analyticsadmin' ),
'GET:container-lookup' => array(
'service' => 'tagmanager',
'scopes' => array(
'https://www.googleapis.com/auth/tagmanager.readonly',
),
),
'GET:container-destinations' => array(
'GET:container-destinations' => array(
'service' => 'tagmanager',
'scopes' => array(
'https://www.googleapis.com/auth/tagmanager.readonly',
),
),
'GET:conversion-events' => array(
'GET:conversion-events' => array(
'service' => 'analyticsadmin',
'shareable' => $shareable,
),
'POST:create-account-ticket' => array(
'POST:create-account-ticket' => array(
'service' => 'analyticsprovisioning',
'scopes' => array( Analytics::EDIT_SCOPE ),
'request_scopes_message' => __( 'You’ll need to grant Site Kit permission to create a new Analytics account on your behalf.', 'google-site-kit' ),
),
'GET:google-tag-settings' => array(
'GET:google-tag-settings' => array(
'service' => 'tagmanager',
'scopes' => array(
'https://www.googleapis.com/auth/tagmanager.readonly',
),
),
'POST:create-property' => array(
'POST:create-property' => array(
'service' => 'analyticsadmin',
'scopes' => array( Analytics::EDIT_SCOPE ),
'request_scopes_message' => __( 'You’ll need to grant Site Kit permission to create a new Analytics 4 property on your behalf.', 'google-site-kit' ),
),
'POST:create-webdatastream' => array(
'POST:create-webdatastream' => array(
'service' => 'analyticsadmin',
'scopes' => array( Analytics::EDIT_SCOPE ),
'request_scopes_message' => __( 'You’ll need to grant Site Kit permission to create a new Analytics 4 web data stream for this site on your behalf.', 'google-site-kit' ),
),
'GET:properties' => array( 'service' => 'analyticsadmin' ),
'GET:property' => array( 'service' => 'analyticsadmin' ),
'GET:webdatastreams' => array( 'service' => 'analyticsadmin' ),
'GET:webdatastreams-batch' => array( 'service' => 'analyticsadmin' ),
'GET:properties' => array( 'service' => 'analyticsadmin' ),
'GET:property' => array( 'service' => 'analyticsadmin' ),
'GET:webdatastreams' => array( 'service' => 'analyticsadmin' ),
'GET:webdatastreams-batch' => array( 'service' => 'analyticsadmin' ),
'GET:enhanced-measurement-settings' => array( 'service' => 'analyticsenhancedmeasurement' ),
'POST:enhanced-measurement-settings' => array(
'service' => 'analyticsenhancedmeasurement',
'scopes' => array( Analytics::EDIT_SCOPE ),
'request_scopes_message' => __( 'You’ll need to grant Site Kit permission to update enhanced measurement settings for this Analytics 4 web data stream on your behalf.', 'google-site-kit' ),
),
);

if ( Feature_Flags::enabled( 'ga4Reporting' ) ) {
Expand Down Expand Up @@ -656,6 +664,106 @@ protected function create_data_request( Data_Request $data ) {
$request->setProperty( $property_id );

return $this->get_analyticsdata_service()->properties->runReport( $property_id, $request );
case 'GET:enhanced-measurement-settings':
if ( ! isset( $data['propertyID'] ) ) {
return new WP_Error(
'missing_required_param',
/* translators: %s: Missing parameter name */
sprintf( __( 'Request parameter is empty: %s.', 'google-site-kit' ), 'propertyID' ),
array( 'status' => 400 )
);
}

if ( ! isset( $data['webDataStreamID'] ) ) {
return new WP_Error(
'missing_required_param',
/* translators: %s: Missing parameter name */
sprintf( __( 'Request parameter is empty: %s.', 'google-site-kit' ), 'webDataStreamID' ),
array( 'status' => 400 )
);
}

$name = self::normalize_property_id(
$data['propertyID']
) . '/dataStreams/' . $data['webDataStreamID'] . '/enhancedMeasurementSettings';

$analyticsadmin = $this->get_analyticsenhancedmeasurements_service();

return $analyticsadmin
->properties_enhancedMeasurements // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
->getEnhancedMeasurementSettings( $name );
case 'POST:enhanced-measurement-settings':
if ( ! isset( $data['propertyID'] ) ) {
return new WP_Error(
'missing_required_param',
/* translators: %s: Missing parameter name */
sprintf( __( 'Request parameter is empty: %s.', 'google-site-kit' ), 'propertyID' ),
array( 'status' => 400 )
);
}

if ( ! isset( $data['webDataStreamID'] ) ) {
return new WP_Error(
'missing_required_param',
/* translators: %s: Missing parameter name */
sprintf( __( 'Request parameter is empty: %s.', 'google-site-kit' ), 'webDataStreamID' ),
array( 'status' => 400 )
);
}

if ( ! isset( $data['enhancedMeasurementSettings'] ) ) {
return new WP_Error(
'missing_required_param',
/* translators: %s: Missing parameter name */
sprintf( __( 'Request parameter is empty: %s.', 'google-site-kit' ), 'enhancedMeasurementSettings' ),
array( 'status' => 400 )
);
}

$enhanced_measurement_settings = $data['enhancedMeasurementSettings'];

$fields = array(
'name',
'streamEnabled',
'scrollsEnabled',
'outboundClicksEnabled',
'siteSearchEnabled',
'videoEngagementEnabled',
'fileDownloadsEnabled',
'pageChangesEnabled',
'formInteractionsEnabled',
'searchQueryParameter',
'uriQueryParameter',
);

$invalid_keys = array_diff( array_keys( $enhanced_measurement_settings ), $fields );

if ( ! empty( $invalid_keys ) ) {
return new WP_Error(
'invalid_property_name',
/* translators: %s: Invalid property names */
sprintf( __( 'Invalid properties in enhancedMeasurementSettings: %s.', 'google-site-kit' ), implode( ', ', $invalid_keys ) ),
array( 'status' => 400 )
);
}

$name = self::normalize_property_id(
$data['propertyID']
) . '/dataStreams/' . $data['webDataStreamID'] . '/enhancedMeasurementSettings';

$post_body = new EnhancedMeasurementSettingsModel( $data['enhancedMeasurementSettings'] );

$analyticsadmin = $this->get_analyticsenhancedmeasurements_service();

return $analyticsadmin
->properties_enhancedMeasurements // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
->updateEnhancedMeasurementSettings(
$name,
$post_body,
array(
'updateMask' => 'streamEnabled', // Only allow updating the streamEnabled field for now.
)
);
case 'GET:webdatastreams':
if ( ! isset( $data['propertyID'] ) ) {
return new WP_Error(
Expand Down Expand Up @@ -891,6 +999,17 @@ protected function get_analyticsdata_service() {
return $this->get_service( 'analyticsdata' );
}

/**
* Gets the configured Analytics Data service object instance.
*
* @since n.e.x.t
*
* @return PropertiesEnhancedMeasurementService The Analytics Admin API service.
*/
protected function get_analyticsenhancedmeasurements_service() {
return $this->get_service( 'analyticsenhancedmeasurement' );
}

/**
* Sets up the Google services the module should use.
*
Expand All @@ -907,10 +1026,11 @@ protected function setup_services( Google_Site_Kit_Client $client ) {
$google_proxy = $this->authentication->get_google_proxy();

return array(
'analyticsadmin' => new Google_Service_GoogleAnalyticsAdmin( $client ),
'analyticsdata' => new Google_Service_AnalyticsData( $client ),
'analyticsprovisioning' => new AccountProvisioningService( $client, $google_proxy->url() ),
'tagmanager' => new Google_Service_TagManager( $client ),
'analyticsadmin' => new Google_Service_GoogleAnalyticsAdmin( $client ),
'analyticsdata' => new Google_Service_AnalyticsData( $client ),
'analyticsprovisioning' => new AccountProvisioningService( $client, $google_proxy->url() ),
'analyticsenhancedmeasurement' => new PropertiesEnhancedMeasurementService( $client ),
'tagmanager' => new Google_Service_TagManager( $client ),
);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
<?php
// phpcs:ignoreFile

// Suppress coding standards checks for this file.
// Reason: This file is a copy of the `GoogleAnalyticsAdminV1alphaEnhancedMeasurementSettings` class
// from the Google API PHP Client library with a slight modification.

/**
* Class EnhancedMeasurementSettingsModel
*
* @package Google\Site_Kit\Modules\Analytics_4\GoogleAnalyticsAdmin
* @copyright 2023 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\GoogleAnalyticsAdmin;

/**
* The EnhancedMeasurementSettingsModel class.
*/
class EnhancedMeasurementSettingsModel extends \Google\Site_Kit_Dependencies\Google\Model {
public $fileDownloadsEnabled;
public $name;
public $outboundClicksEnabled;
public $pageChangesEnabled;
public $scrollsEnabled;
public $searchQueryParameter;
public $siteSearchEnabled;
public $streamEnabled;
public $uriQueryParameter;
public $videoEngagementEnabled;
public function setFileDownloadsEnabled( $fileDownloadsEnabled ) {
$this->fileDownloadsEnabled = $fileDownloadsEnabled;
}
public function getFileDownloadsEnabled() {
return $this->fileDownloadsEnabled;
}
public function setName( $name ) {
$this->name = $name;
}
public function getName() {
return $this->name;
}
public function setOutboundClicksEnabled( $outboundClicksEnabled ) {
$this->outboundClicksEnabled = $outboundClicksEnabled;
}
public function getOutboundClicksEnabled() {
return $this->outboundClicksEnabled;
}
public function setPageChangesEnabled( $pageChangesEnabled ) {
$this->pageChangesEnabled = $pageChangesEnabled;
}
public function getPageChangesEnabled() {
return $this->pageChangesEnabled;
}
public function setScrollsEnabled( $scrollsEnabled ) {
$this->scrollsEnabled = $scrollsEnabled;
}
public function getScrollsEnabled() {
return $this->scrollsEnabled;
}
public function setSearchQueryParameter( $searchQueryParameter ) {
$this->searchQueryParameter = $searchQueryParameter;
}
public function getSearchQueryParameter() {
return $this->searchQueryParameter;
}
public function setSiteSearchEnabled( $siteSearchEnabled ) {
$this->siteSearchEnabled = $siteSearchEnabled;
}
public function getSiteSearchEnabled() {
return $this->siteSearchEnabled;
}
public function setStreamEnabled( $streamEnabled ) {
$this->streamEnabled = $streamEnabled;
}
public function getStreamEnabled() {
return $this->streamEnabled;
}
public function setUriQueryParameter( $uriQueryParameter ) {
$this->uriQueryParameter = $uriQueryParameter;
}
public function getUriQueryParameter() {
return $this->uriQueryParameter;
}
public function setVideoEngagementEnabled( $videoEngagementEnabled ) {
$this->videoEngagementEnabled = $videoEngagementEnabled;
}
public function getVideoEngagementEnabled() {
return $this->videoEngagementEnabled;
}
}