Matomo tracking

This commit is contained in:
Gerrit Linnemann 2019-03-24 17:26:26 +01:00
parent 0e6ec9e0fb
commit df74cb23c0
10 changed files with 415 additions and 19 deletions

View File

@ -30,9 +30,9 @@ exports.mail = function(data) {
let mailOptions = { let mailOptions = {
from: extractFrom(data), // sender address from: extractFrom(data), // sender address
to: app.get('CONF').mail.request.to, // comma separated list of receivers to: app.get('CONF').mail.request.to, // comma separated list of receivers
subject: "Equipment Anfrage", // Subject line subject: "Equipment Anfrage: " + data.title, // Subject line
text: "Hello world?", // plain text body text: JSON.stringify(data), // plain text body
html: "<b>Hello world?</b>" // html body html: JSON.stringify(data) // html body
}; };
let info = transporter.sendMail(mailOptions) let info = transporter.sendMail(mailOptions)

View File

@ -0,0 +1,23 @@
MIT License
Copyright 2014-2017 Frederic Hemberger
Copyright 2018 Frederic Hemberger, Matomo Team
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@ -0,0 +1,70 @@
# Matomo Tracker [![NPM version][npm-image]][npm-url] [![Build Status][travis-image]][travis-url]
> A wrapper for the Matomo Tracking HTTP API
## Usage
First, install `matomo-tracker` as a dependency:
```shell
npm install --save matomo-tracker
```
Then, use it in your project:
```javascript
var MatomoTracker = require('matomo-tracker');
// Initialize with your site ID and Matomo URL
var matomo = new MatomoTracker(1, 'http://mywebsite.com/matomo.php');
// Optional: Respond to tracking errors
matomo.on('error', function(err) {
console.log('error tracking request: ', err);
});
// Track a request URL:
// Either as a simple string …
matomo.track('http://example.com/track/this/url');
// … or provide further options:
matomo.track({
url: 'http://example.com/track/this/url',
action_name: 'This will be shown in your dashboard',
ua: 'Node.js v0.10.24',
cvar: JSON.stringify({
'1': ['custom variable name', 'custom variable value']
})
});
// … or trackBulk:
var events = [{
'_id': 'AA814767-7B1F-5C81-8F1D-8E47AD7D2982',
'cdt': '2018-03-22T02:32:22.867Z',
'e_c': 'Buy',
'e_a': 'rightButton',
'e_v': '2'
},{
'_id': 'AA814767-7B1F-5C81-8F1D-8E47AD7D2982',
'cdt': '2018-03-22T02:33:52.962Z',
'e_c': 'Buy',
'e_a': 'leftButton',
'e_v': '4'
}];
matomo.trackBulk(events, (resData) => {
// done.
})
```
That's it. For a complete list of options, see [Matomo's Tracking HTTP API Reference](https://developer.matomo.org/api-reference/tracking-api).
## License
[MIT License](http://en.wikipedia.org/wiki/MIT_License)
[npm-url]: https://npmjs.org/package/matomo-tracker
[npm-image]: https://img.shields.io/npm/v/matomo-tracker.svg
[travis-url]: https://travis-ci.org/matomo-org/matomo-nodejs-tracker
[travis-image]: https://img.shields.io/travis/matomo-org/matomo-nodejs-tracker.svg

View File

@ -0,0 +1,145 @@
/**
* A Node.js wrapper for the Matomo (http://matomo.org) tracking HTTP API
* https://github.com/matomo-org/matomo-tracker
*
* @author Frederic Hemberger, Matomo Team
* @license MIT
*/
'use strict';
const assert = require('assert');
const events = require('events');
const util = require('util');
const qs = require('querystring');
const url = require('url');
/**
* @constructor
* @param {Number} siteId Id of the site you want to track
* @param {String} trackerUrl URL of your Matomo instance
* @param {Boolean} [true] noURLValidation Set to true if the `piwik.php` has been renamed
*/
function MatomoTracker (siteId, trackerUrl, noURLValidation) {
if (!(this instanceof MatomoTracker)) {
return new MatomoTracker(siteId, trackerUrl, noURLValidation);
}
events.EventEmitter.call(this);
assert.ok(siteId && (typeof siteId === 'number' || typeof siteId === 'string'), 'Matomo siteId required.');
assert.ok(trackerUrl && typeof trackerUrl === 'string', 'Matomo tracker URL required, e.g. http://example.com/matomo.php');
if (!noURLValidation) {
assert.ok(trackerUrl.endsWith('matomo.php') || trackerUrl.endsWith('piwik.php'), 'A tracker URL must end with "matomo.php" or "piwik.php"');
}
this.siteId = siteId;
this.trackerUrl = trackerUrl;
// Use either HTTPS or HTTP agent according to Matomo tracker URL
this.agent = require(trackerUrl.startsWith('https') ? 'https' : 'http');
}
util.inherits(MatomoTracker, events.EventEmitter);
/**
* Executes the call to the Matomo tracking API
*
* For a list of tracking option parameters see
* https://developer.matomo.org/api-reference/tracking-api
*
* @param {(String|Object)} options URL to track or options (must contain URL as well)
*/
MatomoTracker.prototype.track = function track (options) {
var hasErrorListeners = this.listeners('error').length;
if (typeof options === 'string') {
options = {
url: options
};
}
// Set mandatory options
options = options || {};
options.idsite = this.siteId;
options.rec = 1;
assert.ok(options.url, 'URL to be tracked must be specified.');
var requestUrl = this.trackerUrl + '?' + qs.stringify(options);
var self = this;
var req = this.agent.get(requestUrl, function (res) {
// Check HTTP statuscode for 200 and 30x
if (!/^(200|30[12478])$/.test(res.statusCode)) {
if (hasErrorListeners) {
self.emit('error', res.statusCode);
}
}
});
req.on('error', function (err) {
hasErrorListeners && self.emit('error', err.message);
});
req.end();
};
MatomoTracker.prototype.trackBulk = function trackBulk (events, callback) {
var hasErrorListeners = this.listeners('error').length;
assert.ok(events && (events.length > 0), 'Events require at least one.');
assert.ok(this.siteId !== undefined && this.siteId !== null, 'siteId must be specified.');
var body = JSON.stringify({
requests: events.map(query => {
query.idsite = this.siteId;
query.rec = 1;
return '?' + qs.stringify(query);
})
});
var uri = url.parse(this.trackerUrl);
const requestOptions = {
protocol: uri.protocol,
hostname: uri.hostname,
port: uri.port,
path: uri.path,
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': Buffer.byteLength(body),
}
};
const req = this.agent.request(requestOptions, res => {
if (!/^(200|30[12478])$/.test(res.statusCode)) {
if (hasErrorListeners) {
this.emit('error', res.statusCode);
}
}
let data = [];
res.on('data', chunk => {
data.push(chunk);
});
res.on('end', () => {
data = Buffer.concat(data).toString();
typeof callback === 'function' && callback(data);
});
});
req.on('error', (err) => {
hasErrorListeners && this.emit('error', err.message);
}
);
req.write(body);
req.end();
};
module.exports = MatomoTracker;

View File

@ -0,0 +1,108 @@
{
"_args": [
[
{
"raw": "matomo-tracker",
"scope": null,
"escapedName": "matomo-tracker",
"name": "matomo-tracker",
"rawSpec": "",
"spec": "latest",
"type": "tag"
},
"/Users/gerrit/Documents/dev/nodejs/Dein.Equipment/html/Dein.Equipment"
]
],
"_from": "matomo-tracker@latest",
"_id": "matomo-tracker@2.2.0",
"_inCache": true,
"_location": "/matomo-tracker",
"_nodeVersion": "9.11.1",
"_npmOperationalInternal": {
"host": "s3://npm-registry-packages",
"tmp": "tmp/matomo-tracker_2.2.0_1523541623256_0.5041344136923325"
},
"_npmUser": {
"name": "lw1",
"email": "npm@lw1.at"
},
"_npmVersion": "5.8.0",
"_phantomChildren": {},
"_requested": {
"raw": "matomo-tracker",
"scope": null,
"escapedName": "matomo-tracker",
"name": "matomo-tracker",
"rawSpec": "",
"spec": "latest",
"type": "tag"
},
"_requiredBy": [
"#USER",
"/"
],
"_resolved": "https://registry.npmjs.org/matomo-tracker/-/matomo-tracker-2.2.0.tgz",
"_shasum": "f1064977a7e96e6737f213bf8503b5390aaccfe3",
"_shrinkwrap": null,
"_spec": "matomo-tracker",
"_where": "/Users/gerrit/Documents/dev/nodejs/Dein.Equipment/html/Dein.Equipment",
"author": {
"name": "Frederic Hemberger",
"url": "https://github.com/matomo-org"
},
"bugs": {
"url": "https://github.com/matomo-org/matomo-tracker/issues"
},
"dependencies": {},
"description": "A wrapper for the Matomo tracking HTTP API",
"devDependencies": {
"chai": "^4.1.2",
"eslint": "^4.19.1",
"mocha": "^5.0.5",
"nock": "^9.2.5",
"sinon": "^4.5.0",
"sinon-chai": "^3.0.0"
},
"directories": {},
"dist": {
"integrity": "sha512-kZIN4zRmuWRyG4S42kkMawMcsT6BQ/FYPK8IjeLNXAbN/CwPSlxlt7SdSyK/5k8F+S8nlmjXeUXf5SNFAXi8dA==",
"shasum": "f1064977a7e96e6737f213bf8503b5390aaccfe3",
"tarball": "https://registry.npmjs.org/matomo-tracker/-/matomo-tracker-2.2.0.tgz",
"fileCount": 4,
"unpackedSize": 7876
},
"engines": {
"node": ">=4.2.0"
},
"files": [
"index.js"
],
"gitHead": "ed888ba22fc542dccd95149940edc5e7ef203bbf",
"homepage": "https://github.com/matomo-org/matomo-tracker",
"keywords": [
"piwik",
"matomo",
"analytics",
"tracking"
],
"license": "MIT",
"maintainers": [
{
"name": "lw1",
"email": "npm@lw1.at"
}
],
"name": "matomo-tracker",
"optionalDependencies": {},
"readme": "ERROR: No README data found!",
"repository": {
"type": "git",
"url": "git://github.com/matomo-org/matomo-nodejs-tracker.git"
},
"scripts": {
"eslint": "eslint --max-warnings=0 index.js test/index.test.js",
"mocha": "mocha --reporter spec --exit",
"test": "npm run mocha && npm run eslint"
},
"version": "2.2.0"
}

View File

@ -18,6 +18,7 @@
"http-errors": "~1.6.2", "http-errors": "~1.6.2",
"jsonlint": "^1.6.3", "jsonlint": "^1.6.3",
"less-middleware": "~2.2.1", "less-middleware": "~2.2.1",
"matomo-tracker": "^2.2.0",
"morgan": "~1.9.0", "morgan": "~1.9.0",
"mysql": "^2.16.0", "mysql": "^2.16.0",
"nodemailer": "^5.1.1", "nodemailer": "^5.1.1",

View File

@ -4,6 +4,7 @@ $(function() {
initCookieInfo(); initCookieInfo();
initCookieAcceptButtonAction(); initCookieAcceptButtonAction();
initTooltips(); initTooltips();
initRequestForm();
}); });
@ -52,3 +53,15 @@ function initCookieAcceptButtonAction() {
$section.remove(); $section.remove();
}); });
} }
function initRequestForm() {
var $form = $('form.request');
var action = $form.attr('data-action-replacement');
var $submitBtn = $form.find('button[type="submit"]:first');
var buttonLabel = $form.attr('data-buttonlabel-replacement');
setTimeout(function() {
$form.attr('action', action);
$submitBtn.html(buttonLabel);
}, 3000);
}

View File

@ -1,4 +1,5 @@
var express = require('express'); var express = require('express');
var MatomoTracker = require('matomo-tracker');
var router = express.Router(); var router = express.Router();
/* GET home page */ /* GET home page */
@ -93,19 +94,36 @@ router.post('/request/', function(req, res, next) {
var app = req.app var app = req.app
var mailer = app.get('MAILER') var mailer = app.get('MAILER')
const paramStart = req.body.start const params = {
const paramEnd = req.body.end id: req.body.itemID,
const paramName = req.body.name title: req.body.itemTitle,
const paramContact = req.body.contact start: req.body.start,
end: req.body.end,
name: req.body.name,
contact: req.body.contact
}
mailer.mail({ mailer.mail(params)
name: paramName,
contact: paramContact, var fullUrl = req.protocol + '://' + req.get('host') + req.originalUrl;
start: paramStart, trackAtMatomo(app, fullUrl, 'Anfrage', params)
end: paramEnd
})
res.render('request', { title: 'Dein.Equipment: Anfrage gesendet' }) res.render('request', { title: 'Dein.Equipment: Anfrage gesendet' })
}) })
function trackAtMatomo(app, url, actionName, data) {
var matomo = new MatomoTracker(app.get('CONF').matomo.site.id, app.get('CONF').matomo.url)
matomo.on('error', function(err) {
app.get('LOG').error('Router | Error tracking request: ' + err);
})
matomo.track({
url: url,
action_name: actionName, // Action, shown on dashboard
ua: 'Dein.Equipment Backend', // UserAgend
data: JSON.stringify(data)
})
}
module.exports = router; module.exports = router;

View File

@ -19,7 +19,10 @@ block content
input(type="hidden", value=item.unavailableDates) input(type="hidden", value=item.unavailableDates)
.calendar .calendar
.col-sm .col-sm
form.request(action="/request/", method="post") form.request(action="/fuckyoubot/", method="post", data-action-replacement="/request/", data-buttonlabel-replacement="Anfrage senden")
input(type="hidden", name="itemID", value=item.id)
input(type="hidden", name="itemTitle", value=item.title)
h5 #{item.title} anfragen h5 #{item.title} anfragen
.form-group .form-group
.input-group .input-group
@ -47,4 +50,4 @@ block content
input(type="text", class="input-sm form-control", name="contact", placeholder="E-Mail oder Telefonnummer", data-toggle="tooltip", data-placement="top", title="Wie möchtest du von uns Antwort erhalten? Nenn uns deine Telefonnummer, oder deine E-Mail-Adresse.") input(type="text", class="input-sm form-control", name="contact", placeholder="E-Mail oder Telefonnummer", data-toggle="tooltip", data-placement="top", title="Wie möchtest du von uns Antwort erhalten? Nenn uns deine Telefonnummer, oder deine E-Mail-Adresse.")
.form-group .form-group
.input-group .input-group
button(type="submit", class="btn btn-primary btn-block", value="request") Anfrage button(type="submit", class="btn btn-primary btn-block", value="request") Bitte warten ...

View File

@ -40,3 +40,18 @@ html
script(src="/javascripts/moment.min.js", crossorigin="anonymous") script(src="/javascripts/moment.min.js", crossorigin="anonymous")
script(src="/javascripts/calendar.js", crossorigin="anonymous") script(src="/javascripts/calendar.js", crossorigin="anonymous")
script(src="/javascripts/actions.js", crossorigin="anonymous") script(src="/javascripts/actions.js", crossorigin="anonymous")
script.
// Matomo
var _paq = window._paq || [];
/* tracker methods like "setCustomDimension" should be called before "trackPageView" */
_paq.push(['trackPageView']);
_paq.push(['enableLinkTracking']);
(function() {
var u="//matomo.adawim.com/";
_paq.push(['setTrackerUrl', u+'matomo.php']);
_paq.push(['setSiteId', '2']);
var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
g.type='text/javascript'; g.async=true; g.defer=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s);
})();
// End Matomo Code