google / google/site-kit-wp

Decouple Google Tag Gateway health status from GTG settings for improved architecture

Open
#11,541 9 comments 0 reactions 0 assignees View on GitHub
P1 QA: Eng Team M Type: Enhancement Type: Infrastructure
Dominant language
JavaScript
Stars
1.4k
Forks
383
Avg merge
4d 14h
Merged PRs (30d)
77

Description

## Feature Description

Decouple Google Tag Gateway (GTG) health status from GTG settings to create a cleaner separation of concerns and improve data architecture. Currently, health status properties (`isGTGHealthy`, `isScriptAccessEnabled`) are stored alongside site configuration (`isEnabled`) in a single settings object, which combines server health monitoring with site preferences.

This decoupling will:
- Separate health monitoring data from site configuration settings
- Enable intent-based storage where `isEnabled` is only saved when users make deliberate choices
- Distinguish between user decisions and default states for future auto-enablement features
- Simplify settings management and health state tracking
- Enable better migration strategies for tracking user interaction history
- Provide a foundation for future GTG enhancements like auto-enablement features

---------------

_Do not alter or remove anything below. The following sections will be managed by moderators only._

## Acceptance criteria

* New health monitoring data (`isUpstreamHealthy`, `isMpathHealthy`) should be stored separately from site configuration data (`isEnabled`).
* Health monitoring data should be managed independently from site configuration settings.
* Existing health checks (`isGTGHealthy`, `isScriptAccessEnabled`) should be removed from GTG settings and replaced with the new separated health monitoring system to determine GTG operational status, while preserving the existing health check logic and functionality.
* A new API endpoint should be created for health monitoring data, while existing GTG settings endpoints should continue to work seamlessly (backward compatibility).
* Health monitoring data should be automatically migrated from existing combined settings using proper migration patterns.
* The `isEnabled` setting should only be stored in the database when it represents an intentional user choice, ensuring we can distinguish between user decisions and default states.
* Migration should handle existing sites based on their `isEnabled` value:
* Sites with `isEnabled: false` should be treated as the default state (not storing the setting), enabling future auto-enablement.
* Sites with `isEnabled: true` should be migrated as explicit user choices.
* User interaction history should be determined using the mechanism to check if options (GTG enabled setting) have been set by avoiding the need for introducing a new flag. Otherwise, with a tracking flag as a fallback if needed.

## Implementation Brief

**Note:** Use the POC work in the [`wip/11449`](https://github.com/google/site-kit-wp/compare/main...wip/11449) branch as a starting point for this implementation.

### Backend Implementation

* [ ] Create new `Google_Tag_Gateway_Health` class extending `Setting` to manage health monitoring settings:
* Define `OPTION = 'googlesitekit_google_tag_gateway_health'`
* Implement `get_default()` returning `['isUpstreamHealthy' => null, 'isMpathHealthy' => null]`
* Implement `get_sanitize_callback()` to sanitize boolean health values
* Implement `merge()` method to update health monitoring data only
* Add `is_healthy()` method returning `true` when both health flags are `true`
* [ ] Update `Google_Tag_Gateway_Settings` class to only manage site configuration:
* Remove `isGTGHealthy` and `isScriptAccessEnabled` from `get_default()`
* Keep only `isEnabled` in default settings
* Update `get_sanitize_callback()` to handle only `isEnabled`
* Update `merge()` method to only allow `isEnabled` updates
* Deprecate `is_google_tag_gateway_active()` method (replace with new architecture)
* [ ] Refactor `Google_Tag_Gateway` class to use both settings and health instances:
* Add `$health_state` property of type `Google_Tag_Gateway_Health`
* Update constructor to instantiate both settings and health classes
* Update `register()` method to register both settings and health
* Add `is_ready_and_active()` method combining `isEnabled` && `isUpstreamHealthy` && `isMpathHealthy`:
* Use `Google_Tag_Gateway_Health::is_healthy()` method to check the health status
* Update `get_feature_metrics()` to use separated data sources
* Update `get_debug_fields()` to use new health property names
* Update `healthcheck()` method to save health data to `Google_Tag_Gateway_Health` instance
* [ ] Update `REST_Google_Tag_Gateway_Controller` to handle separated data:
* Add `$health_state` property and update constructor to accept `Google_Tag_Gateway_Health` instance
* Create new `gtg-health` REST endpoint for health monitoring data (`GET` only):
* Returns current health status: `{ "isUpstreamHealthy": true|false|null, "isMpathHealthy": true|false|null }`
* Does NOT trigger health checks (read-only access to stored health data)
* Update existing `gtg-settings` endpoint to return only site configuration data (`GET`/`POST`)
* Returns: `{ "isEnabled": true|false }` (no health data)
* Replace existing `gtg-server-requirement-status` endpoint with new `POST:gtg-health-checks` endpoint:
* Triggers server-side health checks via `Google_Tag_Gateway::healthcheck()`
* Returns health data: `{ "isUpstreamHealthy": true|false|null, "isMpathHealthy": true|false|null }`
* Similar to `core/site/data/health-checks` endpoint pattern

### Migration Implementation

* [ ] Create `Migration_n_e_x_t` class following Site Kit migration patterns:
* Extend standard migration class structure with `DB_VERSION`, `register()`, and `migrate()` methods
* Implement migration logic based on AC requirements:
* For existing sites with GTG settings:
* Extract health data (`isGTGHealthy`, `isScriptAccessEnabled`) → migrate to new `Google_Tag_Gateway_Health` option as (`isUpstreamHealthy`, `isMpathHealthy`)
* Sites with `isEnabled: true` → keep `isEnabled: true` in settings (explicit user choice)
* Sites with `isEnabled: false` → remove the entire GTG settings option (treat as default state)
* Use WordPress `Options::has()` method to detect if GTG settings exist, with tracking flags as fallback if needed
* [ ] Register migration class in `includes/Plugin.php` following existing pattern
* Add migration instantiation and registration in the main plugin initialization

### Frontend Implementation

* [ ] Update existing GTG datastore (`assets/js/googlesitekit/datastore/site/google-tag-gateway.js`) to handle separated backend data
* **Update `baseInitialState` to separate concerns:**
```javascript
const baseInitialState = {
gtgSettings: undefined, // Only { isEnabled }
gtgSavedSettings: undefined, // Only { isEnabled }
gtgHealthStatus: undefined, // Only { isUpstreamHealthy, isMpathHealthy }
};
```
* **Create separate reducer callbacks:**
* `settingsReducerCallback`: Updates only `gtgSettings` and `gtgSavedSettings` with `{ isEnabled }`
* `healthReducerCallback`: Updates only `gtgHealthStatus` with `{ isUpstreamHealthy, isMpathHealthy }`
* **Add `fetchGetGTGHealthStore`** for new `GET:gtg-health` endpoint using `healthReducerCallback`
* **Add `fetchPostGTGHealthChecksStore`** for new `POST:gtg-health-checks` endpoint using `healthReducerCallback`
* **Update `fetchGetGoogleTagGatewaySettingsStore`** to use `GET:gtg-settings` endpoint (already using `settingsReducerCallback`)
* **Remove `fetchGetGTGServerRequirementStatusStore`** from store combination and replace with `fetchPostGTGHealthChecksStore`
* **Update `fetchSaveGoogleTagGatewaySettingsStore`** to use `POST:gtg-settings` endpoint validation to ensure only `isEnabled` property (already implemented)
* **Add new selectors for health data:**
* `getGoogleTagGatewayHealthStatus: (state) => state.gtgHealthStatus`
* `isUpstreamHealthy()` - reads from `gtgHealthStatus.isUpstreamHealthy`
* `isMpathHealthy()` - reads from `gtgHealthStatus.isMpathHealthy`
* **Remove old health selectors**:
* `isGTGHealthy()`
* `isScriptAccessEnabled()`
* **Add resolver for health data:**
* `*getGoogleTagGatewayHealthStatus()` resolver to fetch health status when undefined
* **Update `baseReducer`** to handle health data actions if needed (or keep health data read-only from API)
* **Update store combination** to include new `fetchGetGTGHealthStore` (GET) and `fetchPostGTGHealthChecksStore` (POST)
* [ ] Update GTG components to use new selector names and endpoints
* Update `assets/js/components/google-tag-gateway/GoogleTagGatewayToggle.js`:
* Replace `fetchGetGTGServerRequirementStatus()` dispatch with `fetchPostGTGHealthChecks()`
* Replace `isFetchingGetGTGServerRequirementStatus()` selector with `isFetchingPostGTGHealthChecks()`
* Update to use `isUpstreamHealthy()` and `isMpathHealthy()` selectors instead of `isGTGHealthy()` and `isScriptAccessEnabled()`
* Update `assets/js/googlesitekit/notifications/register-defaults.js`:
* Replace `fetchGetGTGServerRequirementStatus()` dispatch with `fetchPostGTGHealthChecks()`
* Update health selectors to use new names
* Update `assets/js/modules/ads/components/settings/SettingsView.js` GTG health checks to use new selectors
* Update `assets/js/modules/analytics-4/components/settings/SettingsView.js` GTG health checks to use new selectors
* Update `assets/js/modules/tagmanager/components/settings/SettingsView.js` GTG health checks to use new selectors
* Combine `isEnabled` (from settings) with `isUpstreamHealthy` && `isMpathHealthy` (from health) for operational status

#### Backward Compatibility

* Preserve existing health check logic and functionality (no changes to health check algorithms)

### Test Coverage

#### PHP Tests
* Create `Google_Tag_Gateway_HealthTest.php` for new health class
* Update `Google_Tag_Gateway_SettingsTest.php` to remove health properties
* Update `REST_Google_Tag_Gateway_ControllerTest.php` for new endpoints
* Update `Google_Tag_GatewayTest.php` for new architecture
* Create migration test class for GTG health decoupling

#### JavaScript Tests
* Update `assets/js/googlesitekit/datastore/site/google-tag-gateway.test.js`:
* Remove `fetchGetGTGServerRequirementStatusStore` tests
* Add `fetchPostGTGHealthChecksStore` tests
* Remove health selectors (`isGTGHealthy`, `isScriptAccessEnabled`)
* Add new health selectors (`isUpstreamHealthy`, `isMpathHealthy`)
* Update any other test files that mock GTG health properties to use the new state structure
* Update the VRT images if needed

## QA Brief

#### Prerequisites
* Ensure the `googleTagGateway` feature flag is enabled
* Have a site with Google Ads, Analytics 4, or Tag Manager connected
* Database verification should be done using the `wp_options` table in the database.
* **Note:** There are no new UI or behavior changes as part of this ticket. So the GTG funtionality should work as expected and shouldn't cause any regressions.

#### Test 1: GTG Toggle Functionality
1. Navigate to Settings → Connected Services → Ads/Analytics/Tag Manager
2. Locate the "Google tag gateway for advertisers" toggle
3. Verify the toggle is OFF by default in a new site
4. Enable the toggle → Verify the toggle switches to ON, settings save successfully
5. Verify the toggle state persists across Ads, Analytics, and Tag Manager settings
6. Disable the toggle in any module → Verify the toggle is OFF in all modules.
7. The above should work as expected and shouldn't cause any regressions.

#### Test 2: Site Health Information
1. Navigate to Tools → Site Health → Info → Site Kit by Google
2. Verify the three GTG-related fields as it works before:
- "Google tag gateway for advertisers" (Enabled/Disabled)
- "Google tag gateway for advertisers: Service healthy" (Yes/No)
- "Google tag gateway for advertisers: Script accessible" (Yes/No)

#### Test 3: Frontend Verification
1. Enable GTG toggle (ensure health checks pass)
2. Visit the frontend of the site
3. View page source and verify the `gtg/measurement.php` script references are present
4. The above can be verified in the browser Network tab as well.

#### Test 4: Fresh Installation (No Migration)
1. Setup Site Kit with the `develop` branch which has the new GTG health monitoring implementation.
2. Visit Analytics Settings and verify the GTG toggle is OFF by default.
3. Check database and verify the `googlesitekit_google_tag_gateway` option does **not** exist initially (GTG disabled by default).
4. Verify the `googlesitekit_google_tag_gateway_health` option is created with `{"isUpstreamHealthy":true|false,"isMpathHealthy":true|false}` (health data from automatic checks).
5. Enable GTG toggle and verify the `googlesitekit_google_tag_gateway` option is now created with `{"isEnabled":true}`.

---

#### QA:Eng (Migration Verification)

**Note**: Migration testing requires temporarily modifying the DB version constant in code.

#### Setup for Migration Tests
1. Checkout Site Kit version 1.163.0 (or any version before this change)
2. Set up GTG in a specific state (enabled or disabled)
3. Update to the `develop` branch which has the new GTG health monitoring implementation.
4. Temporarily set `Migration_N_E_X_T::DB_VERSION` to the next DB version to force migration
5. Delete the `googlesitekit_db_version` option from `wp_options` table in the database
6. Visit SK dashboard to trigger migration
7. Verify migration results

#### Test 1: Migration with GTG Enabled
**Setup (on old version)**:
1. Enable GTG toggle
2. Verify DB option: `googlesitekit_google_tag_gateway` = `{"isEnabled":true,"isGTGHealthy":true,"isScriptAccessEnabled":true}`

**After Migration**:
1. Check `googlesitekit_google_tag_gateway` = `{"isEnabled":true}` (legacy health fields removed)
2. Check `googlesitekit_google_tag_gateway_health` = `{"isUpstreamHealthy":true,"isMpathHealthy":true}` (health data migrated)
3. Visit Settings and verify the GTG toggle is ON (preserved user's choice)

#### Test 2: Migration with GTG Disabled
**Setup (on old version)**:
1. Ensure GTG toggle is OFF
2. Verify DB option: `googlesitekit_google_tag_gateway` = `{"isEnabled":false,...}`

**After Migration**:
1. Check `googlesitekit_google_tag_gateway` option is **deleted** (treated as default state)
2. Check `googlesitekit_google_tag_gateway_health` exists with migrated health data
3. Visit Settings and verify the GTG toggle is OFF
4. Enable toggle and verify the `googlesitekit_google_tag_gateway` option is created with `{"isEnabled":true}`

#### Test 3: Fresh Installation (No Migration)
1. Setup Site Kit with the `develop` branch which has the new GTG health monitoring implementation.
2. Visit Analytics Settings and verify the GTG toggle is OFF by default.
3. Check database and verify the `googlesitekit_google_tag_gateway` option does **not** exist initially (GTG disabled by default).
4. Verify the `googlesitekit_google_tag_gateway_health` option is created with `{"isUpstreamHealthy":true|false,"isMpathHealthy":true|false}` (health data from automatic checks).
5. Enable GTG toggle and verify the `googlesitekit_google_tag_gateway` option is now created with `{"isEnabled":true}`.

#### Test 4: New API Endpoints Verification
1. Open browser DevTools → Network tab
2. View any Settings edit page with GTG toggle (Ads/Analytics/Tag Manager)
3. Verify the `POST:gtg-health-checks` endpoint is called instead of the legacy `gtg-server-requirement-status` endpoint.

#### Test 5: Selectors Verification
Open browser console and test the following selectors:

**GTG Settings:**
```javascript
googlesitekit.data.select('core/site').getGoogleTagGatewaySettings()
// Expected: { isEnabled: true|false }
```

**GTG Health Status:**
```javascript
googlesitekit.data.select('core/site').getGoogleTagGatewayHealthStatus()
// Expected: { isUpstreamHealthy: true|false|null, isMpathHealthy: true|false|null }

googlesitekit.data.select('core/site').isUpstreamHealthy()
// Expected: true|false|null

googlesitekit.data.select('core/site').isMpathHealthy()
// Expected: true|false|null
```

**GTG Enabled Status:**
```javascript
googlesitekit.data.select('core/site').isGoogleTagGatewayEnabled()
// Expected: true|false
```

## Changelog entry

*

Contributor guide

Open the contributing guide

Research direction

Start with the POC in the wip/11449 branch, then read the Google_Tag_Gateway, Google_Tag_Gateway_Settings, and REST_Google_Tag_Gateway_Controller classes alongside assets/js/googlesitekit/datastore/site/google-tag-gateway.js. Trace the existing settings and health-check endpoints, migrations in includes/Plugin.php, and their PHP and JavaScript tests. Done means separated settings and health data, migrated existing options, working endpoints, updated consumers, and passing coverage.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript, php, wordpress
Domain
api, database, full-stack, testing
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.