+ $options,
+ 'posted_values' => [],
+ ];
+ }
+
+ $rebuilt_options = [];
+ foreach ( $rebuilt as $name => $value ) {
+ $rebuilt_options[] = [
+ 'name' => $name,
+ 'value' => $value,
+ ];
+ }
+
+ return [
+ 'options' => $rebuilt_options,
+ 'posted_values' => $posted_values,
+ ];
+ }
+}
diff --git a/src/Admin/Settings/Page.php b/src/Admin/Settings/Page.php
index 594950d3..dca14118 100644
--- a/src/Admin/Settings/Page.php
+++ b/src/Admin/Settings/Page.php
@@ -489,6 +489,15 @@ public function __construct() {
$this->fields['self-hosted'][1]['fields'][] = self::OPTION_DISABLED_BY_PROXY_HOOK;
}
+ if ( Helpers::is_multilang_domain_mode() ) {
+ $this->fields['general'][0]['fields'] = [
+ [
+ 'slug' => 'domain_map',
+ 'type' => 'domain_map',
+ ],
+ ];
+ }
+
/**
* No Plugin Token is entered.
*/
diff --git a/src/Ajax.php b/src/Ajax.php
index 2f05eea0..a05493a5 100644
--- a/src/Ajax.php
+++ b/src/Ajax.php
@@ -11,6 +11,7 @@
use Plausible\Analytics\WP\Admin\Messages;
use Plausible\Analytics\WP\Admin\Settings\Hooks;
+use Plausible\Analytics\WP\Admin\Settings\OptionsParser;
use Plausible\Analytics\WP\Admin\Settings\Page;
use Plausible\Analytics\WP\Client\ApiException;
@@ -372,6 +373,18 @@ function ( $option ) {
}
}
+ $options_to_parse = [];
+ foreach ( $options as $option ) {
+ $options_to_parse[] = (array) $option;
+ }
+
+ $parsed_options = OptionsParser::parse_keyed_options( $options_to_parse, $settings );
+ $options = [];
+ foreach ( $parsed_options['options'] as $option ) {
+ $options[] = (object) $option;
+ }
+ $posted_values = $parsed_options['posted_values'];
+
foreach ( $options as $option ) {
$name = sanitize_text_field( $option->name );
$value = $this->clean( $option->value );
@@ -385,11 +398,30 @@ function ( $option ) {
// Validate Plugin Token if this is the Plugin Token field.
if ( $name === 'api_token' ) {
- $this->validate_api_token( $value );
-
- $additional = $this->maybe_render_additional_message( $name, $value );
-
- Messages::set_additional( $additional, $name );
+ if ( isset( $posted_values['api_token'] ) ) {
+ // Multilang: validate ONLY the freshly posted token. During validation, force
+ // Helpers::get_domain() to return the Plausible domain entered for THIS pair, so
+ // Client::validate_api_token()'s data-domain comparison works. The per-domain
+ // domain_name isn't persisted yet at this point, and the admin request host is
+ // not necessarily the domain being connected.
+ $posted_domain = isset( $posted_values['domain_name'] ) ? $this->clean( $posted_values['domain_name'] ) : '';
+ $force_domain = function ( $s ) use ( $posted_domain ) {
+ $s['domain_name'] = $posted_domain; // string -> Helpers::get_domain() returns it directly
+
+ return $s;
+ };
+
+ add_filter( 'plausible_analytics_settings', $force_domain );
+ $this->validate_api_token( $this->clean( $posted_values['api_token'] ) );
+ remove_filter( 'plausible_analytics_settings', $force_domain );
+ // No additional (missing-token) message for the multilang case.
+ } else {
+ $this->validate_api_token( $value );
+
+ $additional = $this->maybe_render_additional_message( $name, $value );
+
+ Messages::set_additional( $additional, $name );
+ }
}
// Refresh Tracker ID if Domain Name has changed (e.g. after migration from staging to production)
diff --git a/src/ClientFactory.php b/src/ClientFactory.php
index 6d17509d..a1ce56dc 100644
--- a/src/ClientFactory.php
+++ b/src/ClientFactory.php
@@ -13,7 +13,7 @@ class ClientFactory {
/**
* Setup basic authorization.
*
- * @param string $token Allows to specify the token, e.g. when it's not stored in the DB yet.
+ * @param string $token Allows specifying the token, e.g., when it's not stored in the DB yet.
*/
public function __construct( $token = '' ) {
$this->token = $token;
@@ -35,7 +35,7 @@ public function build() {
}
if ( ! $this->token ) {
- $this->token = Helpers::get_settings()['api_token'];
+ $this->token = Helpers::get_api_token();
}
if ( ! $this->token ) {
diff --git a/src/Helpers.php b/src/Helpers.php
index 257b4d8e..00d785dc 100644
--- a/src/Helpers.php
+++ b/src/Helpers.php
@@ -26,6 +26,17 @@ public static function get_domain() {
$settings = static::get_settings();
if ( ! empty( $settings['domain_name'] ) ) {
+ if ( is_array( $settings['domain_name'] ) ) {
+ $current_domain = static::get_current_multilang_domain();
+ $domain_name = $settings['domain_name'][ $current_domain ] ?? '';
+
+ if ( ! empty( $domain_name ) ) {
+ return $domain_name;
+ }
+
+ return reset( $settings['domain_name'] );
+ }
+
return $settings['domain_name'];
}
@@ -34,6 +45,84 @@ public static function get_domain() {
return preg_replace( '/^http(s?):\/\/(www\.)?/i', '', $url );
}
+ /**
+ * Returns the API token.
+ *
+ * @return string
+ */
+ public static function get_api_token() {
+ $settings = static::get_settings();
+ $token = $settings['api_token'] ?? '';
+
+ if ( is_array( $token ) ) {
+ return $token[ static::get_current_multilang_domain() ] ?? '';
+ }
+
+ return (string) $token;
+ }
+
+ /**
+ * Returns true only when WPML is active, its negotiation type is "different domain per language", AND at least one domain is configured.
+ *
+ * @return bool
+ */
+ public static function is_multilang_domain_mode() {
+ $is_wpml_active = defined( 'ICL_SITEPRESS_VERSION' );
+
+ if ( ! $is_wpml_active ) {
+ return (bool) apply_filters( 'plausible_analytics_is_multilang_domain_mode', false );
+ }
+
+ $negotiation_type = (int) apply_filters( 'wpml_setting', 0, 'language_negotiation_type' );
+ $domains = static::get_multilang_domains();
+ $value = $negotiation_type === 2 && ! empty( $domains );
+
+ return (bool) apply_filters( 'plausible_analytics_is_multilang_domain_mode', $value );
+ }
+
+ /**
+ * Returns a plain, numerically-indexed array of the configured domain strings.
+ *
+ * @return array
+ */
+ public static function get_multilang_domains() {
+ $domains = apply_filters( 'wpml_setting', [], 'language_domains' );
+
+ return (array) apply_filters( 'plausible_analytics_multilang_domains', $domains );
+ }
+
+ /**
+ * Returns the domain string that corresponds to the current request.
+ *
+ * @return string
+ */
+ public static function get_current_multilang_domain() {
+ if ( ! static::is_multilang_domain_mode() ) {
+ return '';
+ }
+
+ $domains = static::get_multilang_domains();
+ $language_domains = apply_filters( 'wpml_setting', [], 'language_domains' );
+ $current_language = apply_filters( 'wpml_current_language', null );
+
+ if ( $current_language && isset( $language_domains[ $current_language ] ) ) {
+ return (string) apply_filters( 'plausible_analytics_current_multilang_domain', $language_domains[ $current_language ] );
+ }
+
+ $http_host = $_SERVER['HTTP_HOST'] ?? '';
+ $host = preg_replace( '/^https?:\/\/(www\.)?|(\/.*)|(:\d+)/i', '', $http_host );
+
+ foreach ( $domains as $domain ) {
+ $clean_domain = preg_replace( '/^https?:\/\/(www\.)?|(\/.*)|(:\d+)/i', '', $domain );
+
+ if ( $host === $clean_domain ) {
+ return (string) apply_filters( 'plausible_analytics_current_multilang_domain', $domain );
+ }
+ }
+
+ return (string) apply_filters( 'plausible_analytics_current_multilang_domain', reset( $domains ) );
+ }
+
/**
* Get Settings.
*
@@ -65,7 +154,7 @@ public static function get_settings() {
'self_hosted_shared_link' => '',
];
- $settings = get_option( 'plausible_analytics_settings', [] );
+ $settings = function_exists( 'get_option' ) ? get_option( 'plausible_analytics_settings', [] ) : [];
return apply_filters( 'plausible_analytics_settings', wp_parse_args( $settings, $defaults ) );
}
diff --git a/tests/HelpersMultilangTest.php b/tests/HelpersMultilangTest.php
new file mode 100644
index 00000000..ff9d1252
--- /dev/null
+++ b/tests/HelpersMultilangTest.php
@@ -0,0 +1,130 @@
+original_server = $_SERVER;
+ }
+
+ protected function tearDown(): void {
+ $_SERVER = $this->original_server;
+ parent::tearDown();
+ }
+
+ public function test_is_multilang_domain_mode() {
+ // Mock WPML not active
+ $this->assertFalse( Helpers::is_multilang_domain_mode() );
+
+ // Mock WPML active, but wrong negotiation type
+ define( 'ICL_SITEPRESS_VERSION', '4.5.0' );
+ \Brain\Monkey\Filters\expectApplied( 'wpml_setting' )
+ ->with( false, 'language_negotiation_type' )
+ ->andReturn( 1 );
+ $this->assertFalse( Helpers::is_multilang_domain_mode() );
+
+ // Mock WPML active, correct negotiation type, but no domains
+ \Brain\Monkey\Filters\expectApplied( 'wpml_setting' )
+ ->with( false, 'language_negotiation_type' )
+ ->andReturn( 2 );
+ \Brain\Monkey\Filters\expectApplied( 'wpml_setting' )
+ ->with( [], 'language_domains' )
+ ->andReturn( [] );
+ $this->assertFalse( Helpers::is_multilang_domain_mode() );
+
+ // Mock WPML active, correct negotiation type, and domains
+ \Brain\Monkey\Filters\expectApplied( 'wpml_setting' )
+ ->with( false, 'language_negotiation_type' )
+ ->andReturn( 2 );
+ \Brain\Monkey\Filters\expectApplied( 'wpml_setting' )
+ ->with( [], 'language_domains' )
+ ->andReturn( [ 'en' => 'english.dev.local', 'nl' => 'dutch.dev.local' ] );
+ $this->assertTrue( Helpers::is_multilang_domain_mode() );
+ }
+
+ public function test_get_current_multilang_domain() {
+ // Mock multilang mode
+ add_filter( 'plausible_analytics_is_multilang_domain_mode', '__return_true' );
+ \Brain\Monkey\Filters\expectApplied( 'wpml_setting' )
+ ->with( [], 'language_domains' )
+ ->andReturn( [ 'en' => 'english.dev.local', 'nl' => 'dutch.dev.local' ] );
+
+ // 1. Resolution via current language
+ \Brain\Monkey\Filters\expectApplied( 'wpml_current_language', null )
+ ->andReturn( 'nl' );
+
+ $this->assertEquals( 'dutch.dev.local', Helpers::get_current_multilang_domain() );
+
+ // 2. Resolution via HTTP_HOST
+ \Brain\Monkey\Filters\expectApplied( 'wpml_current_language', null )
+ ->andReturn( null );
+ $_SERVER['HTTP_HOST'] = 'english.dev.local';
+ $this->assertEquals( 'english.dev.local', Helpers::get_current_multilang_domain() );
+
+ $_SERVER['HTTP_HOST'] = 'www.english.dev.local:8080';
+ $this->assertEquals( 'english.dev.local', Helpers::get_current_multilang_domain() );
+
+ // 3. Fallback to first domain
+ $_SERVER['HTTP_HOST'] = 'unknown.local';
+ $this->assertEquals( 'english.dev.local', Helpers::get_current_multilang_domain() );
+ }
+
+ public function test_get_domain_and_api_token() {
+ $settings = [
+ 'domain_name' => [
+ 'en' => 'english.plausible.io',
+ 'nl' => 'dutch.plausible.io',
+ ],
+ 'api_token' => [
+ 'en' => 'token-en',
+ 'nl' => 'token-nl',
+ ],
+ ];
+
+ add_filter( 'plausible_analytics_settings', function () use ( $settings ) {
+ return $settings;
+ } );
+
+ // Mock current domain to 'en'
+ add_filter( 'plausible_analytics_current_multilang_domain', function () {
+ return 'en';
+ } );
+ add_filter( 'plausible_analytics_is_multilang_domain_mode', '__return_true' );
+
+ $this->assertEquals( 'english.plausible.io', Helpers::get_domain() );
+ $this->assertEquals( 'token-en', Helpers::get_api_token() );
+
+ // Switch to 'nl'
+ remove_all_filters( 'plausible_analytics_current_multilang_domain' );
+ add_filter( 'plausible_analytics_current_multilang_domain', function () {
+ return 'nl';
+ } );
+
+ $this->assertEquals( 'dutch.plausible.io', Helpers::get_domain() );
+ $this->assertEquals( 'token-nl', Helpers::get_api_token() );
+
+ // Fallback for domain_name if current not set
+ remove_all_filters( 'plausible_analytics_current_multilang_domain' );
+ add_filter( 'plausible_analytics_current_multilang_domain', function () {
+ return 'de';
+ } );
+ $this->assertEquals( 'english.plausible.io', Helpers::get_domain() ); // first entry
+ $this->assertEquals( '', Helpers::get_api_token() ); // empty for token
+
+ // String shapes
+ remove_all_filters( 'plausible_analytics_settings' );
+ add_filter( 'plausible_analytics_settings', function () {
+ return [
+ 'domain_name' => 'single.io',
+ 'api_token' => 'single-token',
+ ];
+ } );
+ $this->assertEquals( 'single.io', Helpers::get_domain() );
+ $this->assertEquals( 'single-token', Helpers::get_api_token() );
+ }
+}
diff --git a/tests/OptionsParserTest.php b/tests/OptionsParserTest.php
new file mode 100644
index 00000000..ede61d34
--- /dev/null
+++ b/tests/OptionsParserTest.php
@@ -0,0 +1,72 @@
+ 'domain_name[english.dev.local]', 'value' => 'english.plausible.io' ],
+ [ 'name' => 'api_token[english.dev.local]', 'value' => 'token1' ],
+ [ 'name' => 'domain_name[dutch.dev.local]', 'value' => 'dutch.plausible.io' ],
+ [ 'name' => 'api_token[dutch.dev.local]', 'value' => 'token2' ],
+ [ 'name' => 'excluded_pages[0]', 'value' => '/test' ],
+ [ 'name' => 'proxy_enabled', 'value' => 'on' ],
+ [ 'name' => 'domain_name[1example.com]', 'value' => 'one.plausible.io' ],
+ ];
+
+ $settings = [
+ 'domain_name' => [
+ 'other.dev.local' => 'other.plausible.io',
+ ],
+ 'api_token' => 'old-string-token',
+ ];
+
+ $result = OptionsParser::parse_keyed_options( $options, $settings );
+
+ $rebuilt = $result['options'];
+ $posted_values = $result['posted_values'];
+
+ $rebuilt_map = [];
+ foreach ( $rebuilt as $option ) {
+ $rebuilt_map[ $option['name'] ] = $option['value'];
+ }
+
+ // Verify merged domain_name
+ $this->assertIsArray( $rebuilt_map['domain_name'] );
+ $this->assertEquals( 'english.plausible.io', $rebuilt_map['domain_name']['english.dev.local'] );
+ $this->assertEquals( 'dutch.plausible.io', $rebuilt_map['domain_name']['dutch.dev.local'] );
+ $this->assertEquals( 'other.plausible.io', $rebuilt_map['domain_name']['other.dev.local'] );
+ $this->assertEquals( 'one.plausible.io', $rebuilt_map['domain_name']['1example.com'] );
+
+ // Verify merged api_token (started as string, should become array)
+ $this->assertIsArray( $rebuilt_map['api_token'] );
+ $this->assertEquals( 'token1', $rebuilt_map['api_token']['english.dev.local'] );
+ $this->assertEquals( 'token2', $rebuilt_map['api_token']['dutch.dev.local'] );
+
+ // Verify numeric key stayed as is
+ $this->assertEquals( '/test', $rebuilt_map['excluded_pages[0]'] );
+
+ // Verify simple option stayed as is
+ $this->assertEquals( 'on', $rebuilt_map['proxy_enabled'] );
+
+ // Verify posted_values (holds the first encountered value for each keyed option)
+ $this->assertEquals( 'english.plausible.io', $posted_values['domain_name'] );
+ $this->assertEquals( 'token1', $posted_values['api_token'] );
+ }
+
+ public function test_no_keyed_options() {
+ $options = [
+ [ 'name' => 'domain_name', 'value' => 'plausible.io' ],
+ [ 'name' => 'excluded_pages[0]', 'value' => '/test' ],
+ ];
+ $settings = [];
+
+ $result = OptionsParser::parse_keyed_options( $options, $settings );
+
+ $this->assertEquals( $options, $result['options'] );
+ $this->assertEmpty( $result['posted_values'] );
+ }
+}
From dcfb62b47b7732f902d4b228b1d30d42b9e2804f Mon Sep 17 00:00:00 2001
From: Daan van den Bergh <18595395+Dan0sz@users.noreply.github.com>
Date: Mon, 22 Jun 2026 11:45:13 +0200
Subject: [PATCH 02/74] Fixed: add main WP domain to Language Domains list.
---
src/Helpers.php | 12 +++++++++---
1 file changed, 9 insertions(+), 3 deletions(-)
diff --git a/src/Helpers.php b/src/Helpers.php
index 00d785dc..c9a7584e 100644
--- a/src/Helpers.php
+++ b/src/Helpers.php
@@ -81,14 +81,20 @@ public static function is_multilang_domain_mode() {
}
/**
- * Returns a plain, numerically-indexed array of the configured domain strings.
+ * Returns a plain, numerically indexed array of the configured domain strings.
*
* @return array
*/
public static function get_multilang_domains() {
- $domains = apply_filters( 'wpml_setting', [], 'language_domains' );
+ $domains = apply_filters( 'wpml_setting', [], 'language_domains' );
+ $main = preg_replace( '/^https?:\/\/(www\.)?/i', '', home_url() );
- return (array) apply_filters( 'plausible_analytics_multilang_domains', $domains );
+ // WPML's language_domains omits the default language; prepend the main WP domain.
+ if ( ! in_array( $main, $domains, true ) ) {
+ array_unshift( $domains, $main );
+ }
+
+ return apply_filters( 'plausible_analytics_multilang_domains', $domains );
}
/**
From f1ac183e4211e087b9873eff82e0e2d71ab7342f Mon Sep 17 00:00:00 2001
From: Daan van den Bergh <18595395+Dan0sz@users.noreply.github.com>
Date: Mon, 22 Jun 2026 11:52:51 +0200
Subject: [PATCH 03/74] Fixed: validate both fields before updating Connect
button status.
---
assets/src/js/admin/main.js | 23 +++++++++++++++++++----
1 file changed, 19 insertions(+), 4 deletions(-)
diff --git a/assets/src/js/admin/main.js b/assets/src/js/admin/main.js
index 15c0fb51..5bced811 100644
--- a/assets/src/js/admin/main.js
+++ b/assets/src/js/admin/main.js
@@ -531,16 +531,31 @@ document.addEventListener('DOMContentLoaded', () => {
},
/**
- * Disable Connect button if Domain Name or API Token field is empty.
+ * Disable the Connect button if the Domain Name or API Token field is empty.
*
* @param e
*/
disableConnectButton: function (e) {
let target = e.target;
let pair = target.closest('.multilang-domain-pair');
- let button = pair ? pair.querySelector('.plausible-analytics-connect-button') : document.getElementById('connect_plausible_analytics');
+ let button;
let buttonIsHref = false;
+ if (pair !== null) {
+ button = pair.querySelector('.plausible-analytics-connect-button');
+ let allFilled = Array.from(pair.querySelectorAll('input')).every(input => input.value.trim() !== '');
+
+ if (button === null) {
+ return;
+ }
+
+ button.disabled = !allFilled;
+
+ return;
+ }
+
+ button = document.getElementById('connect_plausible_analytics');
+
if (button === null) {
let slide_id = document.location.hash;
button = document.querySelector(slide_id + ' .plausible-analytics-wizard-next-step');
@@ -556,7 +571,7 @@ document.addEventListener('DOMContentLoaded', () => {
button.disabled = false;
} else {
button.classList.remove('pointer-events-none');
- button.classList.replace('bg-gray-200', 'bg-indigo-600')
+ button.classList.replace('bg-gray-200', 'bg-indigo-600');
}
return;
@@ -567,7 +582,7 @@ document.addEventListener('DOMContentLoaded', () => {
button.innerHTML = button.innerHTML.replace('Connected', 'Connect');
} else {
button.classList += ' pointer-events-none';
- button.classList.replace('bg-indigo-600', 'bg-gray-200')
+ button.classList.replace('bg-indigo-600', 'bg-gray-200');
}
},
From 0e905a175d02c5c12aeffda252d22ae0d43da543 Mon Sep 17 00:00:00 2001
From: Daan van den Bergh <18595395+Dan0sz@users.noreply.github.com>
Date: Mon, 22 Jun 2026 16:23:41 +0200
Subject: [PATCH 04/74] Fixed: Domain Name en API token are now always stored
as an array.
---
assets/src/js/admin/main.js | 31 +-
src/Admin/Settings/API.php | 1404 +++++++++++++-------------
src/Admin/Settings/OptionsParser.php | 38 +-
src/Admin/Settings/Page.php | 72 +-
src/Ajax.php | 416 ++++----
src/Helpers.php | 191 ++--
tests/HelpersMultilangTest.php | 166 +--
tests/OptionsParserTest.php | 47 +-
8 files changed, 1158 insertions(+), 1207 deletions(-)
diff --git a/assets/src/js/admin/main.js b/assets/src/js/admin/main.js
index 5bced811..d67e36c6 100644
--- a/assets/src/js/admin/main.js
+++ b/assets/src/js/admin/main.js
@@ -15,8 +15,6 @@ document.addEventListener('DOMContentLoaded', () => {
nonceElem: document.getElementById('_wpnonce'),
nonce: '',
showWizardElem: document.getElementById('show_wizard'),
- domainNameElem: document.getElementById('domain_name'),
- apiTokenElem: document.getElementById('api_token'),
createAPITokenElems: document.getElementsByClassName('plausible-create-api-token'),
buttonElems: document.getElementsByClassName('plausible-analytics-button'),
stepElems: document.getElementsByClassName('plausible-analytics-wizard-next-step'),
@@ -44,14 +42,6 @@ document.addEventListener('DOMContentLoaded', () => {
this.showWizardElem.addEventListener('click', this.showWizard);
}
- if (this.domainNameElem !== null) {
- this.domainNameElem.addEventListener('keyup', this.disableConnectButton);
- }
-
- if (this.apiTokenElem !== null) {
- this.apiTokenElem.addEventListener('keyup', this.disableConnectButton);
- }
-
if (this.createAPITokenElems.length > 0) {
for (let i = 0; i < this.createAPITokenElems.length; i++) {
this.createAPITokenElems[i].addEventListener('click', this.createAPIToken);
@@ -367,7 +357,7 @@ document.addEventListener('DOMContentLoaded', () => {
},
/**
- * Save value of input or text area to DB.
+ * Save the value of the input or text area to DB.
*
* @param e
*/
@@ -403,11 +393,11 @@ document.addEventListener('DOMContentLoaded', () => {
* @param e
*/
switchMultilangDomain: function (e) {
- const selectedDomain = e.target.value;
+ const selectedKey = e.target.value;
const pairs = document.querySelectorAll('.multilang-domain-pair');
pairs.forEach(function (pair) {
- if (pair.dataset.wpmlDomain === selectedDomain) {
+ if (pair.dataset.multilangKey === selectedKey) {
pair.classList.remove('hidden');
} else {
pair.classList.add('hidden');
@@ -554,13 +544,9 @@ document.addEventListener('DOMContentLoaded', () => {
return;
}
- button = document.getElementById('connect_plausible_analytics');
-
- if (button === null) {
- let slide_id = document.location.hash;
- button = document.querySelector(slide_id + ' .plausible-analytics-wizard-next-step');
- buttonIsHref = true;
- }
+ let slide_id = document.location.hash;
+ button = document.querySelector(slide_id + ' .plausible-analytics-wizard-next-step');
+ buttonIsHref = true;
if (button === null) {
return;
@@ -595,11 +581,6 @@ document.addEventListener('DOMContentLoaded', () => {
e.preventDefault();
let domainElem = document.querySelector('.multilang-domain-pair:not(.hidden) [id^="domain_name"]');
-
- if (domainElem === null) {
- domainElem = document.getElementById('domain_name');
- }
-
let domain = domainElem ? domainElem.value : '';
domain = domain.replaceAll('/', '%2F');
diff --git a/src/Admin/Settings/API.php b/src/Admin/Settings/API.php
index c3c1e743..8f485880 100644
--- a/src/Admin/Settings/API.php
+++ b/src/Admin/Settings/API.php
@@ -20,532 +20,333 @@ class API {
/**
* Admin Setting Fields.
*
+ * @var array
* @since 1.3.0
* @access public
- * @var array
*/
public $fields = [];
/**
* Slide IDs and Titles
*
- * @since v2.0.0
* @var string[] $slides
+ * @since v2.0.0
*/
private $slides = [];
/**
* Slide IDs and Descriptions
*
- * @since v2.0.0
* @var array $slides_description
+ * @since v2.0.0
*/
private $slides_description = [];
/**
- * Render Fields.
+ * Render Checkbox Field.
*
* @since 1.3.0
* @access public
- * @return void
+ * @return string
*/
- public function settings_page() {
- wp_nonce_field( 'plausible_analytics_toggle_option' );
-
- $settings = Helpers::get_settings();
- $followed_wizard = get_option( 'plausible_analytics_wizard_done' ) || ! empty( $settings['self_hosted_domain'] );
-
- /**
- * On-boarding wizard.
- */
- if ( ! $followed_wizard ) {
- $this->slides = [
- 'welcome' => __( 'Welcome to Plausible Analytics', 'plausible-analytics' ),
- 'domain_name' => __( 'Confirm domain', 'plausible-analytics' ),
- 'api_token' => __( 'Create Plugin Token', 'plausible-analytics' ),
- 'enable_analytics_dashboard' => __( 'View the stats in your WP dashboard', 'plausible-analytics' ),
- 'enhanced_measurements' => __( 'Enhanced measurements', 'plausible-analytics' ),
- 'proxy_enabled' => __( 'Enable proxy', 'plausible-analytics' ),
- 'success' => __( 'Success!', 'plausible-analytics' ),
- ];
- $this->slides_description = [
- 'welcome' => sprintf(
- // translators: 1: URL to Plausible website, 2: URL to Plausible registration page.
- __(
- '
Plausible Analytics is an easy to use, open source, lightweight and privacy-friendly alternative to Google Analytics. We\'re super excited to have you on board!
To use our plugin, you need to register an account. To explore the product, we offer you a free 30-day trial. No credit card is required to sign up for the trial.
Already have an account? Please do follow the following steps to get the most out of your Plausible experience.
',
- 'plausible-analytics'
- ),
- 'https://plausible.io/?utm_source=WordPress&utm_medium=Referral&utm_campaign=WordPress+plugin',
- 'https://plausible.io/register?utm_source=WordPress&utm_medium=Referral&utm_campaign=WordPress+plugin'
- ),
- 'domain_name' => __(
- 'Confirm your domain name as you\'ve added it to your Plausible account.',
- 'plausible-analytics'
- ),
- 'api_token' => __(
- 'Create a Plugin Token (link opens in a new window) that we\'ll use to automate your setup process. Paste the Plugin Token in the field below and click "Next".',
- 'plausible-analytics'
- ),
- 'enable_analytics_dashboard' => __(
- 'Would you like to view your site\'s stats in your WordPress dashboard?',
- 'plausible-analytics'
- ),
- 'enhanced_measurements' => __( 'Enable enhanced measurements to automatically track actions that visitors take on your site.', 'plausible-analytics' ),
- 'proxy_enabled' => __(
- 'Run our script as a first party connection from your domain name to count visitors who use ad blockers',
- 'plausible-analytics'
- ),
- 'success' => sprintf(
- // translators: 1: URL to Plausible statistics dashboard, 2: URL to plugin settings, 3: URL to Plausible documentation, 4: URL to Plausible contact.
- __(
- '
Note that visits from logged in users aren\'t tracked. If you want to track visits for certain user roles, then please specify them in the plugin\'s settings.
Need help? Our documentation is the best place to find most answers right away.
Still haven\'t found the answer you\'re looking for? We\'re here to help. Please contact our support.
Congrats! Your traffic is now being counted without compromising the user experience and privacy of your visitors.
Note that visits from logged in users aren\'t tracked. If you want to track visits for certain user roles, then please specify them in the plugin\'s settings.
Need help? Our documentation is the best place to find most answers right away.
Still haven\'t found the answer you\'re looking for? We\'re here to help. Please contact our support.
Plausible Analytics is an easy to use, open source, lightweight and privacy-friendly alternative to Google Analytics. We\'re super excited to have you on board!
To use our plugin, you need to register an account. To explore the product, we offer you a free 30-day trial. No credit card is required to sign up for the trial.
Already have an account? Please do follow the following steps to get the most out of your Plausible experience.
',
+ 'plausible-analytics'
+ ),
+ 'https://plausible.io/?utm_source=WordPress&utm_medium=Referral&utm_campaign=WordPress+plugin',
+ 'https://plausible.io/register?utm_source=WordPress&utm_medium=Referral&utm_campaign=WordPress+plugin'
+ ),
+ 'domain_name' => __(
+ 'Confirm your domain name as you\'ve added it to your Plausible account.',
+ 'plausible-analytics'
+ ),
+ 'api_token' => __(
+ 'Create a Plugin Token (link opens in a new window) that we\'ll use to automate your setup process. Paste the Plugin Token in the field below and click "Next".',
+ 'plausible-analytics'
+ ),
+ 'enable_analytics_dashboard' => __(
+ 'Would you like to view your site\'s stats in your WordPress dashboard?',
+ 'plausible-analytics'
+ ),
+ 'enhanced_measurements' => __( 'Enable enhanced measurements to automatically track actions that visitors take on your site.', 'plausible-analytics' ),
+ 'proxy_enabled' => __(
+ 'Run our script as a first party connection from your domain name to count visitors who use ad blockers',
+ 'plausible-analytics'
+ ),
+ 'success' => sprintf(
+ // translators: 1: URL to Plausible statistics dashboard, 2: URL to plugin settings, 3: URL to Plausible documentation, 4: URL to Plausible contact.
+ __(
+ '
Note that visits from logged in users aren\'t tracked. If you want to track visits for certain user roles, then please specify them in the plugin\'s settings.
Need help? Our documentation is the best place to find most answers right away.
Still haven\'t found the answer you\'re looking for? We\'re here to help. Please contact our support.
Congrats! Your traffic is now being counted without compromising the user experience and privacy of your visitors.
Note that visits from logged in users aren\'t tracked. If you want to track visits for certain user roles, then please specify them in the plugin\'s settings.
Need help? Our documentation is the best place to find most answers right away.
Still haven\'t found the answer you\'re looking for? We\'re here to help. Please contact our support.