Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement Matomo Tag Manager Support #51

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 31 additions & 6 deletions Block/Matomo.php
Original file line number Diff line number Diff line change
Expand Up @@ -112,12 +112,37 @@ protected function _prepareTracker()
*/
public function getJsOptions()
{
return [
'scriptUrl' => $this->getScriptUrl(),
'trackerUrl' => $this->getTrackerUrl(),
'siteId' => $this->getSiteId(),
'actions' => $this->getTracker()->toArray()
];
if ($this->isContainerEnabled()) {
$result = [];
} else {
$result = [
'scriptUrl' => $this->getScriptUrl(),
'trackerUrl' => $this->getTrackerUrl(),
'siteId' => $this->getSiteId(),
];
}
$result['isContainerEnabled'] = $this->_dataHelper->isContainerEnabled();
$result['actions'] = $this->getTracker()->toArray();

return $result;
}

/**
* Check if Matomo Tag Manager Container is enabled
* @return string
*/
public function isContainerEnabled()
{
return $this->_dataHelper->isContainerEnabled();
}

/**
* Get Matomo Tag Manager Container URL
* @return string
*/
public function getContainerUrl()
{
return $this->_dataHelper->getContainerUrl();
}

/**
Expand Down
44 changes: 44 additions & 0 deletions Helper/Data.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ class Data extends \Magento\Framework\App\Helper\AbstractHelper
const XML_PATH_CDN_HOSTNAME = 'piwik/tracking/cdn_hostname';
const XML_PATH_JS_SCRIPT_PATH = 'piwik/tracking/js_script_path';
const XML_PATH_PHP_SCRIPT_PATH = 'piwik/tracking/php_script_path';
const XML_PATH_CONTAINER_ENABLED = 'piwik/tracking/container_enabled';
const XML_PATH_CONTAINER_SCRIPT_PATH = 'piwik/tracking/container_script_path';
const XML_PATH_SITE_ID = 'piwik/tracking/site_id';
const XML_PATH_LINK_ENABLED = 'piwik/tracking/link_enabled';
const XML_PATH_LINK_DELAY = 'piwik/tracking/link_delay';
Expand Down Expand Up @@ -151,6 +153,48 @@ public function getJsScriptPath($store = null)
)), '/') ?: 'matomo.js';
}

/**
* Retrieve Matomo Tag Manager JS container Url
*
* @param null|string|bool|int|Store $store
* @return string
*/
public function getContainerUrl($store = null, $secure = null)
{
return $this->getBaseUrl($store, $secure)
. $this->getContainerPath($store);
}

/**
* Retrieve Matomo Tag Manager JS container path
*
* @param null|string|bool|int|Store $store
* @return ?string
*/
public function getContainerPath($store = null)
{
return ltrim(trim($this->scopeConfig->getValue(
self::XML_PATH_CONTAINER_SCRIPT_PATH,
\Magento\Store\Model\ScopeInterface::SCOPE_STORE,
$store
)), '/') ?: null;
}

/**
* Retrieve Matomo Tag Manager JS container path
*
* @param null|string|bool|int|Store $store
* @return bool
*/
public function isContainerEnabled($store = null)
{
return boolval($this->scopeConfig->getValue(
self::XML_PATH_CONTAINER_ENABLED,
\Magento\Store\Model\ScopeInterface::SCOPE_STORE,
$store
) ?: false);
}

/**
* Retrieve Matomo tracker JS script URL
*
Expand Down
4 changes: 4 additions & 0 deletions Observer/BeforeTrackPageViewObserver.php
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,10 @@ public function execute(\Magento\Framework\Event\Observer $observer)
*/
protected function _pushLinkTracking(\Chessio\Matomo\Model\Tracker $tracker)
{
if ($this->_dataHelper->isContainerEnabled()) {
return $this;
}

if ($this->_dataHelper->isLinkTrackingEnabled()) {
$tracker->enableLinkTracking(true);
$delay = $this->_dataHelper->getLinkTrackingDelay();
Expand Down
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@ php bin/magento module:enable Chessio_Matomo --clear-static-content
Once installed, configuration options can be found in the Magento 2 administration panel under *Stores/Configuration/Sales/Matomo API*.
To start tracking, set *Enable Tracking* to *Yes*, enter the *Hostname* of your Matomo installation and click *Save Config*. If you have multiple websites in the same Matomo installation, make sure the *Site ID* configured in Magento is correct.

### Using Matomo Tag Manager

You can use the Matomo Tag Manager instead of Matomo directly. Set the configuration *Enable Matomo Tag Manager Container* to yes and set the *Container Script Path*.
For details on how to configure the Matomo Tag Manager, to track ecommerce events, see doc/tag-manager.md

## Customization

If you need to send some custom information to your Matomo server, Chessio_Matomo lets you do so using event observers.
Expand Down
44 changes: 44 additions & 0 deletions doc/tag-manager.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Using Matomo Tag Manager with the Matomo Magento 2 Module

This describes how you can set up the tag manager to track events through Matomo Ecommerce tracking.
Essentially, Ecommerce events generated by the Magento 2 module are forwarded to the Matomo events.

First make sure to set the configuration *Enable Matomo Tag Manager Container* to yes and set the *Container Script Path*.

## Configuring triggers

In the Matomo Tag manager container, configure all the necessary triggers.

Repeat the steps below for the four events

* `setEcommerceView`
* `addEcommerceItem`
* `trackEcommerceCartUpdate`
* `trackEcommerceOrder`

### Steps to configure each trigger event

1. Go to *Trigger*
2. Click create new trigger
3. Click custom event
4. Name and Event name should be the same

### Steps to configure the ecommerce tag

1. Go to *Tags*
2. Click *Create New Tag*
3. Choose *Custom HTML*
4. Name "Universal Ecommerce Tag for Matomo" (or choose your own)
5. HTML
```
<script>
window._paq = window._paq || [];
var parameters = {{parameters}};
var data = [{{customEventMatch}}].concat(parameters);
console.log(data);
window._paq.push(data);
</script>
```

6. *Configure when the tag should do this*, choose all the events from above, one by one
7. Save tag
27 changes: 27 additions & 0 deletions etc/adminhtml/system.xml
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,30 @@
</depends>
<frontend_class>required-entry</frontend_class>
</field>
<field id="container_enabled"
translate="label"
type="select"
sortOrder="25"
showInDefault="1"
showInWebsite="1"
showInStore="1">
<label>Enable Matomo Tag Manager Container</label>
<source_model>Magento\Config\Model\Config\Source\Yesno</source_model>
</field>
<field id="container_script_path"
translate="label comment"
type="text"
sortOrder="27"
showInDefault="1"
showInWebsite="1"
showInStore="1">
<label>Container Script Path, relative to the hostname</label>
<comment>Example: js/container_abcDEFgh.js</comment>
<depends>
<field id="enabled">1</field>
<field id="container_enabled">1</field>
</depends>
</field>
<field id="site_id"
translate="label comment"
type="text"
Expand All @@ -76,6 +100,7 @@
<comment>Listed under Settings/Website in your Matomo administration panel</comment>
<depends>
<field id="enabled">1</field>
<field id="container_enabled">0</field>
</depends>
<frontend_class>required-entry validate-digits validate-zero-or-greater</frontend_class>
</field>
Expand All @@ -91,6 +116,7 @@
<comment>Enable tracking of outlinks and downloads</comment>
<depends>
<field id="enabled">1</field>
<field id="container_enabled">0</field>
</depends>
</field>
<field id="link_delay"
Expand All @@ -105,6 +131,7 @@
<depends>
<field id="enabled">1</field>
<field id="link_enabled">1</field>
<field id="container_enabled">0</field>
</depends>
<frontend_class>validate-digits validate-zero-or-greater</frontend_class>
</field>
Expand Down
2 changes: 2 additions & 0 deletions etc/config.xml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@
<uid_provider></uid_provider>
<php_script_path>matomo.php</php_script_path>
<js_script_path>matomo.js</js_script_path>
<container_enabled>0</container_enabled>
<container_script_path></container_script_path>
<cdn_hostname></cdn_hostname>
</tracking>
</piwik>
Expand Down
6 changes: 6 additions & 0 deletions view/frontend/layout/default.xml
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,11 @@
as="matomo.tracker"
template="matomo.phtml" />
</referenceContainer>
<referenceBlock name="head.additional">
<block class="Chessio\Matomo\Block\Matomo"
name="matomo.tag_manager"
as="matomo.tag_manager"
template="tag_manager.phtml" />
</referenceBlock>
</body>
</page>
12 changes: 10 additions & 2 deletions view/frontend/templates/matomo.phtml
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,12 @@
* You should have received a copy of the GNU Affero General Public License
* along with Chessio_Matomo. If not, see <http://www.gnu.org/licenses/>.
*/

?>
<?php /** @var \Chessio\Matomo\Block\Matomo $block */ ?>
<?php /** @var \Chessio\Matomo\Block\Matomo $block */
if ($block->isContainerEnabled()) {
return;
}
?>
<script type="text/x-magento-init">
<?= $block->jsonEncode([
'*' => [
Expand All @@ -34,6 +37,8 @@
// However that might cause the tracker script to miss the `DOMContentLoaded'
// event which breaks the link tracking feature.
?>

<!-- Matomo Analytics -->
<script type="text/javascript">
(function (w, d) {
w._paq = w._paq || [];
Expand All @@ -48,6 +53,8 @@
s.parentNode.insertBefore(g, s);
})(window, document);
</script>
<!-- End Matomo Analytics -->

<?php
// The following script is a workaround that prevents the checkout loader
// overlay from spinning indefinitely in cases where a browser plugin such as
Expand Down Expand Up @@ -84,6 +91,7 @@
});
})(require);
</script>

<noscript>
<p>
<img src="<?= $block->getTrackingPixelUrl(); ?>"
Expand Down
86 changes: 86 additions & 0 deletions view/frontend/templates/tag_manager.phtml
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
<?php
/**
* Copyright 2016-2018 Henrik Hedelund
* Copyright 2020 Falco Nogatz
*
* This file is part of Chessio_Matomo.
*
* Chessio_Matomo is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Chessio_Matomo is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Chessio_Matomo. If not, see <http://www.gnu.org/licenses/>.
*/
?>
<?php /** @var \Chessio\Matomo\Block\Matomo $block */
if (!$block->isContainerEnabled()) {
return;
}
?>
<script type="text/x-magento-init">
Comment on lines +24 to +27
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the original PR (that targeted the fork), @amenk wrote:

I am wondering if we could extract this, together with the workaround script, to a seperate template to avoid duplication

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what do you think? should we create an additional block (actually 2 additional blocks) or leave it like that?

<?= $block->jsonEncode([
'*' => [
'Chessio_Matomo/js/tracker' => $block->getJsOptions()
]
]); ?>
</script>
<?php
// The following script can be omitted in which case the
// `Chessio_Matomo/js/tracker' component will inject the tracker script instead.
// However that might cause the tracker script to miss the `DOMContentLoaded'
// event which breaks the link tracking feature.
?>
<!-- Matomo Tag Manager -->
<script type="text/javascript">
var _mtm = window._mtm = window._mtm || [];
_mtm.push({'mtm.startTime': (new Date().getTime()), 'event': 'mtm.Start'});
var d = document, g = d.createElement('script'), s = d.getElementsByTagName('script')[0];
g.type = 'text/javascript';
g.async = true;
g.src = '<?= $block->escapeJsQuote($block->getContainerUrl()); ?>';
s.parentNode.insertBefore(g, s);
</script>
<!-- End Matomo Tag Manager -->
<?php
// The following script is a workaround that prevents the checkout loader
// overlay from spinning indefinitely in cases where a browser plugin such as
// AdBlock stops the tracker JS component from loading. The loader indicator
// relies on require's module registry to decide when to hide itself so here we
// export a mocked version of the component if we get an `errback' from require.
// @see vendor/magento/module-checkout/view/frontend/web/js/checkout-loader.js
// @see lib/web/mage/requirejs/resolver.js
?>
<script type="text/javascript">
(function (require, undefined) {
'use strict';
var moduleName = 'Chessio_Matomo/js/tracker';
(require !== undefined) && require([moduleName], undefined, function (e) {
if (e.requireType === 'scripterror'
&& (e.requireModules && e.requireModules[0]) === moduleName
) {
require.undef(moduleName);
define(moduleName, function () {
var noop = function () { /* NoOp */ };
var error = function () {
throw new Error('Failed to load Matomo module');
};
var mock = {
createTracker: error,
getMatomo: error,
getTracker: error,
push: noop
};
mock[moduleName] = noop;
return mock;
});
}
});
})(require);
</script>
Loading