From 39ffc0ccacec2df71ed635db3ce552f52b2c021c Mon Sep 17 00:00:00 2001 From: Daan van den Bergh <18595395+Dan0sz@users.noreply.github.com> Date: Wed, 11 Nov 2026 14:06:47 +0100 Subject: [PATCH 1/4] Let Logged-in user status control the user_logged_in property The property (and its Custom Property) followed Authors and categories instead, so the Logged-in user status option had no effect. Its logged-out value is no longer translated, as that split it up per language. An upgrade routine enables the Custom Property for sites that already have Logged-in user status enabled. Fixes #339 --- readme.txt | 4 ++++ src/Admin/Provisioning.php | 9 ++++++++- src/Admin/Upgrades.php | 24 ++++++++++++++++++++++++ src/InitOptions.php | 8 ++++++-- tests/TestCase.php | 13 +++++++++++++ tests/integration/InitOptionsTest.php | 19 ++++++++++++++++++- 6 files changed, 73 insertions(+), 4 deletions(-) diff --git a/readme.txt b/readme.txt index 3b7cfc49..da507cda 100644 --- a/readme.txt +++ b/readme.txt @@ -278,6 +278,10 @@ Please make sure you make a backup of your database before updating any version == Changelog == += 2.6.5 = +* Fixed: the "Logged-in user status" option had no effect: the user_logged_in property was sent (and its Custom Property created) when "Authors and categories" was enabled instead. It now follows "Logged-in user status", so sites with only "Authors and categories" enabled no longer send it. +* Fixed: the user_logged_in value for logged-out visitors was translated (e.g. "non" in French), which split it up per language. It's now always "no". + = 2.6.4 = * Improved: the proxy now also forwards the visitor's Accept-Language and User-Agent Client Hints (Sec-CH-UA*) headers to Plausible Analytics, so its bot detection works for proxied requests, too. * Fixed: on sites using WPML (or another multilingual plugin) with a directory per language, the Domain Name could be pre-filled with the language directory included (e.g. example.com/fr), which made the Plugin Token show as invalid. diff --git a/src/Admin/Provisioning.php b/src/Admin/Provisioning.php index 72afb5b3..e0ef1df5 100644 --- a/src/Admin/Provisioning.php +++ b/src/Admin/Provisioning.php @@ -68,7 +68,6 @@ class Provisioning { private $custom_pageview_properties = [ 'author', 'category', - 'user_logged_in', ]; /** * @var string[] $custom_search_properties @@ -673,6 +672,7 @@ public function maybe_create_custom_properties( $_, $settings ) { $query_params = $settings['query_params'] ?? []; if ( ! EnhancedMeasurements::is_enabled( EnhancedMeasurements::PAGEVIEW_PROPS, $enhanced_measurements ) && + ! EnhancedMeasurements::is_enabled( EnhancedMeasurements::LOGGED_IN_USER_STATUS, $enhanced_measurements ) && ! EnhancedMeasurements::is_enabled( EnhancedMeasurements::ECOMMERCE_REVENUE, $enhanced_measurements ) && ! EnhancedMeasurements::is_enabled( EnhancedMeasurements::SEARCH_QUERIES, $enhanced_measurements ) && empty( $query_params ) ) { @@ -691,6 +691,13 @@ public function maybe_create_custom_properties( $_, $settings ) { } } + /** + * Enable the Custom Property for the Logged-in user status option. + */ + if ( EnhancedMeasurements::is_enabled( EnhancedMeasurements::LOGGED_IN_USER_STATUS, $enhanced_measurements ) ) { + $properties[] = new Client\Model\CustomProp( [ 'custom_prop' => [ 'key' => 'user_logged_in' ] ] ); + } + /** * Create Custom Properties for WooCommerce integration. */ diff --git a/src/Admin/Upgrades.php b/src/Admin/Upgrades.php index dbe6ae07..8e709c0e 100644 --- a/src/Admin/Upgrades.php +++ b/src/Admin/Upgrades.php @@ -110,6 +110,10 @@ public function run() { $this->upgrade_to_262(); } + if ( version_compare( $plausible_analytics_version, '2.6.5', '<' ) ) { + $this->upgrade_to_265(); + } + // Add required upgrade routines for future versions here. } @@ -493,6 +497,26 @@ public function upgrade_to_262() { update_option( 'plausible_analytics_version', '2.6.2' ); } + /** + * Upgrade routine for 2.6.5 + * + * Until now, the user_logged_in Custom Property was only enabled along with Authors and categories. Enable it for + * sites that have Logged-in user status enabled, now that this option actually controls it. + * + * @since v2.6.5 + * + * @return void + * + * @codeCoverageIgnore because all we'd be doing is testing the Plugins API. + */ + public function upgrade_to_265() { + if ( EnhancedMeasurements::is_enabled( EnhancedMeasurements::LOGGED_IN_USER_STATUS ) ) { + ( new Provisioning() )->maybe_create_custom_properties( [], Helpers::get_settings() ); + } + + update_option( 'plausible_analytics_version', '2.6.5' ); + } + /** * Display a notice to CE users that haven't entered an API token yet. * diff --git a/src/InitOptions.php b/src/InitOptions.php index e6f0de70..9a58b6e2 100644 --- a/src/InitOptions.php +++ b/src/InitOptions.php @@ -176,11 +176,15 @@ private function url_matches_patterns( $url, $patterns ) { public function maybe_track_logged_in_users( $options = [] ) { $settings = Helpers::get_settings(); - if ( ! is_array( $settings['enhanced_measurements'] ) || ! in_array( EnhancedMeasurements::PAGEVIEW_PROPS, $settings['enhanced_measurements'] ) ) { + if ( ! is_array( $settings['enhanced_measurements'] ) || ! in_array( EnhancedMeasurements::LOGGED_IN_USER_STATUS, $settings['enhanced_measurements'] ) ) { return $options; // @codeCoverageIgnore } - $logged_in = _x( 'no', 'Value when user is not logged in.', 'plausible-analytics' ); + /** + * Not translated, as it's a property value: translating it would split it up per language in the dashboard, + * just like the role names it sits next to. + */ + $logged_in = 'no'; if ( is_user_logged_in() ) { $user = wp_get_current_user(); diff --git a/tests/TestCase.php b/tests/TestCase.php index 49e2b12a..b6b4e6bf 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -173,6 +173,19 @@ public function enablePageviewProps( $settings ) { return $settings; } + /** + * Enable Logged-in user status. + * + * @param $settings + * + * @return mixed + */ + public function enableLoggedInUserStatus( $settings ) { + $settings['enhanced_measurements'] = [ 'user-logged-in' ]; + + return $settings; + } + /** * Enable the proxy. * diff --git a/tests/integration/InitOptionsTest.php b/tests/integration/InitOptionsTest.php index 6413038b..13b76cd2 100644 --- a/tests/integration/InitOptionsTest.php +++ b/tests/integration/InitOptionsTest.php @@ -147,16 +147,31 @@ public function testExcludePageview() { * @return void */ public function testTrackLoggedInUsers() { + // The logged-out value must not be translated, whatever the site's language. + $translate = function ( $translation, $text ) { + return $text === 'no' ? 'non' : $translation; + }; + try { /** @var InitOptions $class */ $class = $this->getMockBuilder( InitOptions::class )->disableOriginalConstructor()->onlyMethods( [] )->getMock(); + // Authors and categories doesn't control the user_logged_in property. add_filter( 'plausible_analytics_settings', [ $this, 'enablePageviewProps' ] ); $params = $class->maybe_track_logged_in_users(); + $this->assertArrayNotHasKey( 'customProperties', $params ); + + remove_filter( 'plausible_analytics_settings', [ $this, 'enablePageviewProps' ] ); + add_filter( 'plausible_analytics_settings', [ $this, 'enableLoggedInUserStatus' ] ); + + add_filter( 'gettext_with_context', $translate, 10, 2 ); + + $params = $class->maybe_track_logged_in_users(); + $this->assertArrayHasKey( 'customProperties', $params ); - $this->assertArrayHasKey( 'user_logged_in', $params['customProperties'] ); + $this->assertEquals( 'no', $params['customProperties']['user_logged_in'] ); global $current_user; @@ -172,6 +187,8 @@ public function testTrackLoggedInUsers() { $this->assertEquals( 'test', $params['customProperties']['user_logged_in'] ); } finally { remove_filter( 'plausible_analytics_settings', [ $this, 'enablePageviewProps' ] ); + remove_filter( 'plausible_analytics_settings', [ $this, 'enableLoggedInUserStatus' ] ); + remove_filter( 'gettext_with_context', $translate ); // Don't leave the test user logged in for the tests that follow. wp_set_current_user( 0 ); } From 43eb53cc361fd0ae02c0bdf514091adc50f1f3cb Mon Sep 17 00:00:00 2001 From: Daan van den Bergh <18595395+Dan0sz@users.noreply.github.com> Date: Wed, 11 Nov 2026 16:13:31 +0100 Subject: [PATCH 2/4] Don't run the 2.6.5 upgrade on AJAX requests A failing API call sends a JSON error there, which would replace the response of the unrelated AJAX handler (e.g. the heartbeat) and keep the upgrade from completing. --- src/Admin/Upgrades.php | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/Admin/Upgrades.php b/src/Admin/Upgrades.php index 8e709c0e..8ed15f1e 100644 --- a/src/Admin/Upgrades.php +++ b/src/Admin/Upgrades.php @@ -510,6 +510,16 @@ public function upgrade_to_262() { * @codeCoverageIgnore because all we'd be doing is testing the Plugins API. */ public function upgrade_to_265() { + /** + * Upgrades also run on AJAX requests (e.g. the heartbeat), where a failing API call would send an error response + * in place of the requested handler's. Wait for a regular admin request, where API errors are silent. + * + * @see Client::send_json_error() + */ + if ( wp_doing_ajax() ) { + return; + } + if ( EnhancedMeasurements::is_enabled( EnhancedMeasurements::LOGGED_IN_USER_STATUS ) ) { ( new Provisioning() )->maybe_create_custom_properties( [], Helpers::get_settings() ); } From c84c26ae05929b761eaf348d08fe3847adc45c44 Mon Sep 17 00:00:00 2001 From: Daan van den Bergh <18595395+Dan0sz@users.noreply.github.com> Date: Thu, 12 Nov 2026 09:54:29 +0100 Subject: [PATCH 3/4] Shorten the 2.6.5 changelog entries --- readme.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/readme.txt b/readme.txt index da507cda..7a0490c3 100644 --- a/readme.txt +++ b/readme.txt @@ -279,8 +279,8 @@ Please make sure you make a backup of your database before updating any version == Changelog == = 2.6.5 = -* Fixed: the "Logged-in user status" option had no effect: the user_logged_in property was sent (and its Custom Property created) when "Authors and categories" was enabled instead. It now follows "Logged-in user status", so sites with only "Authors and categories" enabled no longer send it. -* Fixed: the user_logged_in value for logged-out visitors was translated (e.g. "non" in French), which split it up per language. It's now always "no". +* Fixed: the user_logged_in property followed the "Authors and categories" option instead of "Logged-in user status". +* Fixed: the user_logged_in value for logged-out visitors is no longer translated, so it's always "no". = 2.6.4 = * Improved: the proxy now also forwards the visitor's Accept-Language and User-Agent Client Hints (Sec-CH-UA*) headers to Plausible Analytics, so its bot detection works for proxied requests, too. From c888d1bef6e91b6a292d34b2bb8b705ec71f84f6 Mon Sep 17 00:00:00 2001 From: Daan van den Bergh <18595395+Dan0sz@users.noreply.github.com> Date: Thu, 12 Nov 2026 09:55:43 +0100 Subject: [PATCH 4/4] Shorten code comments --- src/Admin/Upgrades.php | 7 +++---- src/InitOptions.php | 5 +---- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/src/Admin/Upgrades.php b/src/Admin/Upgrades.php index 8ed15f1e..b7263874 100644 --- a/src/Admin/Upgrades.php +++ b/src/Admin/Upgrades.php @@ -500,8 +500,7 @@ public function upgrade_to_262() { /** * Upgrade routine for 2.6.5 * - * Until now, the user_logged_in Custom Property was only enabled along with Authors and categories. Enable it for - * sites that have Logged-in user status enabled, now that this option actually controls it. + * Enables the user_logged_in Custom Property if Logged-in user status is enabled. * * @since v2.6.5 * @@ -511,8 +510,8 @@ public function upgrade_to_262() { */ public function upgrade_to_265() { /** - * Upgrades also run on AJAX requests (e.g. the heartbeat), where a failing API call would send an error response - * in place of the requested handler's. Wait for a regular admin request, where API errors are silent. + * Skipped on AJAX requests, where a failing API call replaces the response with an error. Runs on the next regular + * admin request instead. * * @see Client::send_json_error() */ diff --git a/src/InitOptions.php b/src/InitOptions.php index 9a58b6e2..4e3f3e73 100644 --- a/src/InitOptions.php +++ b/src/InitOptions.php @@ -180,10 +180,7 @@ public function maybe_track_logged_in_users( $options = [] ) { return $options; // @codeCoverageIgnore } - /** - * Not translated, as it's a property value: translating it would split it up per language in the dashboard, - * just like the role names it sits next to. - */ + // Not translated, so the value is the same in every language. $logged_in = 'no'; if ( is_user_logged_in() ) {