Skip to content

Commit

Permalink
Merge pull request #8431 from google/enhancement/#8382-cmo-ads-linked
Browse files Browse the repository at this point in the history
Consider Analytics Ads linked status in Consent Mode conditions
  • Loading branch information
tofumatt committed Apr 1, 2024
2 parents cee0741 + 6ae739b commit 266daf0
Show file tree
Hide file tree
Showing 12 changed files with 554 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ import { Button, SpinnerButton } from 'googlesitekit-components';
import { CORE_LOCATION } from '../../googlesitekit/datastore/location/constants';
import { CORE_SITE } from '../../googlesitekit/datastore/site/constants';
import { CORE_USER } from '../../googlesitekit/datastore/user/constants';
import { MODULES_ANALYTICS_4 } from '../../modules/analytics-4/datastore/constants';
import { withWidgetComponentProps } from '../../googlesitekit/widgets/util';
import { Cell, Grid, Row } from '../../material-components';
import BannerGraphicsSVG from '../../../svg/graphics/consent-mode-setup.svg';
Expand Down Expand Up @@ -70,8 +69,7 @@ function ConsentModeSetupCTAWidget( { Widget, WidgetNull } ) {
);

const isAdsConnected = useSelect( ( select ) =>
// TODO: Replace this with the `ads` version of the `getAdsConversionID()` selector once it's implemented.
select( MODULES_ANALYTICS_4 ).getAdsConversionID()
select( CORE_SITE ).isAdsConnected()
);

const settingsURL = useSelect( ( select ) =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import fetchMock from 'fetch-mock';
/**
* Internal dependencies
*/
import { provideModules } from '../../../../tests/js/utils';
import WithRegistrySetup from '../../../../tests/js/WithRegistrySetup';
import { CORE_SITE } from '../../googlesitekit/datastore/site/constants';
import { CORE_USER } from '../../googlesitekit/datastore/user/constants';
Expand All @@ -48,9 +49,18 @@ export default {
decorators: [
( Story ) => {
const setupRegistry = ( registry ) => {
registry
.dispatch( MODULES_ANALYTICS_4 )
.receiveGetSettings( { adsConversionID: 'AW-123456789' } );
provideModules( registry, [
{
slug: 'analytics-4',
active: true,
connected: true,
},
] );

registry.dispatch( MODULES_ANALYTICS_4 ).receiveGetSettings( {
adsConversionID: 'AW-123456789',
adsLinked: false,
} );

registry
.dispatch( CORE_SITE )
Expand Down
4 changes: 1 addition & 3 deletions assets/js/components/settings/SettingsCardConsentMode.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ import { __ } from '@wordpress/i18n';
import Data from 'googlesitekit-data';
import { CORE_SITE } from '../../googlesitekit/datastore/site/constants';
import { CORE_USER } from '../../googlesitekit/datastore/user/constants';
import { MODULES_ANALYTICS_4 } from '../../modules/analytics-4/datastore/constants';
import { Grid, Cell, Row } from '../../material-components';
import Badge from '../../components/Badge';
import ConsentModeSwitch from '../consent-mode/ConsentModeSwitch';
Expand All @@ -48,8 +47,7 @@ export default function SettingsCardConsentMode() {
const viewContext = useViewContext();

const isAdsConnected = useSelect( ( select ) =>
// TODO: Replace this with the `ads` version of the `getAdsConversionID()` selector once it's implemented.
select( MODULES_ANALYTICS_4 ).getAdsConversionID()
select( CORE_SITE ).isAdsConnected()
);

const isConsentModeEnabled = useSelect( ( select ) =>
Expand Down
33 changes: 33 additions & 0 deletions assets/js/googlesitekit/datastore/site/consent-mode.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ import API from 'googlesitekit-api';
import Data from 'googlesitekit-data';
import { createFetchStore } from '../../data/create-fetch-store';
import { createReducer } from '../../data/create-reducer';
import { CORE_MODULES } from '../../modules/datastore/constants';
import { CORE_SITE } from './constants';
import { MODULES_ANALYTICS_4 } from '../../../modules/analytics-4/datastore/constants';
import invariant from 'invariant';
import { isPlainObject } from 'lodash';

Expand Down Expand Up @@ -164,6 +166,37 @@ const baseSelectors = {
getConsentAPIInfo: ( state ) => {
return state.consentMode.apiInfo;
},

/**
* Returns true if Google Ads is in use, either through a linked Analytics & Ads account
* or an Ads conversion tracking ID.
*
* TODO: The Ads conversion tracking ID is being moved to the new "Ads" module. Source
* this ID from the "Ads" module once it's implemented.
*
* @since n.e.x.t
*
* @return {boolean|undefined} True if Google Ads is in use, false otherwise. Undefined if the selectors have not loaded.
*/
isAdsConnected: createRegistrySelector( ( select ) => () => {
const { isModuleConnected } = select( CORE_MODULES );

if ( ! isModuleConnected( 'analytics-4' ) ) {
return false;
}

const { getAdsConversionID, getAdsLinked } =
select( MODULES_ANALYTICS_4 );

const adsConversionID = getAdsConversionID();
const adsLinked = getAdsLinked();

if ( [ adsConversionID, adsLinked ].includes( undefined ) ) {
return undefined;
}

return !! adsConversionID || !! adsLinked;
} ),
};

const baseResolvers = {
Expand Down
93 changes: 93 additions & 0 deletions assets/js/googlesitekit/datastore/site/consent-mode.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,13 @@
import API from 'googlesitekit-api';
import {
createTestRegistry,
provideModules,
unsubscribeFromAll,
untilResolved,
waitForDefaultTimeouts,
} from '../../../../../tests/js/utils';
import { CORE_SITE } from './constants';
import { MODULES_ANALYTICS_4 } from '../../../modules/analytics-4/datastore/constants';

describe( 'core/site Consent Mode', () => {
let registry;
Expand Down Expand Up @@ -298,5 +300,96 @@ describe( 'core/site Consent Mode', () => {
expect( console ).toHaveErrored();
} );
} );

describe( 'isAdsConnected', () => {
it( 'returns false if the Analytics module is not connected', () => {
provideModules( registry, [
{
slug: 'analytics-4',
active: false,
connected: false,
},
] );

expect( registry.select( CORE_SITE ).isAdsConnected() ).toBe(
false
);
} );

it( 'returns undefined if either the Ads conversion ID in Analytics or the Analytics and Ads linked status is undefined', () => {
provideModules( registry, [
{
slug: 'analytics-4',
active: true,
connected: true,
},
] );

registry
.dispatch( MODULES_ANALYTICS_4 )
.receiveGetSettings( {} );

expect( registry.select( CORE_SITE ).isAdsConnected() ).toBe(
undefined
);
} );

it( 'returns true if an Ads conversion ID is set in the Analytics module', () => {
provideModules( registry, [
{
slug: 'analytics-4',
active: true,
connected: true,
},
] );

registry.dispatch( MODULES_ANALYTICS_4 ).receiveGetSettings( {
adsConversionID: 'AW-12345',
adsLinked: false, // Set to default, as otherwise if it is set to undefined, the selector will return undefined.
} );

expect( registry.select( CORE_SITE ).isAdsConnected() ).toBe(
true
);
} );

it( 'returns true if Analytics and Ads are linked', () => {
provideModules( registry, [
{
slug: 'analytics-4',
active: true,
connected: true,
},
] );

registry.dispatch( MODULES_ANALYTICS_4 ).receiveGetSettings( {
adsLinked: true,
adsConversionID: '', // Set to default, as otherwise if it is set to undefined, the selector will return undefined.
} );

expect( registry.select( CORE_SITE ).isAdsConnected() ).toBe(
true
);
} );

it( 'returns false if neither an Ads conversion ID is set in Analytics, nor Analytics and Ads are linked', () => {
provideModules( registry, [
{
slug: 'analytics-4',
active: true,
connected: true,
},
] );

registry.dispatch( MODULES_ANALYTICS_4 ).receiveGetSettings( {
adsConversionID: '',
adsLinked: false,
} );

expect( registry.select( CORE_SITE ).isAdsConnected() ).toBe(
false
);
} );
} );
} );
} );
2 changes: 2 additions & 0 deletions assets/js/modules/analytics-4/datastore/base.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ const baseModuleStore = Modules.createModuleStore( 'analytics-4', {
'propertyCreateTime',
'trackingDisabled',
'adsConversionIDMigratedAtMs',
'adsLinked',
'adsLinkedLastSyncedAt',
],
submitChanges,
rollbackChanges,
Expand Down
41 changes: 36 additions & 5 deletions includes/Modules/Analytics_4.php
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@
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;
use Google\Site_Kit\Modules\Analytics_4\Settings;
use Google\Site_Kit\Modules\Analytics_4\Synchronize_AdsLinked;
use Google\Site_Kit\Modules\Analytics_4\Tag_Guard;
use Google\Site_Kit\Modules\Analytics_4\Tag_Interface;
use Google\Site_Kit\Modules\Analytics_4\Web_Tag;
Expand Down Expand Up @@ -190,10 +191,17 @@ public function register() {
);
$synchronize_adsense_linked->register();

$synchronize_ads_linked = new Synchronize_AdsLinked(
$this,
$this->user_options
);
$synchronize_ads_linked->register();

( new Advanced_Tracking( $this->context ) )->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' ) );
add_action( 'admin_init', $this->get_method_proxy( 'handle_provisioning_callback' ) );

// For non-AMP and AMP.
Expand All @@ -212,12 +220,14 @@ function( $old_value, $new_value ) {
$this->custom_dimensions_data_available->reset_data_available();
}

// Reset AdSense link settings when propertyID changes.
// Reset AdSense & Ads link settings when propertyID changes.
if ( $old_value['propertyID'] !== $new_value['propertyID'] ) {
$this->get_settings()->merge(
array(
'adSenseLinked' => false,
'adSenseLinkedLastSyncedAt' => 0,
'adsLinked' => false,
'adsLinkedLastSyncedAt' => 0,
)
);
}
Expand Down Expand Up @@ -423,17 +433,27 @@ public function get_debug_fields() {
? 'none'
: join( ', ', $settings['availableCustomDimensions'] ),
),
'analytics_4_ads_linked' => array(
'label' => __( 'Analytics Ads Linked', 'google-site-kit' ),
'value' => $settings['adsLinked'] ? __( 'Connected', 'google-site-kit' ) : __( 'Not connected', 'google-site-kit' ),
'debug' => $settings['adsLinked'],
),
'analytics_4_ads_linked_last_synced_at' => array(
'label' => __( 'Analytics Ads Linked Last Synced At', 'google-site-kit' ),
'value' => $settings['adsLinkedLastSyncedAt'] ? gmdate( 'Y-m-d H:i:s', $settings['adsLinkedLastSyncedAt'] ) : __( 'Never synced', 'google-site-kit' ),
'debug' => $settings['adsLinkedLastSyncedAt'],
),
);

if ( $this->is_adsense_connected() ) {
$debug_fields['adsense_linked'] = array(
'label' => __( 'AdSense Linked', 'google-site-kit' ),
$debug_fields['analytics_4_adsense_linked'] = array(
'label' => __( 'Analytics AdSense Linked', 'google-site-kit' ),
'value' => $settings['adSenseLinked'] ? __( 'Connected', 'google-site-kit' ) : __( 'Not connected', 'google-site-kit' ),
'debug' => Debug_Data::redact_debug_value( $settings['adSenseLinked'] ),
);

$debug_fields['adsense_linked_last_synced_at'] = array(
'label' => __( 'AdSense Linked Last Synced At', 'google-site-kit' ),
$debug_fields['analytics_4_adsense_linked_last_synced_at'] = array(
'label' => __( 'Analytics AdSense Linked Last Synced At', 'google-site-kit' ),
'value' => $settings['adSenseLinkedLastSyncedAt'] ? gmdate( 'Y-m-d H:i:s', $settings['adSenseLinkedLastSyncedAt'] ) : __( 'Never synced', 'google-site-kit' ),
'debug' => Debug_Data::redact_debug_value( $settings['adSenseLinkedLastSyncedAt'] ),
);
Expand All @@ -453,6 +473,7 @@ protected function get_datapoint_definitions() {
$datapoints = array(
'GET:account-summaries' => array( 'service' => 'analyticsadmin' ),
'GET:accounts' => array( 'service' => 'analyticsadmin' ),
'GET:ads-links' => array( 'service' => 'analyticsadmin' ),
'GET:adsense-links' => array( 'service' => 'analyticsadsenselinks' ),
'GET:container-lookup' => array(
'service' => 'tagmanager',
Expand Down Expand Up @@ -892,6 +913,14 @@ protected function create_data_request( Data_Request $data ) {
return $this->get_service( 'analyticsadmin' )->accounts->listAccounts();
case 'GET:account-summaries':
return $this->get_service( 'analyticsadmin' )->accountSummaries->listAccountSummaries( array( 'pageSize' => 200 ) );
case 'GET:ads-links':
if ( empty( $data['propertyID'] ) ) {
throw new Missing_Required_Param_Exception( 'propertyID' );
}

$parent = self::normalize_property_id( $data['propertyID'] );

return $this->get_service( 'analyticsadmin' )->properties_googleAdsLinks->listPropertiesGoogleAdsLinks( $parent );
case 'GET:adsense-links':
if ( empty( $data['propertyID'] ) ) {
throw new Missing_Required_Param_Exception( 'propertyID' );
Expand Down Expand Up @@ -1466,6 +1495,8 @@ function( $property ) {
$account_summaries,
'displayName'
);
case 'GET:ads-links':
return (array) $response->getGoogleAdsLinks();
case 'GET:adsense-links':
return (array) $response->getAdsenseLinks();
case 'POST:create-account-ticket':
Expand Down
12 changes: 12 additions & 0 deletions includes/Modules/Analytics_4/Settings.php
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,8 @@ protected function get_default() {
'adSenseLinked' => false,
'adSenseLinkedLastSyncedAt' => 0,
'adsConversionIDMigratedAtMs' => 0,
'adsLinked' => false,
'adsLinkedLastSyncedAt' => 0,
);
}

Expand Down Expand Up @@ -166,6 +168,16 @@ function( $dimension ) {
$option['adsConversionIDMigratedAtMs'] = 0;
}
}

if ( isset( $option['adsLinked'] ) ) {
$option['adsLinked'] = (bool) $option['adsLinked'];
}

if ( isset( $option['adsLinkedLastSyncedAt'] ) ) {
if ( ! is_int( $option['adsLinkedLastSyncedAt'] ) ) {
$option['adsLinkedLastSyncedAt'] = 0;
}
}
}

return $option;
Expand Down

0 comments on commit 266daf0

Please sign in to comment.