diff --git a/Template/Tag/MatomoTag.web.js b/Template/Tag/MatomoTag.web.js
index c6babf2e7..067b540eb 100644
--- a/Template/Tag/MatomoTag.web.js
+++ b/Template/Tag/MatomoTag.web.js
@@ -90,7 +90,7 @@
if (!parameters.matomoConfig || !parameters.matomoConfig.name) {
return;
}
-
+
// this is the matomoConfig variable name and the only way to differentiate two different tracker
// configurations
var variableName = parameters.matomoConfig.name;
@@ -98,6 +98,7 @@
// we need to fetch matomoConfig again in case some parameters changed meanwhile that are variables...
// eg userId might be a variable and it's value might be different now
var matomoConfig = parameters.get('matomoConfig', {});
+ var trackingEndpoint = matomoConfig.trackingEndpoint == 'custom' ? matomoConfig.trackingEndpointCustom : matomoConfig.trackingEndpoint;
var tracker;
// we make sure to not update jsonConfig even when the configured values change... otherwise we would create
// randomly too many trackers when eg userId changes meanwhile etc
@@ -109,7 +110,7 @@
lastIdSite = matomoConfig.idSite;
// but even two or more different configs for the same Matomo URL & idSite
lastMatomoUrl = getMatomoUrlFromConfig(matomoConfig);
- var trackerUrl = lastMatomoUrl + matomoConfig.trackingEndpoint;
+ var trackerUrl = lastMatomoUrl + trackingEndpoint;
if (matomoConfig.registerAsDefaultTracker) {
tracker = Piwik.addTracker(trackerUrl, matomoConfig.idSite);
} else {
@@ -131,6 +132,7 @@
if (matomoConfig.enableCrossDomainLinking) {
tracker.enableCrossDomainLinking();
+ tracker.setCrossDomainLinkingTimeout(matomoConfig.crossDomainLinkingTimeout);
}
if (matomoConfig.cookieSameSite) {
@@ -145,6 +147,9 @@
tracker.setCookiePath(matomoConfig.cookiePath);
}
+ if (matomoConfig.cookieNamePrefix) {
+ tracker.setCookieNamePrefix(matomoConfig.cookieNamePrefix);
+ }
if (matomoConfig.cookieDomain) {
tracker.setCookieDomain(matomoConfig.cookieDomain);
@@ -175,11 +180,22 @@
if (matomoConfig.disableAlwaysUseSendBeacon) {
tracker.disableAlwaysUseSendBeacon();
}
+
+ if (matomoConfig.forceRequestMethod) {
+ tracker.setRequestMethod(matomoConfig.requestMethod);
+ if(matomoConfig.requestMethod == 'POST'){
+ tracker.setRequestContentType(matomoConfig.requestContentType);
+ }
+ }
if (matomoConfig.enableLinkTracking) {
tracker.enableLinkTracking();
}
+ if (matomoConfig.enableFileTracking) {
+ tracker.enableFileTracking();
+ }
+
if (matomoConfig.requireConsent) {
tracker.requireConsent();
}
@@ -187,11 +203,25 @@
if (matomoConfig.enableDoNotTrack) {
tracker.setDoNotTrack(1);
}
+
+ if (matomoConfig.disablePerformanceTracking) {
+ tracker.disablePerformanceTracking();
+ }
+
+ if (typeof matomoConfig.appendToTrackingUrl === 'string' && matomoConfig.appendToTrackingUrl.length > 0) {
+ tracker.appendToTrackingUrl(matomoConfig.appendToTrackingUrl);
+ }
+
+ if(typeof matomoConfig.customRequestProcessing === 'function'
+ && matomoConfig.customRequestProcessing.length >= 1 ) {
+ tracker.setCustomRequestProcessing(matomoConfig.customRequestProcessing);
+ }
+
if (matomoConfig.enableJSErrorTracking) {
tracker.enableJSErrorTracking();
}
if (matomoConfig.enableHeartBeatTimer) {
- tracker.enableHeartBeatTimer();
+ tracker.enableHeartBeatTimer(matomoConfig.heartBeatTime);
}
if (matomoConfig.trackAllContentImpressions) {
tracker.trackAllContentImpressions();
@@ -223,7 +253,7 @@
var possiblyUpdatedMatomoUrl = getMatomoUrlFromConfig(matomoConfig);
if (possiblyUpdatedMatomoUrl && lastMatomoUrl !== possiblyUpdatedMatomoUrl) {
// might change each time this method is called
- tracker.setTrackerUrl(possiblyUpdatedMatomoUrl + matomoConfig.trackingEndpoint);
+ tracker.setTrackerUrl(possiblyUpdatedMatomoUrl + trackingEndpoint);
lastIdSite = possiblyUpdatedMatomoUrl;
}
@@ -250,10 +280,13 @@
var customUrl = parameters.get('customUrl');
if (customUrl) {
tracker.setCustomUrl(customUrl);
- }
+ }
if (matomoConfig.customCookieTimeOutEnable) {
tracker.setVisitorCookieTimeout(matomoConfig.customCookieTimeOut * 86400);
+ tracker.setReferralCookieTimeout(matomoConfig.referralCookieTimeOut * 86400);
+ tracker.setSessionCookieTimeout(matomoConfig.sessionCookieTimeOut * 60);
}
+
tracker.trackPageView();
} else if (trackingType === 'event') {
tracker.trackEvent(parameters.get('eventCategory'), parameters.get('eventAction'), parameters.get('eventName'), parameters.get('eventValue'));
@@ -278,7 +311,8 @@
}
var matomoUrl = getMatomoUrlFromConfig(matomoConfig);
- loadTracker(matomoUrl, matomoConfig.jsEndpoint);
+ var jsEndpoint = matomoConfig.jsEndpoint == 'custom' ? matomoConfig.jsEndpointCustom : matomoConfig.jsEndpoint;
+ loadTracker(matomoUrl, jsEndpoint);
};
};
})();
diff --git a/Template/Variable/CustomRequestProcessingVariable.php b/Template/Variable/CustomRequestProcessingVariable.php
new file mode 100644
index 000000000..9f46edded
--- /dev/null
+++ b/Template/Variable/CustomRequestProcessingVariable.php
@@ -0,0 +1,69 @@
+makeSetting('jsFunction', "function(request){ return request; }", FieldConfig::TYPE_STRING, function (FieldConfig $field) {
+ $field->title = Piwik::translate('TagManager_CustomRequestProcessingVariableJsFunctionTitle');
+ $field->description = Piwik::translate('TagManager_CustomRequestProcessingVariableJsFunctionDescription');
+ $field->uiControl = FieldConfig::UI_CONTROL_TEXTAREA;
+ $field->validators[] = new NotEmpty();
+ $field->validate = function ($value) {
+ $value = trim($value);
+ if (strpos($value, 'function(request){') !== 0) {
+ throw new \Exception('The value needs to start with "function(request){"');
+ }
+ };
+ $field->transform = function ($value) {
+ return trim($value);
+ };
+ }),
+ );
+ }
+
+ public function loadTemplate($context, $entity)
+ {
+ if (!empty($entity['parameters']['jsFunction'])) {
+ $function = rtrim(trim($entity['parameters']['jsFunction']), ';');
+
+ return '(function () { return function (parameters, TagManager) { this.get = function(){ return ' . $function . '; } ; } })();';
+ }
+ }
+
+ public function hasAdvancedSettings()
+ {
+ return false;
+ }
+}
diff --git a/Template/Variable/MatomoConfigurationVariable.php b/Template/Variable/MatomoConfigurationVariable.php
index 084e799e9..5ec408277 100644
--- a/Template/Variable/MatomoConfigurationVariable.php
+++ b/Template/Variable/MatomoConfigurationVariable.php
@@ -17,6 +17,7 @@
use Piwik\Validators\CharacterLength;
use Piwik\Validators\NotEmpty;
use Piwik\Validators\NumberRange;
+use Piwik\Plugins\TagManager\Validators\CustomRequestProcessing;
class MatomoConfigurationVariable extends BaseVariable
{
@@ -45,6 +46,7 @@ public function hasAdvancedSettings()
public function getParameters()
{
$idSite = Common::getRequestVar('idSite', 0, 'int');
+ $idContainer = Common::getRequestVar('idContainer', '', 'string');
$url = SettingsPiwik::getPiwikUrl();
if (SettingsPiwik::isHttpsForced()) {
@@ -96,15 +98,29 @@ public function getParameters()
$field->title = Piwik::translate('TagManager_MatomoConfigurationMatomoEnableLinkTrackingTitle');
$field->description = Piwik::translate('TagManager_MatomoConfigurationMatomoEnableLinkTrackingDescription');
}),
+ $this->makeSetting('enableFileTracking', false, FieldConfig::TYPE_BOOL, function (FieldConfig $field) {
+ $field->title = Piwik::translate('TagManager_MatomoConfigurationMatomoEnableFileTrackingTitle');
+ $field->description = Piwik::translate('TagManager_MatomoConfigurationMatomoEnableFileTrackingDescription');
+ }),
$this->makeSetting('enableCrossDomainLinking', false, FieldConfig::TYPE_BOOL, function (FieldConfig $field) {
$field->title = Piwik::translate('TagManager_MatomoConfigurationMatomoEnableCrossDomainLinkingTitle');
$field->description = Piwik::translate('TagManager_MatomoConfigurationMatomoEnableCrossDomainLinkingDescription');
}),
+ $this->makeSetting('crossDomainLinkingTimeout', '180', FieldConfig::TYPE_INT, function (FieldConfig $field) {
+ $field->title = Piwik::translate('TagManager_MatomoConfigurationMatomoCrossDomainLinkingTimeoutTitle');
+ $field->description = Piwik::translate('TagManager_MatomoConfigurationMatomoCrossDomainLinkingTimeoutDescription');
+ $field->condition = 'enableCrossDomainLinking';
+ $field->validators[] = new NumberRange($min = 1);
+ }),
$this->makeSetting('enableDoNotTrack', false, FieldConfig::TYPE_BOOL, function (FieldConfig $field) {
$field->title = Piwik::translate('TagManager_MatomoConfigurationMatomoEnableDoNotTrackTitle');
$field->description = Piwik::translate('TagManager_MatomoConfigurationMatomoEnableDoNotTrackDescription');
$field->inlineHelp = Piwik::translate('TagManager_MatomoConfigurationMatomoEnableDoNotTrackInlineHelp', array('', ''));
}),
+ $this->makeSetting('disablePerformanceTracking', false, FieldConfig::TYPE_BOOL, function (FieldConfig $field) {
+ $field->title = Piwik::translate('TagManager_MatomoConfigurationMatomoDisablePerformanceTrackingTitle');
+ $field->description = Piwik::translate('TagManager_MatomoConfigurationMatomoDisablePerformanceTrackingDescription');
+ }),
$this->makeSetting('enableJSErrorTracking', false, FieldConfig::TYPE_BOOL, function (FieldConfig $field) {
$field->title = Piwik::translate('TagManager_MatomoConfigurationMatomoEnableJSErrorTrackingTitle');
$field->description = Piwik::translate('TagManager_MatomoConfigurationMatomoEnableJSErrorTrackingDescription');
@@ -113,6 +129,12 @@ public function getParameters()
$field->title = Piwik::translate('TagManager_MatomoConfigurationMatomoEnableHeartBeatTimerTitle');
$field->description = Piwik::translate('TagManager_MatomoConfigurationMatomoEnableHeartBeatTimerDescription');
}),
+ $this->makeSetting('heartBeatTime', '15', FieldConfig::TYPE_INT, function (FieldConfig $field) {
+ $field->title = Piwik::translate('TagManager_MatomoConfigurationMatomoHeartBeatTimeTitle');
+ $field->description = Piwik::translate('TagManager_MatomoConfigurationMatomoHeartBeatTimeDescription');
+ $field->condition = 'enableHeartBeatTimer';
+ $field->validators[] = new NumberRange($min = 5);
+ }),
$this->makeSetting('trackAllContentImpressions', false, FieldConfig::TYPE_BOOL, function (FieldConfig $field) {
$field->title = Piwik::translate('TagManager_MatomoConfigurationMatomoTrackAllContentImpressionsTitle');
$field->description = Piwik::translate('TagManager_MatomoConfigurationMatomoTrackAllContentImpressionsDescription');
@@ -137,14 +159,26 @@ public function getParameters()
$field->condition = '!requireConsent && !disableCookies';
}),
$this->makeSetting('customCookieTimeOutEnable', false, FieldConfig::TYPE_BOOL, function (FieldConfig $field) {
- $field->title = Piwik::translate('TagManager_MatomoConfigurationMatomoCustomCookieTimeOutEnableTitle');
- $field->description = Piwik::translate('TagManager_MatomoConfigurationMatomoCustomCookieTimeOutEnableDescription');
+ $field->title = Piwik::translate('TagManager_MatomoConfigurationMatomoCustomCookieTimeOutsEnableTitle');
+ $field->description = Piwik::translate('TagManager_MatomoConfigurationMatomoCustomCookieTimeOutsEnableDescription');
$field->condition = '!disableCookies';
}),
$this->makeSetting('customCookieTimeOut', '393', FieldConfig::TYPE_INT, function (FieldConfig $field) {
- $field->title = Piwik::translate('TagManager_MatomoConfigurationMatomoCustomCookieTimeOutTitle');
- $field->description = Piwik::translate('TagManager_MatomoConfigurationMatomoCustomCookieTimeOutDescription');
- $field->condition = 'customCookieTimeOutEnable == true';
+ $field->title = Piwik::translate('TagManager_MatomoConfigurationMatomoVisitorCookieTimeOutTitle');
+ $field->description = Piwik::translate('TagManager_MatomoConfigurationMatomoVisitorCookieTimeOutDescription');
+ $field->condition = 'customCookieTimeOutEnable && !disableCookies';
+ $field->validators[] = new NumberRange($min = 1);
+ }),
+ $this->makeSetting('referralCookieTimeOut', '182', FieldConfig::TYPE_INT, function (FieldConfig $field) {
+ $field->title = Piwik::translate('TagManager_MatomoConfigurationMatomoReferralCookieTimeOutTitle');
+ $field->description = Piwik::translate('TagManager_MatomoConfigurationMatomoReferralCookieTimeOutDescription');
+ $field->condition = 'customCookieTimeOutEnable && !disableCookies';
+ $field->validators[] = new NumberRange($min = 1);
+ }),
+ $this->makeSetting('sessionCookieTimeOut', '30', FieldConfig::TYPE_INT, function (FieldConfig $field) {
+ $field->title = Piwik::translate('TagManager_MatomoConfigurationMatomoSessionCookieTimeOutTitle');
+ $field->description = Piwik::translate('TagManager_MatomoConfigurationMatomoSessionCookieTimeOutDescription');
+ $field->condition = 'customCookieTimeOutEnable && !disableCookies';
$field->validators[] = new NumberRange($min = 1);
}),
$this->makeSetting('setSecureCookie', false, FieldConfig::TYPE_BOOL, function (FieldConfig $field) {
@@ -160,6 +194,14 @@ public function getParameters()
return trim($value);
};
}),
+ $this->makeSetting('cookieNamePrefix', '_pk_', FieldConfig::TYPE_STRING, function (FieldConfig $field) {
+ $field->title = Piwik::translate('TagManager_MatomoConfigurationMatomoCookieNamePrefixTitle');
+ $field->description = Piwik::translate('TagManager_MatomoConfigurationMatomoCookieNamePrefixDescription');
+ $field->validators[] = new CharacterLength(1, 20);
+ $field->transform = function ($value) {
+ return trim($value);
+ };
+ }),
$this->makeSetting('cookiePath', '', FieldConfig::TYPE_STRING, function (FieldConfig $field) {
$field->title = Piwik::translate('TagManager_MatomoConfigurationMatomoCookiePathTitle');
$field->description = Piwik::translate('TagManager_MatomoConfigurationMatomoCookiePathDescription');
@@ -265,16 +307,16 @@ public function getParameters()
$field->uiControlAttributes['field1'] = $field1->toArray();
$field->uiControlAttributes['field2'] = $field2->toArray();
}),
- $this->makeSetting('bundleTracker', true, FieldConfig::TYPE_BOOL, function (FieldConfig $field) {
- $field->title = Piwik::translate('TagManager_MatomoConfigurationMatomoBundleTrackerTitle');
- $field->uiControl = FieldConfig::UI_CONTROL_CHECKBOX;
- $field->description = Piwik::translate('TagManager_MatomoConfigurationMatomoBundleTrackerDescription');
- }),
$this->makeSetting('registerAsDefaultTracker', true, FieldConfig::TYPE_BOOL, function (FieldConfig $field) {
$field->title = Piwik::translate('TagManager_MatomoConfigurationMatomoRegisterAsDefaultTrackerTitle');
$field->uiControl = FieldConfig::UI_CONTROL_CHECKBOX;
$field->description = Piwik::translate('TagManager_MatomoConfigurationMatomoRegisterAsDefaultTrackerDescription');
}),
+ $this->makeSetting('bundleTracker', true, FieldConfig::TYPE_BOOL, function (FieldConfig $field) {
+ $field->title = Piwik::translate('TagManager_MatomoConfigurationMatomoBundleTrackerTitle');
+ $field->uiControl = FieldConfig::UI_CONTROL_CHECKBOX;
+ $field->description = Piwik::translate('TagManager_MatomoConfigurationMatomoBundleTrackerDescription');
+ }),
$this->makeSetting('jsEndpoint', $jsEndpoint, FieldConfig::TYPE_STRING, function (FieldConfig $field) {
$field->title = Piwik::translate('TagManager_MatomoConfigurationMatomoJsEndpointTitle');
$field->uiControl = FieldConfig::UI_CONTROL_SINGLE_SELECT;
@@ -283,9 +325,19 @@ public function getParameters()
'piwik.js' => 'piwik.js',
'js/' => 'js/',
'js/tracker.php' => 'js/tracker.php',
+ 'custom' => Piwik::translate('TagManager_MatomoConfigurationMatomoJsEndpointCustom'),
);
$field->description = Piwik::translate('TagManager_MatomoConfigurationMatomoJsEndpointDescription');
+ $field->condition = '!bundleTracker';
+ }),
+ $matomoUrl = $this->makeSetting('jsEndpointCustom', 'custom.js', FieldConfig::TYPE_STRING, function (FieldConfig $field) {
+ $field->title = Piwik::translate('TagManager_MatomoConfigurationMatomoJsEndpointCustomTitle');
+ $field->description = Piwik::translate('TagManager_MatomoConfigurationMatomoJsEndpointCustomDescription');
+ $field->condition = '!bundleTracker && jsEndpoint == "custom"';
+ $field->transform = function ($value) {
+ return trim($value);
+ };
}),
$this->makeSetting('trackingEndpoint', $phpEndpoint, FieldConfig::TYPE_STRING, function (FieldConfig $field) {
$field->title = Piwik::translate('TagManager_MatomoConfigurationMatomoTrackingEndpointTitle');
@@ -295,10 +347,53 @@ public function getParameters()
'piwik.php' => 'piwik.php',
'js/' => 'js/',
'js/tracker.php' => 'js/tracker.php',
+ 'custom' => Piwik::translate('TagManager_MatomoConfigurationMatomoTrackingEndpointCustom'),
);
-
+
$field->description = Piwik::translate('TagManager_MatomoConfigurationMatomoTrackingEndpointDescription');
}),
+ $matomoUrl = $this->makeSetting('trackingEndpointCustom', 'custom.php', FieldConfig::TYPE_STRING, function (FieldConfig $field) {
+ $field->title = Piwik::translate('TagManager_MatomoConfigurationMatomoTrackingEndpointCustomTitle');
+ $field->description = Piwik::translate('TagManager_MatomoConfigurationMatomoTrackingEndpointCustomDescription');
+ $field->condition = 'trackingEndpoint == "custom"';
+ $field->transform = function ($value) {
+ return trim($value);
+ };
+ }),
+ $this->makeSetting('appendToTrackingUrl', '', FieldConfig::TYPE_STRING, function (FieldConfig $field) {
+ $field->title = Piwik::translate('TagManager_MatomoConfigurationMatomoAppendToTrackingUrlTitle');
+ $field->description = Piwik::translate('TagManager_MatomoConfigurationMatomoAppendToTrackingUrlDescription');
+ $field->customFieldComponent = self::FIELD_VARIABLE_COMPONENT;
+ }),
+ $this->makeSetting('forceRequestMethod', false, FieldConfig::TYPE_BOOL, function (FieldConfig $field) {
+ $field->title = Piwik::translate('TagManager_MatomoConfigurationMatomoForceRequestMethodTitle');
+ $field->description = Piwik::translate('TagManager_MatomoConfigurationMatomoForceRequestMethodDescription');
+ }),
+ $this->makeSetting('requestMethod', 'GET', FieldConfig::TYPE_STRING, function (FieldConfig $field) {
+ $field->title = Piwik::translate('TagManager_MatomoConfigurationMatomoRequestMethodTitle');
+ $field->uiControl = FieldConfig::UI_CONTROL_SINGLE_SELECT;
+ $field->availableValues = array(
+ 'GET' => 'GET',
+ 'POST' => 'POST'
+ );
+
+ $field->condition = 'forceRequestMethod';
+ $field->inlineHelp = Piwik::translate('TagManager_MatomoConfigurationMatomoRequestMethodInlineHelp', array('', '', '
'));
+ }),
+ $matomoUrl = $this->makeSetting('requestContentType', 'application/x-www-form-urlencoded; charset=UTF-8', FieldConfig::TYPE_STRING, function (FieldConfig $field) {
+ $field->title = Piwik::translate('TagManager_MatomoConfigurationMatomoRequestContentTypeTitle');
+ $field->description = Piwik::translate('TagManager_MatomoConfigurationMatomoRequestContentTypeDescription');
+ $field->condition = 'forceRequestMethod && requestMethod == "POST"';
+ $field->transform = function ($value) {
+ return trim($value);
+ };
+ }),
+ $this->makeSetting('customRequestProcessing', '', FieldConfig::TYPE_STRING, function (FieldConfig $field) use ($idSite, $idContainer) {
+ $field->title = Piwik::translate('TagManager_MatomoConfigurationMatomoCustomRequestProcessingTitle');
+ $field->description = Piwik::translate('TagManager_MatomoConfigurationMatomoCustomRequestProcessingDescription', Piwik::translate('TagManager_CustomRequestProcessingVariableName'));
+ $field->customFieldComponent = self::FIELD_VARIABLE_COMPONENT;
+ $field->validators[] = new CustomRequestProcessing($idSite, $idContainer);
+ }),
);
$pluginParameters = [];
diff --git a/Updates/5.0.0-rc3.php b/Updates/5.0.0-rc3.php
new file mode 100644
index 000000000..2acd13ee2
--- /dev/null
+++ b/Updates/5.0.0-rc3.php
@@ -0,0 +1,80 @@
+migration = $factory;
+ }
+
+ /**
+ * Return database migrations to be executed in this update.
+ *
+ * Database migrations should be defined here, instead of in `doUpdate()`, since this method is used
+ * in the `core:update` command when displaying the queries an update will run. If you execute
+ * migrations directly in `doUpdate()`, they won't be displayed to the user. Migrations will be executed in the
+ * order as positioned in the returned array.
+ *
+ * @param Updater $updater
+ * @return Migration\Db[]
+ */
+ public function getMigrations(Updater $updater)
+ {
+ return array(
+ );
+ }
+
+ /**
+ * Perform the incremental version update.
+ *
+ * This method should perform all updating logic. If you define queries in the `getMigrations()` method,
+ * you must call {@link Updater::executeMigrations()} here.
+ *
+ * @param Updater $updater
+ */
+ public function doUpdate(Updater $updater)
+ {
+ $updater->executeMigrations(__FILE__, $this->getMigrations($updater));
+
+ // Migrate the MatomoConfiguration type variables to all include the newly configured fields.
+ $migrator = new NewVariableParameterMigrator(MatomoConfigurationVariable::ID, 'heartBeatTime', 15);
+ $migrator->addField('referralCookieTimeOut', 182);
+ $migrator->addField('sessionCookieTimeOut', 30);
+ $migrator->addField('enableFileTracking', false);
+ $migrator->addField('crossDomainLinkingTimeout', 180);
+ $migrator->addField('cookieNamePrefix', '_pk_');
+ $migrator->addField('disablePerformanceTracking', false);
+ $migrator->addField('trackingEndpointCustom', 'custom.php');
+ $migrator->addField('jsEndpointCustom', 'custom.js');
+ $migrator->addField('appendToTrackingUrl', '');
+ $migrator->addField('forceRequestMethod', false);
+ $migrator->addField('requestMethod', 'GET');
+ $migrator->addField('requestContentType', 'application/x-www-form-urlencoded; charset=UTF-8');
+ $migrator->addField('customRequestProcessing', '');
+ $migrator->migrate();
+ }
+}
diff --git a/Validators/CustomRequestProcessing.php b/Validators/CustomRequestProcessing.php
new file mode 100644
index 000000000..325deb542
--- /dev/null
+++ b/Validators/CustomRequestProcessing.php
@@ -0,0 +1,58 @@
+idSite = $idSite;
+ $this->idContainer = $idContainer;
+ $this->container = StaticContainer::get('Piwik\Plugins\TagManager\Model\Container');
+ $this->variable = StaticContainer::get('Piwik\Plugins\TagManager\Model\Variable');
+ }
+
+ public function validate($value)
+ {
+ if (empty($value)) {
+ return;
+ }
+ $customRequestProcessingVariableName = Piwik::translate('TagManager_CustomRequestProcessingVariableName');
+ if (substr($value, 0, 2) != '{{' || substr($value, -2, 2) != '}}' || strlen($value) < 5) {
+ throw new Exception(Piwik::translate('TagManager_ErrorNotAnVariableOfTypeException', $customRequestProcessingVariableName));
+ }
+ $idContainerVersion = $this->container->getContainer($this->idSite, $this->idContainer)['draft']['idcontainerversion'];
+ $name = substr($value, 2, -2);
+ $target = $this->variable->findVariableByName($this->idSite, $idContainerVersion, $name);
+ if (!is_array($target) || $target['type'] != CustomRequestProcessingVariable::ID) {
+ throw new Exception(Piwik::translate('TagManager_ErrorNotAnVariableOfTypeException', $customRequestProcessingVariableName));
+ }
+ }
+
+}
diff --git a/lang/en.json b/lang/en.json
index e9b340637..7f7aa18d9 100644
--- a/lang/en.json
+++ b/lang/en.json
@@ -269,6 +269,8 @@
"CustomImageTagName": "Custom Image",
"CustomJsFunctionVariableDescription": "Executes a custom JavaScript function to retrieve the value.",
"CustomJsFunctionVariableName": "Custom JavaScript",
+ "CustomRequestProcessingVariableName": "Custom Request Processing Function",
+ "CustomRequestProcessingVariableDescription": "A custom function to use with a Matomo Tracker that can transform all tracking requests.",
"CustomVariables": "Custom variables",
"CustomizeTracking": "Customize Tracking",
"CustomizeTrackingTeaser": "Want to configure the Matomo tracking for this container? Here is a list of existing Matomo configurations in this container:",
@@ -369,6 +371,7 @@
"ErrorMessageVariableName": "Error Message",
"ErrorNameDuplicate": "This name is already in use.",
"ErrorNotAnArray": "\"%1$s\" has to be an array.",
+ "ErrorNotAnVariableOfTypeException": "Must be a variable of type \"%s\"!",
"ErrorPreviewReservedEnvironment": "The preview environment cannot be configured as it is a reserved environment",
"ErrorTriggerAtPositionXDoesNotExist": "The trigger \"%1$s\" at position \"%2$s\" does not exist.",
"ErrorTriggerNotRemovableAsInUse": "This trigger cannot be deleted as it is used in a tag. To remove this trigger, update any referenced tag first.",
@@ -536,15 +539,23 @@
"MatomoConfigurationMatomoIDSiteException": "The idSite can only include idSites and variables.",
"MatomoConfigurationMatomoEnableLinkTrackingTitle": "Enable Link Tracking",
"MatomoConfigurationMatomoEnableLinkTrackingDescription": "Enables the automatic download and outlink tracking.",
+ "MatomoConfigurationMatomoEnableFileTrackingTitle": "Enable File Tracking",
+ "MatomoConfigurationMatomoEnableFileTrackingDescription": "Enable tracking of file:// protocol actions. By default, the file:// protocol is not tracked.",
"MatomoConfigurationMatomoEnableCrossDomainLinkingTitle": "Enable Cross Domain Linking",
"MatomoConfigurationMatomoEnableCrossDomainLinkingDescription": "Enable this to accurately measure the same visitor across multiple domain names.",
+ "MatomoConfigurationMatomoCrossDomainLinkingTimeoutTitle": "Cross Domain Linking Timeout",
+ "MatomoConfigurationMatomoCrossDomainLinkingTimeoutDescription": "Set the cross domain linking timeout (in seconds). By default, the two visits across domains will be linked together when the link is clicked and the page is loaded within a 180 seconds timeout window.",
"MatomoConfigurationMatomoEnableDoNotTrackTitle": "Enable Do Not Track",
"MatomoConfigurationMatomoEnableDoNotTrackDescription": "Enable this feature to not track users who opt out of tracking using Mozilla's (proposed) Do Not Track setting",
+ "MatomoConfigurationMatomoDisablePerformanceTrackingTitle": "Disable Performance Tracking",
+ "MatomoConfigurationMatomoDisablePerformanceTrackingDescription": "Disables page performance tracking.",
"MatomoConfigurationMatomoEnableDoNotTrackInlineHelp": "%1$sNote: When enabled it sets _paq.push([\"setDoNotTrack\", true]); which will not send any tracking request when a visitor has DNT enabled unlike the \"DNT Matomo Setting\" which drops the request on the server when a visitor has DNT enabled.%2$s",
"MatomoConfigurationMatomoEnableJSErrorTrackingTitle": "Enable JavaScript Error Tracking",
"MatomoConfigurationMatomoEnableJSErrorTrackingDescription": "Enables the tracking of uncaught JavaScript errors as an event.",
"MatomoConfigurationMatomoEnableHeartBeatTimerTitle": "Enable HeartBeat Timer",
"MatomoConfigurationMatomoEnableHeartBeatTimerDescription": "Install a Heart beat timer that will regularly send requests to Matomo in order to better measure the time spent on the page.",
+ "MatomoConfigurationMatomoHeartBeatTimeTitle": "HeartBeat Time",
+ "MatomoConfigurationMatomoHeartBeatTimeDescription": "The time interval in seconds in which to send pings. Can not be lower then 5s.",
"MatomoConfigurationMatomoEnableFormAnalyticsTitle": "Enable Form Tracking",
"MatomoConfigurationMatomoEnableFormAnalyticsDescription": "Enables the tracking of forms.",
"MatomoConfigurationMatomoEnableFormAnalyticsInlineHelp": "%1$sNote: When disabled it will execute Matomo.FormAnalytics.disableFormAnalytics(); which will disable form tracking requests.%2$s",
@@ -559,16 +570,22 @@
"MatomoConfigurationMatomoDisableCookiesDescription": "Disables all first party cookies.",
"MatomoConfigurationMatomoRequireConsentTitle": "Require tracking consent",
"MatomoConfigurationMatomoRequireConsentDescription": "Track only when user gave tracking consent. In a consent screen you need to call \"window._paq=window._paq||[];window._paq.push(['rememberConsentGiven']);\" when the user gives consent.",
- "MatomoConfigurationMatomoCustomCookieTimeOutEnableTitle": "Enable custom visitor Cookie timeout",
- "MatomoConfigurationMatomoCustomCookieTimeOutEnableDescription": "Allows you to set a custom time in full days for the _pk_id cookie.",
- "MatomoConfigurationMatomoCustomCookieTimeOutTitle": "The pk_id expire time in full days",
- "MatomoConfigurationMatomoCustomCookieTimeOutDescription": "Timeout in full days. By default, the Matomo tracking cookie expires in 13 months (365 + 28 days) = 393 days.",
+ "MatomoConfigurationMatomoCustomCookieTimeOutsEnableTitle": "Enable Custom Cookie Timeouts",
+ "MatomoConfigurationMatomoCustomCookieTimeOutsEnableDescription": "Allows you to set custom timeouts for various cookies.",
+ "MatomoConfigurationMatomoVisitorCookieTimeOutTitle": "Visitor Cookie Timeout",
+ "MatomoConfigurationMatomoVisitorCookieTimeOutDescription": "Timeout of pk_id in full days. By default, the Matomo tracking cookie expires in 13 months (365 + 28 days) = 393 days.",
+ "MatomoConfigurationMatomoReferralCookieTimeOutTitle": "Referral Cookie Timeout",
+ "MatomoConfigurationMatomoReferralCookieTimeOutDescription": "Timeout of the referral cookie in full days. By default, the Matomo tracking cookie expires in 6 months = 182 days.",
+ "MatomoConfigurationMatomoSessionCookieTimeOutTitle": "Session Cookie Timeout",
+ "MatomoConfigurationMatomoSessionCookieTimeOutDescription": "Timeout of the session cookie in minutes.",
"MatomoConfigurationMatomoRequireCookieConsentTitle": "Require cookie consent",
"MatomoConfigurationMatomoRequireCookieConsentDescription": "Use cookies only if the user gave cookie consent, otherwise track the user without cookies. In a consent screen you need to call \"window._paq=window._paq||[];window._paq.push(['rememberCookieConsentGiven']);\" when the user gives consent for cookies.",
"MatomoConfigurationMatomoSetSecureCookieTitle": "Enable Secure Cookie",
"MatomoConfigurationMatomoSetSecureCookieDescription": "Enable the Secure cookie flag on all first party cookies. This should be used when your website is only available under HTTPS so that all tracking cookies are always sent over secure connection.",
"MatomoConfigurationMatomoCookieDomainTitle": "Cookie Domain",
"MatomoConfigurationMatomoCookieDomainInlineHelp": "The default is the current document domain. If your website can be visited for example at both www.example.com and example.com, you would use: \".example.com\" or \"*.example.com\". %1$sNote: The variable is only evaluated at the time when tracker is being created, make sure you have the variable defined before that.%2$s",
+ "MatomoConfigurationMatomoCookieNamePrefixTitle": "Cookie Name Prefix",
+ "MatomoConfigurationMatomoCookieNamePrefixDescription": "The name prefix of the cookies.",
"MatomoConfigurationMatomoCookiePathTitle": "Cookie Path",
"MatomoConfigurationMatomoCookiePathDescription": "When tracking many subdirectories in separate websites, the cookie path prevents the number of cookies to quickly increase and prevent browser from deleting some of the cookies. This ensures optimal data accuracy and improves performance for your users (fewer cookies are sent with each request).",
"MatomoConfigurationMatomoCookieSameSiteTitle": "Same Site Cookie",
@@ -591,8 +608,24 @@
"MatomoConfigurationMatomoRegisterAsDefaultTrackerDescription": "When enabled, the tracker will be registered as the default one for the website, and will receive all commands that get pushed into the global _paq variable. Useful if you want to use the tracker config from the container with your own _paq.push() JavaScript code.",
"MatomoConfigurationMatomoJsEndpointTitle": "Tracker Javascript Path",
"MatomoConfigurationMatomoJsEndpointDescription": "Here you can configure the source path of the Matomo Tracker JavaScript, if you are not using the \"Bundle Tracker\" option.",
+ "MatomoConfigurationMatomoJsEndpointCustom": "Custom",
+ "MatomoConfigurationMatomoJsEndpointCustomTitle": "Custom Tracker Javascript Path",
+ "MatomoConfigurationMatomoJsEndpointCustomDescription": "Here you can configure a non standard path to fetch the tracker from. Will be appended to the Matomo URL. Should not start with '/'. Keep in mind that, since this is non standard, you have to handle the requests there yourself!",
"MatomoConfigurationMatomoTrackingEndpointTitle": "Tracking Request Target Path",
"MatomoConfigurationMatomoTrackingEndpointDescription": "Here you can configure the target path for tracking requests.",
+ "MatomoConfigurationMatomoTrackingEndpointCustom": "Custom",
+ "MatomoConfigurationMatomoTrackingEndpointCustomTitle": "Custom Tracking Request Target Path",
+ "MatomoConfigurationMatomoTrackingEndpointCustomDescription": "Here you can configure a non standard path for tracking requests. Will be appended to the Matomo URL. Should not start with '/'. Keep in mind that, since this is non standard, you have to handle the requests there yourself!",
+ "MatomoConfigurationMatomoAppendToTrackingUrlTitle": "Append To Tracking Url",
+ "MatomoConfigurationMatomoAppendToTrackingUrlDescription": "Append a custom string to the end of the HTTP request to matomo.php? (or your selected respective tracking endpoint).",
+ "MatomoConfigurationMatomoForceRequestMethodTitle": "Force Request Method",
+ "MatomoConfigurationMatomoForceRequestMethodDescription": "Enables forcing the request method to either GET or POST.",
+ "MatomoConfigurationMatomoRequestMethodTitle": "Request Method",
+ "MatomoConfigurationMatomoRequestMethodInlineHelp": "To use the POST request method, either 1) the Matomo host is the same as the tracked website host (Matomo installed in the same domain as your tracked website), or 2) if Matomo is not installed on the same host as your website, you need to enable CORS (Cross domain requests) as explained in this %1$sFAQ%2$s. Keep in mind that when Matomo uses sendBeacon() for sending tracking requests (which is enabled by default), it will send data via POST. If you want Matomo to never send POST requests, you can use this method to force GET which will automatically disable sendBeacon.%3$s",
+ "MatomoConfigurationMatomoRequestContentTypeTitle": "Content-Type",
+ "MatomoConfigurationMatomoRequestContentTypeDescription": "Set request Content-Type header value for POST requests.",
+ "MatomoConfigurationMatomoCustomRequestProcessingTitle": "Custom Request Processing",
+ "MatomoConfigurationMatomoCustomRequestProcessingDescription": "Can be set to a variable of type \"%s\" to augment or override default request sending behaviour.",
"MatomoTagDescription": "Matomo is the leading open source analytics platform.",
"MatomoTagHelp": "This tag lets you track pageviews and events into your Matomo. You can customize the tracking to your needs.",
"MatomoTagName": "Matomo Analytics",
@@ -865,6 +898,8 @@
"CookieVariableUrlDecodeDescription": "If enabled, the value will be decoded",
"CustomJsFunctionVariableJsFunctionTitle": "JavaScript Function",
"CustomJsFunctionVariableJsFunctionDescription": "The value should start with \"function() { \" and end with \"return yourValue; }\". You have to define a function and return a value. We highly recommend to test the pasted JavaScript function to avoid JavaScript errors on your website.",
+ "CustomRequestProcessingVariableJsFunctionTitle": "JavaScript Function",
+ "CustomRequestProcessingVariableJsFunctionDescription": "The function will be called once the request (query parameters string) has been prepared, and before the request content is sent. If the return value evaluates to false, no request will be sent. Must start with \"function(request){\".",
"DataLayerVariableNameTitle": "Data Layer Variable Name",
"DataLayerVariableNameDescription": "The name of any variable that is stored within the dataLayer. In case you want to access the value of a nested object, you can access the value of an object by separating each property by a dot, for example \"object1.myPropertyOfObject1\".",
"DomElementVariableSelectionMethodDescription": "Select the way you want to identify the element you want to read the value from.",
@@ -920,4 +955,4 @@
"SiteWithoutDataMtmStep2": "If you would like to customize this container, visit the %1$sContainer Dashboard%2$s",
"SiteWithoutDataMtmStep3": "Copy the code below and paste it on every page of your website. We recommend pasting it immediately before the closing %1$s tag. %2$sLearn more%3$s."
}
-}
+}
\ No newline at end of file
diff --git a/tests/System/expected/test___TagManager.exportContainerVersion_site_default_container.xml b/tests/System/expected/test___TagManager.exportContainerVersion_site_default_container.xml
index 042213e3a..c9dc203fa 100644
--- a/tests/System/expected/test___TagManager.exportContainerVersion_site_default_container.xml
+++ b/tests/System/expected/test___TagManager.exportContainerVersion_site_default_container.xml
@@ -79,10 +79,14 @@
//example.com/piwik/tests/PHPUnit/proxy/
6
1
+ 0
0
+ 180
0
+ 0
0
0
+ 15
0
0
0
@@ -90,8 +94,11 @@
0
0
393
+ 182
+ 30
0
+ _pk_
Lax
0
@@ -102,10 +109,17 @@
- 1
1
+ 1
matomo.js
+ custom.js
matomo.php
+ custom.php
+
+ 0
+ GET
+ application/x-www-form-urlencoded; charset=UTF-8
+
diff --git a/tests/System/expected/test_webContext__TagManager.getAvailableVariableTypesInContext.xml b/tests/System/expected/test_webContext__TagManager.getAvailableVariableTypesInContext.xml
index d8b2e91f3..570e53f6a 100644
--- a/tests/System/expected/test_webContext__TagManager.getAvailableVariableTypesInContext.xml
+++ b/tests/System/expected/test_webContext__TagManager.getAvailableVariableTypesInContext.xml
@@ -484,6 +484,38 @@
Others
+
+ CustomRequestProcessing
+ Custom Request Processing Function
+ A custom function to use with a Matomo Tracker that can transform all tracking requests.
+ Others
+ plugins/TagManager/images/defaultIcon.svg
+
+ 9999
+
+ web
+
+ 0
+ 1
+
+
+ jsFunction
+ JavaScript Function
+ function(request){ return request; }
+ function(request){ return request; }
+ string
+ textarea
+
+
+
+ The function will be called once the request (query parameters string) has been prepared, and before the request content is sent. If the return value evaluates to false, no request will be sent. Must start with "function(request){".
+
+
+
+ 0
+
+
+
EtrackerConfiguration
EtrackerConfiguration
@@ -820,6 +852,22 @@
0
+
+ enableFileTracking
+ Enable File Tracking
+ 0
+ 0
+ boolean
+ checkbox
+
+
+
+ Enable tracking of file:// protocol actions. By default, the file:// protocol is not tracked.
+
+
+
+ 0
+
enableCrossDomainLinking
Enable Cross Domain Linking
@@ -836,6 +884,22 @@
0
+
+ crossDomainLinkingTimeout
+ Cross Domain Linking Timeout
+ 180
+ 180
+ integer
+ text
+
+
+
+ Set the cross domain linking timeout (in seconds). By default, the two visits across domains will be linked together when the link is clicked and the page is loaded within a 180 seconds timeout window.
+
+
+ enableCrossDomainLinking
+ 0
+
enableDoNotTrack
Enable Do Not Track
@@ -852,6 +916,22 @@
0
+
+ disablePerformanceTracking
+ Disable Performance Tracking
+ 0
+ 0
+ boolean
+ checkbox
+
+
+
+ Disables page performance tracking.
+
+
+
+ 0
+
enableJSErrorTracking
Enable JavaScript Error Tracking
@@ -884,6 +964,22 @@
0
+
+ heartBeatTime
+ HeartBeat Time
+ 15
+ 15
+ integer
+ text
+
+
+
+ The time interval in seconds in which to send pings. Can not be lower then 5s.
+
+
+ enableHeartBeatTimer
+ 0
+
trackAllContentImpressions
Track All Content Impressions
@@ -966,7 +1062,7 @@
customCookieTimeOutEnable
- Enable custom visitor Cookie timeout
+ Enable Custom Cookie Timeouts
0
0
boolean
@@ -974,7 +1070,7 @@
- Allows you to set a custom time in full days for the _pk_id cookie.
+ Allows you to set custom timeouts for various cookies.
!disableCookies
@@ -982,7 +1078,7 @@
customCookieTimeOut
- The pk_id expire time in full days
+ Visitor Cookie Timeout
393
393
integer
@@ -990,10 +1086,42 @@
- Timeout in full days. By default, the Matomo tracking cookie expires in 13 months (365 + 28 days) = 393 days.
+ Timeout of pk_id in full days. By default, the Matomo tracking cookie expires in 13 months (365 + 28 days) = 393 days.
- customCookieTimeOutEnable == true
+ customCookieTimeOutEnable && !disableCookies
+ 0
+
+
+ referralCookieTimeOut
+ Referral Cookie Timeout
+ 182
+ 182
+ integer
+ text
+
+
+
+ Timeout of the referral cookie in full days. By default, the Matomo tracking cookie expires in 6 months = 182 days.
+
+
+ customCookieTimeOutEnable && !disableCookies
+ 0
+
+
+ sessionCookieTimeOut
+ Session Cookie Timeout
+ 30
+ 30
+ integer
+ text
+
+
+
+ Timeout of the session cookie in minutes.
+
+
+ customCookieTimeOutEnable && !disableCookies
0
@@ -1032,6 +1160,22 @@
FieldVariableTemplate
+
+ cookieNamePrefix
+ Cookie Name Prefix
+ _pk_
+ _pk_
+ string
+ text
+
+
+
+ The name prefix of the cookies.
+
+
+
+ 0
+
cookiePath
Cookie Path
@@ -1203,8 +1347,8 @@
0
- bundleTracker
- Bundle Tracker
+ registerAsDefaultTracker
+ Register As Default Tracker
1
1
boolean
@@ -1212,15 +1356,15 @@
- By bundling the Matomo JavaScript tracker directly into the container it may improve the performance of your website as it reduces the number of needed requests. It is recommended to bundle the Matomo tracker because in most cases the tracker would otherwise be loaded in a separate request on page view anyway. Note: If you use two different Matomo configurations in one container, the setting of the first configuration used in the first Matomo Tag will be applied to all Matomo tags within one container.
+ When enabled, the tracker will be registered as the default one for the website, and will receive all commands that get pushed into the global _paq variable. Useful if you want to use the tracker config from the container with your own _paq.push() JavaScript code.
0
- registerAsDefaultTracker
- Register As Default Tracker
+ bundleTracker
+ Bundle Tracker
1
1
boolean
@@ -1228,7 +1372,7 @@
- When enabled, the tracker will be registered as the default one for the website, and will receive all commands that get pushed into the global _paq variable. Useful if you want to use the tracker config from the container with your own _paq.push() JavaScript code.
+ By bundling the Matomo JavaScript tracker directly into the container it may improve the performance of your website as it reduces the number of needed requests. It is recommended to bundle the Matomo tracker because in most cases the tracker would otherwise be loaded in a separate request on page view anyway. Note: If you use two different Matomo configurations in one container, the setting of the first configuration used in the first Matomo Tag will be applied to all Matomo tags within one container.
@@ -1248,11 +1392,28 @@
piwik.js
js/
js/tracker.php
+ Custom
Here you can configure the source path of the Matomo Tracker JavaScript, if you are not using the "Bundle Tracker" option.
-
+ !bundleTracker
+ 0
+
+
+ jsEndpointCustom
+ Custom Tracker Javascript Path
+ custom.js
+ custom.js
+ string
+ text
+
+
+
+ Here you can configure a non standard path to fetch the tracker from. Will be appended to the Matomo URL. Should not start with '/'. Keep in mind that, since this is non standard, you have to handle the requests there yourself!
+
+
+ !bundleTracker && jsEndpoint == "custom"
0
@@ -1269,6 +1430,7 @@
piwik.php
js/
js/tracker.php
+ Custom
Here you can configure the target path for tracking requests.
@@ -1276,6 +1438,113 @@
0
+
+ trackingEndpointCustom
+ Custom Tracking Request Target Path
+ custom.php
+ custom.php
+ string
+ text
+
+
+
+ Here you can configure a non standard path for tracking requests. Will be appended to the Matomo URL. Should not start with '/'. Keep in mind that, since this is non standard, you have to handle the requests there yourself!
+
+
+ trackingEndpoint == "custom"
+ 0
+
+
+ appendToTrackingUrl
+ Append To Tracking Url
+
+
+ string
+ text
+
+
+
+ Append a custom string to the end of the HTTP request to matomo.php? (or your selected respective tracking endpoint).
+
+
+
+ 0
+
+ TagManager
+ FieldVariableTemplate
+
+
+
+ forceRequestMethod
+ Force Request Method
+ 0
+ 0
+ boolean
+ checkbox
+
+
+
+ Enables forcing the request method to either GET or POST.
+
+
+
+ 0
+
+
+ requestMethod
+ Request Method
+ GET
+ GET
+ string
+ select
+
+
+
+ GET
+ POST
+
+
+ To use the POST request method, either 1) the Matomo host is the same as the tracked website host (Matomo installed in the same domain as your tracked website), or 2) if Matomo is not installed on the same host as your website, you need to enable CORS (Cross domain requests) as explained in this <a href="https://matomo.org/faq/how-to/faq_18694/" target="_blank" rel="noreferrer noopener">FAQ</a>. Keep in mind that when Matomo uses sendBeacon() for sending tracking requests (which is enabled by default), it will send data via POST. If you want Matomo to never send POST requests, you can use this method to force GET which will automatically disable sendBeacon.<br>
+
+ forceRequestMethod
+ 0
+
+
+ requestContentType
+ Content-Type
+ application/x-www-form-urlencoded; charset=UTF-8
+ application/x-www-form-urlencoded; charset=UTF-8
+ string
+ text
+
+
+
+ Set request Content-Type header value for POST requests.
+
+
+ forceRequestMethod && requestMethod == "POST"
+ 0
+
+
+ customRequestProcessing
+ Custom Request Processing
+
+
+ string
+ text
+
+
+
+ Can be set to a variable of type "Custom Request Processing Function" to augment or override default request sending behaviour.
+
+
+
+ 0
+
+ TagManager
+ FieldVariableTemplate
+
+