From aa9d124af848383b756129c79c0cd373406d2e9b Mon Sep 17 00:00:00 2001 From: sgiehl Date: Mon, 13 Jun 2022 15:10:44 +0200 Subject: [PATCH 1/2] Adds support for client hints --- MatomoTracker.php | 51 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/MatomoTracker.php b/MatomoTracker.php index bbac5e2..ac10b05 100644 --- a/MatomoTracker.php +++ b/MatomoTracker.php @@ -121,6 +121,14 @@ public function __construct($idSite, $apiUrl = '') $this->ip = !empty($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : false; $this->acceptLanguage = !empty($_SERVER['HTTP_ACCEPT_LANGUAGE']) ? $_SERVER['HTTP_ACCEPT_LANGUAGE'] : false; $this->userAgent = !empty($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : false; + $this->clientHints = []; + $this->setClientHints( + $_SERVER['HTTP_SEC_CH_UA_MODEL'] ?? '', + $_SERVER['HTTP_SEC_CH_UA_PLATFORM'] ?? '', + $_SERVER['HTTP_SEC_CH_UA_PLATFORM_VERSION'] ?? '', + $_SERVER['HTTP_SEC_CH_UA_FULL_VERSION_LIST'] ?? '', + $_SERVER['HTTP_SEC_CH_UA_FULL_VERSION'] ?? '' + ); if (!empty($apiUrl)) { self::$URL = $apiUrl; } @@ -482,6 +490,47 @@ public function setUserAgent($userAgent) return $this; } + /** + * Sets the client hints, used to detect OS and browser. + * If this function is not called, the client hints sent with the current request will be used. + * + * @param string $model Value of the header 'HTTP_SEC_CH_UA_MODEL' + * @param string $platform Value of the header 'HTTP_SEC_CH_UA_PLATFORM' + * @param string $platformVersion Value of the header 'HTTP_SEC_CH_UA_PLATFORM_VERSION' + * @param string|array $fullVersionList Value of header 'HTTP_SEC_CH_UA_FULL_VERSION_LIST' or an array containing + * all brands with the structure + * [['brand' => 'Chrome', 'version' => '10.0.2'], ['brand' => '...] + * @param string $uaFullVersion Value of the header 'HTTP_SEC_CH_UA_FULL_VERSION' + * + * @return $this + */ + public function setClientHints($model = '', $platform = '', $platformVersion = '', $fullVersionList = '', $uaFullVersion = '') + { + if (is_string($fullVersionList)) { + $reg = '/^"([^"]+)"; ?v="([^"]+)"(?:, )?/'; + $list = []; + + while (\preg_match($reg, $value, $matches)) { + $list[] = ['brand' => $matches[1], 'version' => $matches[2]]; + $value = \substr($value, \strlen($matches[0])); + } + + $fullVersionList = $list; + } elseif (!is_array($fullVersionList)) { + $fullVersionList = []; + } + + $this->clientHints = array_filter([ + 'model' => $model, + 'platform' => $platform, + 'platformVersion' => $platformVersion, + 'uaFullVersion' => $uaFullVersion, + 'fullVersionList' => $fullVersionList, + ]); + + return $this; + } + /** * Sets the country of the visitor. If not used, Matomo will try to find the country * using either the visitor's IP address or language. @@ -1702,6 +1751,7 @@ protected function sendRequest($url, $method = 'GET', $data = null, $force = fal $this->storedTrackingActions[] = $url . (!empty($this->userAgent) ? ('&ua=' . urlencode($this->userAgent)) : '') + . (!empty($this->clientHints) ? ('&uadata=' . urlencode(json_encode($this->clientHints))) : '') . (!empty($this->acceptLanguage) ? ('&lang=' . urlencode($this->acceptLanguage)) : ''); // Clear custom variables & dimensions so they don't get copied over to other users in the bulk request @@ -1709,6 +1759,7 @@ protected function sendRequest($url, $method = 'GET', $data = null, $force = fal $this->clearCustomDimensions(); $this->clearCustomTrackingParameters(); $this->userAgent = false; + $this->clientHints = false; $this->acceptLanguage = false; return true; From 9c2ff78634754012ea7f91992ba71ed44dafdd5c Mon Sep 17 00:00:00 2001 From: sgiehl Date: Tue, 21 Jun 2022 11:34:12 +0200 Subject: [PATCH 2/2] use code compatible with PHP 5.3 --- MatomoTracker.php | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/MatomoTracker.php b/MatomoTracker.php index ac10b05..d0840c2 100644 --- a/MatomoTracker.php +++ b/MatomoTracker.php @@ -123,11 +123,11 @@ public function __construct($idSite, $apiUrl = '') $this->userAgent = !empty($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : false; $this->clientHints = []; $this->setClientHints( - $_SERVER['HTTP_SEC_CH_UA_MODEL'] ?? '', - $_SERVER['HTTP_SEC_CH_UA_PLATFORM'] ?? '', - $_SERVER['HTTP_SEC_CH_UA_PLATFORM_VERSION'] ?? '', - $_SERVER['HTTP_SEC_CH_UA_FULL_VERSION_LIST'] ?? '', - $_SERVER['HTTP_SEC_CH_UA_FULL_VERSION'] ?? '' + !empty($_SERVER['HTTP_SEC_CH_UA_MODEL']) ? $_SERVER['HTTP_SEC_CH_UA_MODEL'] : '', + !empty($_SERVER['HTTP_SEC_CH_UA_PLATFORM']) ? $_SERVER['HTTP_SEC_CH_UA_PLATFORM'] : '', + !empty($_SERVER['HTTP_SEC_CH_UA_PLATFORM_VERSION']) ? $_SERVER['HTTP_SEC_CH_UA_PLATFORM_VERSION'] : '', + !empty($_SERVER['HTTP_SEC_CH_UA_FULL_VERSION_LIST']) ? $_SERVER['HTTP_SEC_CH_UA_FULL_VERSION_LIST'] : '', + !empty($_SERVER['HTTP_SEC_CH_UA_FULL_VERSION']) ? $_SERVER['HTTP_SEC_CH_UA_FULL_VERSION'] : '' ); if (!empty($apiUrl)) { self::$URL = $apiUrl; @@ -494,6 +494,8 @@ public function setUserAgent($userAgent) * Sets the client hints, used to detect OS and browser. * If this function is not called, the client hints sent with the current request will be used. * + * Supported as of Matomo 4.12.0 + * * @param string $model Value of the header 'HTTP_SEC_CH_UA_MODEL' * @param string $platform Value of the header 'HTTP_SEC_CH_UA_PLATFORM' * @param string $platformVersion Value of the header 'HTTP_SEC_CH_UA_PLATFORM_VERSION' @@ -510,9 +512,9 @@ public function setClientHints($model = '', $platform = '', $platformVersion = ' $reg = '/^"([^"]+)"; ?v="([^"]+)"(?:, )?/'; $list = []; - while (\preg_match($reg, $value, $matches)) { + while (\preg_match($reg, $fullVersionList, $matches)) { $list[] = ['brand' => $matches[1], 'version' => $matches[2]]; - $value = \substr($value, \strlen($matches[0])); + $fullVersionList = \substr($fullVersionList, \strlen($matches[0])); } $fullVersionList = $list; @@ -1751,7 +1753,6 @@ protected function sendRequest($url, $method = 'GET', $data = null, $force = fal $this->storedTrackingActions[] = $url . (!empty($this->userAgent) ? ('&ua=' . urlencode($this->userAgent)) : '') - . (!empty($this->clientHints) ? ('&uadata=' . urlencode(json_encode($this->clientHints))) : '') . (!empty($this->acceptLanguage) ? ('&lang=' . urlencode($this->acceptLanguage)) : ''); // Clear custom variables & dimensions so they don't get copied over to other users in the bulk request @@ -1953,6 +1954,9 @@ protected function getRequest($idSite) $customFields . $customDimensions . (!$this->sendImageResponse ? '&send_image=0' : '') . + // client hints + (!empty($this->clientHints) ? ('&uadata=' . urlencode(json_encode($this->clientHints))) : '') . + // DEBUG $this->DEBUG_APPEND_URL;