Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/matomo-org/matomo.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Giehl <stefan@matomo.org>2020-10-27 18:19:45 +0300
committerGitHub <noreply@github.com>2020-10-27 18:19:45 +0300
commiteb1543097d188c322b8470fea240fb62e39d01dd (patch)
tree542900fe35e0c24bb03fa1ea37326b34ec23259e /plugins
parent8f703bbc9d914d013c124d1e1d0f2ecd47d88ec4 (diff)
Adds possibility to force cookie less tracking (#16592)
* Add system and measurable setting to enable cookie less tracking * Never return a visitor id if cookieless tracking is forced * Adds custom tracker.js to prevent cookies * ignore exceptions * cache setting in site attributes for faster tracking * updates expected test files * ensure getVisitorId also works without idSite in request * fix js tests * store global cookie flag in config to avoid failures when building tracker js * use config instead of systemsetting * use a new event to update the tracker file * Fix handling in Request::getVisitorId() * improve setting descriptions * Revert "use config instead of systemsetting" This reverts commit 1fdfb6808415d2984726cedfe2644de31086f927. * Revert "store global cookie flag in config to avoid failures when building tracker js" This reverts commit 2587dbb851d3e44f2740e39c91af3213930cad6f. * code improvements * Reset storage to ensure it's not filled with invalid database objects * updates expected test files * Remove measurable setting again * move setting from systemsettings to ip anonymization settings * Show a warning if tracker file is not writable * updates expected test file * apply some review feedback * fix test * updates expected screenshot * apply review feedback * submodule update
Diffstat (limited to 'plugins')
-rw-r--r--plugins/CustomDimensions/tests/Integration/CustomDimensionsTest.php1
-rw-r--r--plugins/CustomJsTracker/CustomJsTracker.php3
-rw-r--r--plugins/CustomJsTracker/TrackingCode/JsTestPluginTrackerFiles.php5
-rw-r--r--plugins/PrivacyManager/API.php9
-rw-r--r--plugins/PrivacyManager/Config.php2
-rw-r--r--plugins/PrivacyManager/Controller.php8
-rw-r--r--plugins/PrivacyManager/PrivacyManager.php21
-rw-r--r--plugins/PrivacyManager/SystemSettings.php17
-rw-r--r--plugins/PrivacyManager/angularjs/anonymize-ip/anonymize-ip.controller.js1
-rw-r--r--plugins/PrivacyManager/lang/en.json4
-rw-r--r--plugins/PrivacyManager/templates/privacySettings.twig10
-rw-r--r--plugins/PrivacyManager/tests/Integration/PrivacyManagerConfigTest.php1
-rw-r--r--plugins/PrivacyManager/tests/UI/expected-screenshots/PrivacyManager_privacy_settings_default.png4
-rw-r--r--plugins/PrivacyManager/tracker.js35
-rw-r--r--plugins/PrivacyManager/tracker.min.js1
m---------plugins/QueuedTracking0
16 files changed, 110 insertions, 12 deletions
diff --git a/plugins/CustomDimensions/tests/Integration/CustomDimensionsTest.php b/plugins/CustomDimensions/tests/Integration/CustomDimensionsTest.php
index df738bf500..923ace94d7 100644
--- a/plugins/CustomDimensions/tests/Integration/CustomDimensionsTest.php
+++ b/plugins/CustomDimensions/tests/Integration/CustomDimensionsTest.php
@@ -133,6 +133,7 @@ class CustomDimensionsTest extends IntegrationTestCase
$logTable = new LogTable(CustomDimensions::SCOPE_CONVERSION);
$logTable->removeCustomDimension(1);
+ Cache::deleteTrackerCache();
$conversion = array();
diff --git a/plugins/CustomJsTracker/CustomJsTracker.php b/plugins/CustomJsTracker/CustomJsTracker.php
index 5a15fed2d9..9529498d1a 100644
--- a/plugins/CustomJsTracker/CustomJsTracker.php
+++ b/plugins/CustomJsTracker/CustomJsTracker.php
@@ -23,7 +23,8 @@ class CustomJsTracker extends Plugin
'PluginManager.pluginInstalled' => 'updateTracker',
'PluginManager.pluginUninstalled' => 'updateTracker',
'Updater.componentUpdated' => 'updateTracker',
- 'Controller.CoreHome.checkForUpdates.end' => 'updateTracker'
+ 'Controller.CoreHome.checkForUpdates.end' => 'updateTracker',
+ 'CustomJsTracker.updateTracker' => 'updateTracker'
);
}
diff --git a/plugins/CustomJsTracker/TrackingCode/JsTestPluginTrackerFiles.php b/plugins/CustomJsTracker/TrackingCode/JsTestPluginTrackerFiles.php
index 160fee1cc4..c30ab89f60 100644
--- a/plugins/CustomJsTracker/TrackingCode/JsTestPluginTrackerFiles.php
+++ b/plugins/CustomJsTracker/TrackingCode/JsTestPluginTrackerFiles.php
@@ -25,6 +25,11 @@ class JsTestPluginTrackerFiles extends PluginTrackerFiles
$trackerFiles = \_glob(PIWIK_DOCUMENT_ROOT . '/plugins/*/' . self::TRACKER_FILE);
foreach ($trackerFiles as $trackerFile) {
$pluginName = $this->getPluginNameFromFile($trackerFile);
+
+ if ($pluginName === 'PrivacyManager') {
+ continue; // ignore tracker.js of PrivacyManager, as it would disable Cookies
+ }
+
$dirs[$pluginName] = dirname($trackerFile) . '/';
}
return $dirs;
diff --git a/plugins/PrivacyManager/API.php b/plugins/PrivacyManager/API.php
index fe260abcd0..fe8940ed2e 100644
--- a/plugins/PrivacyManager/API.php
+++ b/plugins/PrivacyManager/API.php
@@ -150,7 +150,7 @@ class API extends \Piwik\Plugin\API
/**
* @internal
*/
- public function setAnonymizeIpSettings($anonymizeIPEnable, $maskLength, $useAnonymizedIpForVisitEnrichment, $anonymizeUserId = false, $anonymizeOrderId = false, $anonymizeReferrer = '')
+ public function setAnonymizeIpSettings($anonymizeIPEnable, $maskLength, $useAnonymizedIpForVisitEnrichment, $anonymizeUserId = false, $anonymizeOrderId = false, $anonymizeReferrer = '', $forceCookielessTracking = false)
{
Piwik::checkUserHasSuperUserAccess();
@@ -180,6 +180,13 @@ class API extends \Piwik\Plugin\API
$privacyConfig->anonymizeOrderId = (bool) $anonymizeOrderId;
}
+ if (false !== $forceCookielessTracking) {
+ $privacyConfig->forceCookielessTracking = (bool) $forceCookielessTracking;
+
+ // update tracker files
+ Piwik::postEvent('CustomJsTracker.updateTracker');
+ }
+
return true;
}
diff --git a/plugins/PrivacyManager/Config.php b/plugins/PrivacyManager/Config.php
index 597d4ef3c4..97a5c797eb 100644
--- a/plugins/PrivacyManager/Config.php
+++ b/plugins/PrivacyManager/Config.php
@@ -23,6 +23,7 @@ use Piwik\Tracker\Cache;
* anonymization is deactivated, this value is ignored. For IPv4/IPv6 addresses,
* valid values are the number of octets in IP address to mask (from 0 to 4).
* For IPv6 addresses 0..4 means that 0, 64, 80, 104 or all bits are masked.
+ * @property bool $forceCookielessTracking If enabled, Matomo will try to force tracking without cookies
* @property int $anonymizeUserId If enabled, it will pseudo anonymize the User ID
* @property int $anonymizeOrderId If enabled, it will anonymize the Order ID
* @property string $anonymizeReferrer Whether the referrer should be anonymized and how it much it should be anonymized
@@ -34,6 +35,7 @@ class Config
'ipAddressMaskLength' => array('type' => 'integer', 'default' => 2),
'doNotTrackEnabled' => array('type' => 'boolean', 'default' => true),
'ipAnonymizerEnabled' => array('type' => 'boolean', 'default' => true),
+ 'forceCookielessTracking' => array('type' => 'boolean', 'default' => false),
'anonymizeUserId' => array('type' => 'boolean', 'default' => false),
'anonymizeOrderId' => array('type' => 'boolean', 'default' => false),
'anonymizeReferrer' => array('type' => 'string', 'default' => ''),
diff --git a/plugins/PrivacyManager/Controller.php b/plugins/PrivacyManager/Controller.php
index eae662aeb2..6de9e89e07 100644
--- a/plugins/PrivacyManager/Controller.php
+++ b/plugins/PrivacyManager/Controller.php
@@ -19,8 +19,10 @@ use Piwik\Nonce;
use Piwik\Notification;
use Piwik\Option;
use Piwik\Piwik;
+use Piwik\Plugins\CustomJsTracker\File;
use Piwik\Plugins\LanguagesManager\LanguagesManager;
use Piwik\Scheduler\Scheduler;
+use Piwik\Tracker\TrackerCodeGenerator;
use Piwik\View;
/**
@@ -183,6 +185,11 @@ class Controller extends \Piwik\Plugin\ControllerAdmin
$view = new View('@PrivacyManager/privacySettings');
if (Piwik::hasUserSuperUserAccess()) {
+ $jsCodeGenerator = new TrackerCodeGenerator();
+ $file = new File(PIWIK_DOCUMENT_ROOT . '/' . $jsCodeGenerator->getJsTrackerEndpoint());
+
+ $view->trackerFileName = $jsCodeGenerator->getJsTrackerEndpoint();
+ $view->trackerWritable = $file->hasWriteAccess();
$view->deleteData = $this->getDeleteDataInfo();
$view->anonymizeIP = $this->getAnonymizeIPInfo();
$view->canDeleteLogActions = Db::isLockPrivilegeGranted();
@@ -329,6 +336,7 @@ class Controller extends \Piwik\Plugin\ControllerAdmin
$privacyConfig = new Config();
$anonymizeIP["enabled"] = IPAnonymizer::isActive();
$anonymizeIP["maskLength"] = $privacyConfig->ipAddressMaskLength;
+ $anonymizeIP["forceCookielessTracking"] = $privacyConfig->forceCookielessTracking;
$anonymizeIP["anonymizeOrderId"] = $privacyConfig->anonymizeOrderId;
$anonymizeIP["anonymizeUserId"] = $privacyConfig->anonymizeUserId;
$anonymizeIP["useAnonymizedIpForVisitEnrichment"] = $privacyConfig->useAnonymizedIpForVisitEnrichment;
diff --git a/plugins/PrivacyManager/PrivacyManager.php b/plugins/PrivacyManager/PrivacyManager.php
index 58712c9fa0..46bbc5d64d 100644
--- a/plugins/PrivacyManager/PrivacyManager.php
+++ b/plugins/PrivacyManager/PrivacyManager.php
@@ -186,7 +186,8 @@ class PrivacyManager extends Plugin
'Translate.getClientSideTranslationKeys' => 'getClientSideTranslationKeys',
'Template.pageFooter' => 'renderPrivacyPolicyLinks',
'Db.getTablesInstalled' => 'getTablesInstalled',
- 'Visualization.beforeRender' => 'onConfigureVisualisation'
+ 'Visualization.beforeRender' => 'onConfigureVisualisation',
+ 'CustomJsTracker.shouldAddTrackerFile' => 'shouldAddTrackerFile'
);
}
@@ -741,4 +742,22 @@ class PrivacyManager extends Plugin
return false;
}
+
+ public function shouldAddTrackerFile(&$shouldAdd, $pluginName)
+ {
+ if ($pluginName === 'PrivacyManager') {
+ $shouldAdd = self::isCookieLessTrackingForced();
+ }
+ }
+
+ /**
+ * Returns if cookie less tracking is forced
+ *
+ * @return bool
+ */
+ public static function isCookieLessTrackingForced()
+ {
+ $config = new Config();
+ return !!$config->forceCookielessTracking;
+ }
}
diff --git a/plugins/PrivacyManager/SystemSettings.php b/plugins/PrivacyManager/SystemSettings.php
index 6978f2068b..d64a116d3a 100644
--- a/plugins/PrivacyManager/SystemSettings.php
+++ b/plugins/PrivacyManager/SystemSettings.php
@@ -8,8 +8,11 @@
*/
namespace Piwik\Plugins\PrivacyManager;
+use Piwik\Container\StaticContainer;
+use Piwik\Log;
use Piwik\Piwik;
-use Piwik\Settings\Setting;
+use Piwik\Plugin\Manager;
+use Piwik\Settings\Plugin\SystemSetting;
use Piwik\Settings\FieldConfig;
/**
@@ -17,13 +20,13 @@ use Piwik\Settings\FieldConfig;
*/
class SystemSettings extends \Piwik\Settings\Plugin\SystemSettings
{
- /** @var Setting */
+ /** @var SystemSetting */
public $privacyPolicyUrl;
- /** @var Setting */
+ /** @var SystemSetting */
public $termsAndConditionUrl;
- /** @var Setting */
+ /** @var SystemSetting */
public $showInEmbeddedWidgets;
protected function init()
@@ -33,7 +36,7 @@ class SystemSettings extends \Piwik\Settings\Plugin\SystemSettings
$this->showInEmbeddedWidgets = $this->createShowInEmbeddedWidgetsSetting();
}
- private function createPrivacyPolicyUrlSetting()
+ private function createPrivacyPolicyUrlSetting(): SystemSetting
{
return $this->makeSetting('privacyPolicyUrl', $default = '', FieldConfig::TYPE_STRING, function (FieldConfig $field) {
$field->title = Piwik::translate('PrivacyManager_PrivacyPolicyUrl');
@@ -43,7 +46,7 @@ class SystemSettings extends \Piwik\Settings\Plugin\SystemSettings
});
}
- private function createTermsAndConditionUrlSetting()
+ private function createTermsAndConditionUrlSetting(): SystemSetting
{
return $this->makeSetting('termsAndConditionUrl', $default = '', FieldConfig::TYPE_STRING, function (FieldConfig $field) {
$field->title = Piwik::translate('PrivacyManager_TermsAndConditionUrl');
@@ -53,7 +56,7 @@ class SystemSettings extends \Piwik\Settings\Plugin\SystemSettings
});
}
- private function createShowInEmbeddedWidgetsSetting()
+ private function createShowInEmbeddedWidgetsSetting(): SystemSetting
{
return $this->makeSetting('showInEmbeddedWidgets', $default = false, FieldConfig::TYPE_BOOL, function (FieldConfig $field) {
$field->title = Piwik::translate('PrivacyManager_ShowInEmbeddedWidgets');
diff --git a/plugins/PrivacyManager/angularjs/anonymize-ip/anonymize-ip.controller.js b/plugins/PrivacyManager/angularjs/anonymize-ip/anonymize-ip.controller.js
index 27739a0ccd..cc14920c72 100644
--- a/plugins/PrivacyManager/angularjs/anonymize-ip/anonymize-ip.controller.js
+++ b/plugins/PrivacyManager/angularjs/anonymize-ip/anonymize-ip.controller.js
@@ -22,6 +22,7 @@
anonymizeIPEnable: this.enabled ? '1' : '0',
anonymizeUserId: this.anonymizeUserId ? '1' : '0',
anonymizeOrderId: this.anonymizeOrderId ? '1' : '0',
+ forceCookielessTracking: this.forceCookielessTracking ? '1' : '0',
anonymizeReferrer: this.anonymizeReferrer ? this.anonymizeReferrer : '',
maskLength: this.maskLength,
useAnonymizedIpForVisitEnrichment: parseInt(this.useAnonymizedIpForVisitEnrichment, 10) ? '1' : '0'
diff --git a/plugins/PrivacyManager/lang/en.json b/plugins/PrivacyManager/lang/en.json
index 6846447207..f54dea529b 100644
--- a/plugins/PrivacyManager/lang/en.json
+++ b/plugins/PrivacyManager/lang/en.json
@@ -83,6 +83,10 @@
"DoNotTrack_SupportDNTPreference": "Support Do Not Track preference",
"EstimatedDBSizeAfterPurge": "Estimated database size after purge",
"EstimatedSpaceSaved": "Estimated space saved",
+ "ForceCookielessTracking": "Force tracking without cookies",
+ "ForceCookielessTrackingDescription": "Enabling this option will automatically update %1$s, so it contains some additional code to ensure all trackers won't use cookies. Additionally Matomo will ignore all tracking cookies on server side.",
+ "ForceCookielessTrackingDescription2": "Cookies will be disabled even when using the consent methods in Matomo tracker and calling for example the cookie consent methods won't enable cookies.",
+ "ForceCookielessTrackingDescriptionNotWritable": "The JS tracker file \"%1$s\" is not writable which is required for this feature to fully work. When the JS tracker file is not writable, then the cookies will be only ignored on the server side but cookies might be still set in the browser. To solve this issue you or a system administrator need to change the file permissions so your webserver can change this file.",
"GeolocationAnonymizeIpNote": "Note: Geolocation will have approximately the same results with 1 byte anonymized. With 2 bytes or more, Geolocation will be inaccurate.",
"GDPR": "GDPR",
"GdprManager": "GDPR Manager",
diff --git a/plugins/PrivacyManager/templates/privacySettings.twig b/plugins/PrivacyManager/templates/privacySettings.twig
index 8c5515578a..a7609d77f7 100644
--- a/plugins/PrivacyManager/templates/privacySettings.twig
+++ b/plugins/PrivacyManager/templates/privacySettings.twig
@@ -56,6 +56,16 @@
inline-help="{{ 'PrivacyManager_AnonymizeOrderIdNote'|translate|e('html_attr') }}">
</div>
+ <div piwik-field uicontrol="checkbox" name="forceCookielessTracking"
+ ng-model="anonymizeIp.forceCookielessTracking"
+ data-title="{{ 'PrivacyManager_ForceCookielessTracking'|translate|e('html_attr') }}"
+ value="{{ anonymizeIP.forceCookielessTracking }}"
+ inline-help="{{ 'PrivacyManager_ForceCookielessTrackingDescription'|translate(trackerFileName)|e('html_attr') }}<br/><br/><em>{{ 'PrivacyManager_ForceCookielessTrackingDescription2'|translate|e('html_attr') }}</em>
+ {%- if not trackerWritable %}
+ <br /><br /><p class='alert-warning alert'>{{ 'PrivacyManager_ForceCookielessTrackingDescriptionNotWritable'|translate(trackerFileName)|e('html_attr') }}</p>
+ {% endif -%}">
+ </div>
+
<div piwik-field uicontrol="select" name="anonymizeReferrer"
ng-model="anonymizeIp.anonymizeReferrer"
options='{{ referrerAnonymizationOptions|json_encode|e('html_attr') }}'
diff --git a/plugins/PrivacyManager/tests/Integration/PrivacyManagerConfigTest.php b/plugins/PrivacyManager/tests/Integration/PrivacyManagerConfigTest.php
index 43527d09aa..f55105765c 100644
--- a/plugins/PrivacyManager/tests/Integration/PrivacyManagerConfigTest.php
+++ b/plugins/PrivacyManager/tests/Integration/PrivacyManagerConfigTest.php
@@ -114,6 +114,7 @@ class PrivacyManagerConfigTest extends IntegrationTestCase
'PrivacyManager.anonymizeOrderId' => false,
'PrivacyManager.anonymizeReferrer' => '',
'PrivacyManager.useAnonymizedIpForVisitEnrichment' => false,
+ 'PrivacyManager.forceCookielessTracking' => false,
);
$this->assertEquals($expected, $content);
diff --git a/plugins/PrivacyManager/tests/UI/expected-screenshots/PrivacyManager_privacy_settings_default.png b/plugins/PrivacyManager/tests/UI/expected-screenshots/PrivacyManager_privacy_settings_default.png
index 6a29a57fb9..ae71c0b0c2 100644
--- a/plugins/PrivacyManager/tests/UI/expected-screenshots/PrivacyManager_privacy_settings_default.png
+++ b/plugins/PrivacyManager/tests/UI/expected-screenshots/PrivacyManager_privacy_settings_default.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:964c62f6e55f8acb3fe0c95e86d843e463d6f6d8a5516b9f5d31d0e7c7784594
-size 506238
+oid sha256:a9328de47fe06bb50ffa0e433d6df9bb237a6460c82286041f8efd166f9b05df
+size 545035
diff --git a/plugins/PrivacyManager/tracker.js b/plugins/PrivacyManager/tracker.js
new file mode 100644
index 0000000000..5127619816
--- /dev/null
+++ b/plugins/PrivacyManager/tracker.js
@@ -0,0 +1,35 @@
+/**
+ * Matomo - free/libre analytics platform
+ *
+ * @link https://matomo.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ */
+
+(function () {
+
+ function init() {
+ if ('object' === typeof window && !window.Matomo) {
+ // Matomo is not defined yet
+ return;
+ }
+
+ // disable cookies and remove them when a tracker is created
+ window.Matomo.on('TrackerSetup', function(tracker) {
+ tracker.setCookieConsentGiven=function(){};
+ tracker.rememberCookieConsentGiven=function(){};
+ tracker.disableCookies();
+ });
+ }
+
+ if ('object' === typeof window.Matomo) {
+ init();
+ } else {
+ // tracker is loaded separately for sure
+ if ('object' !== typeof window.matomoPluginAsyncInit) {
+ window.matomoPluginAsyncInit = [];
+ }
+
+ window.matomoPluginAsyncInit.push(init);
+ }
+})(); \ No newline at end of file
diff --git a/plugins/PrivacyManager/tracker.min.js b/plugins/PrivacyManager/tracker.min.js
new file mode 100644
index 0000000000..2c1b21b8a7
--- /dev/null
+++ b/plugins/PrivacyManager/tracker.min.js
@@ -0,0 +1 @@
+(function(){function a(){if("object"===typeof window&&!window.Matomo){return}window.Matomo.on("TrackerSetup",function(b){b.setCookieConsentGiven=function(){};b.rememberCookieConsentGiven=function(){};b.disableCookies()})}if("object"===typeof window.Matomo){a()}else{if("object"!==typeof window.matomoPluginAsyncInit){window.matomoPluginAsyncInit=[]}window.matomoPluginAsyncInit.push(a)}})(); \ No newline at end of file
diff --git a/plugins/QueuedTracking b/plugins/QueuedTracking
-Subproject f179b9d6c715945f128d57a044a482c35ed9e07
+Subproject 1459505ed3388d6f4c82d80b6ff81edae209d8d