Commit d6f3e691 authored by Sebastian Castro's avatar Sebastian Castro
Browse files

matomo: adds matomo integration

parent 77c037ae
......@@ -70,3 +70,9 @@ SENTRY_DSN=
# Php path should be automatically detected, but if you encounter some trouble you can use following variable :
# PHP_PATH=/usr/bin/php
###> Matomo integration - see docs/matomo.md ###
MATOMO_URL=
MATOMO_SITE_ID=
MATOMO_USER_TOKEN=
###< Matomo ###
......@@ -7,5 +7,8 @@ import './js/admin/element-import/element-import'
import './js/admin/osm-tags'
import './js/admin/element-edit'
import './js/admin/source-priority'
import './js/admin/charts'
import './js/i18n'
<template>
<div class="matomo-visits">
<h4>{{ t('js.charts.title_visitors') }}</h4>
<div class="form-inline text-center">
<div class="form-group">
<label>{{ t('js.charts.display') }}</label>
<select class="form-control" v-model="field">
<option v-for="type in ['nb_visits', 'avg_time_on_page', ]" :key="type" :value="type">
{{ t(`js.charts.field.${type}`) }}
</option>
</select>
</div>
<div class="form-group">
<label>{{ t('js.charts.last') }}</label>
<input class="input-last form-control" type="number" v-model="lastCount"/>
<select class="form-control" v-model="period">
<option v-for="type in ['day', 'week', 'month', 'year']" :key="type" :value="type">
{{ t(`js.charts.period.${type}`) }}
</option>
</select>
</div>
<button type="button" class="btn btn-default" @click="loadData">{{ t('js.charts.reload') }}</button>
</div>
<div class="chart-container" ref="chartContainer">
<div class="loader"><i class="fa fa-spienner fa-spin"></i></div>
</div>
</div>
</template>
<script>
import Highcharts from 'highcharts'
export default {
props: ['baseUrl', 'siteId', 'token', 'projectUrl'],
data() {
return {
period: 'month',
lastCount: '12',
field: 'nb_visits',
data: []
}
},
computed: {
matomoUrl() {
return `${this.baseUrl}/index.php?module=API`+
`&method=Actions.getPageTitle`+
`&idSite=${this.siteId}`+
`&pageName=${this.projectUrl}`+ // we use the projectUrl as pageName in order to easily get stats for every project on saas instance
`&period=${this.period}`+
`&date=last${this.lastCount}`+
`&format=JSON`+
`&token_auth=${this.token}`
}
},
watch: {
field: function() {
this.drawData()
}
},
methods: {
loadData() {
$.getJSON(this.matomoUrl, (data) => {
this.data = data
this.drawData()
})
},
drawData() {
const chart = Highcharts.chart(this.$refs.chartContainer, {
chart: { type: 'spline' },
title: false,
xAxis: {
categories: Object.keys(this.data).map((el) => el)
},
yAxis: { title: false },
series: [{
name: t(`js.charts.field.${this.field}`),
data: Object.values(this.data).map((el) => el.length ? el[0][this.field] : 0)
}]
});
}
},
mounted() {
this.loadData()
}
}
</script>
<style lang="scss" scoped>
.matomo-visits {
background-color: white;
padding-top: 1rem;
margin-bottom: 2rem;
}
h4 {
text-align: center;
margin-bottom: 1.5rem;
color: black;
}
.input-last { width: 60px; }
.form-group {
margin-right: 1rem;
}
label {
font-weight: normal;
}
.loader {
padding: 50px 0;
text-align: center;
i { font-size: 30px; }
}
</style>
\ No newline at end of file
import Highcharts from 'highcharts'
// Make it availabel globally for the highcharts-bundle
window.Highcharts = Highcharts
import Vue from '../vendor/vue-custom'
import MatomoVisits from './MatomoVisits'
document.addEventListener('DOMContentLoaded', function() {
if ($('.matomo-visits-container').length > 0) {
new Vue({
el: '.matomo-visits-container',
components: { MatomoVisits }
})
}
})
\ No newline at end of file
......@@ -13,6 +13,9 @@ twig:
oauth_google: '%oauth_google_id%'
oauth_facebook: '%oauth_facebook_id%'
helper: '@App\Services\TwigHelperService'
matomo_url: '%env(MATOMO_URL)%'
matomo_site_id: '%env(MATOMO_SITE_ID)%'
matomo_token: '%env(MATOMO_USER_TOKEN)%'
paths:
"%kernel.root_dir%/../web": RootDir
form_themes:
......
......@@ -55,6 +55,11 @@ services:
arguments:
$rootDB: '%root_db%'
App\Services\TwigHelperService:
arguments:
$baseUrl: '%base_url%'
$useAsSaas: '%use_as_saas%'
# Commands
App\Command\RemoveAbandonnedProjectsCommand:
arguments:
......
# Matomo Integration
If you want to track visitors the open source software Matomo, then you need to
### Provide environement variable
in `.env.local`
```
MATOMO_URL=https://my_matomo_server.org/
MATOMO_SITE_ID=12
MATOMO_USER_TOKEN=anonymous
```
You can also use a dedicate user token if you prefer
### Configure Cross Origin
In your Matomo instance, go to Administration > System > General settings and fill the Cross Origin Section. More info at https://matomo.org/faq/how-to/faq_18694/
### Allow visibility for anonymous user
If you use the anonymous token, then go to Administration > System > Users, and grant anonymous user the "view" permission for the website
......@@ -39,6 +39,7 @@
"dependencies": {
"core-js": "^3.8.1",
"gogocarto-js": "^1.7.3",
"highcharts": "^9.1.0",
"leaflet": "^1.7.1",
"leaflet-shades": "^0.1.4",
"natives": "^1.1.6",
......
......@@ -7,10 +7,12 @@ use Symfony\Contracts\Translation\TranslatorInterface;
class TwigHelperService
{
public function __construct(DocumentManager $dm, TranslatorInterface $t)
public function __construct(DocumentManager $dm, TranslatorInterface $t, $baseUrl, $useAsSaas)
{
$this->dm = $dm;
$this->t = $t;
$this->baseUrl = $baseUrl;
$this->useAsSaas = $useAsSaas;
}
public function config()
......@@ -23,6 +25,16 @@ class TwigHelperService
return $this->t;
}
public function mainUrl()
{
if ($url = $this->config()->getCustomDomain())
return explode('://', $url)[1];
elseif ($this->useAsSaas)
return $this->config()->getDbName() . '.' . $this->baseUrl;
else
return $this->baseUrl;
}
public function listAbouts()
{
return $this->dm->get('About')->findAllOrderedByPosition();
......
......@@ -2,8 +2,6 @@
{% block block %}
<script src="//code.highcharts.com/4.1.8/highcharts.js"></script>
<script src="//code.highcharts.com/4.1.8/modules/exporting.js"></script>
<script type="text/javascript">
{{ chart(collabResolveChart) }}
{{ chart(userInteractChart) }}
......@@ -12,7 +10,19 @@
</script>
<div class="chart-container row">
<div id="userInteractChart" class="col-md-12 chart-item"></div>
<div id="userInteractChart" class="col-md-12 chart-item"></div>
{% if matomo_url and matomo_site_id and matomo_token %}
<div class="matomo-visits-container col-md-12">
<matomo-visits
base-url="{{ matomo_url}}"
site-id="{{ matomo_site_id }}"
token="{{ matomo_token }}"
project-url="{{ helper.mainUrl }}">
</matomo-visits>
</div>
{% endif %}
<div id="contribsAddResolvedPie" class="col-lg-4 col-md-6 chart-item small"></div>
<div id="contribsEditResolvedPie" class="col-lg-4 col-md-6 chart-item small"></div>
<div id="collabResolveChart" class="col-lg-4 col-md-12 chart-item small"></div>
......
......@@ -38,4 +38,25 @@
<link rel="stylesheet" href="{{ asset('fonts/fontawesome-5/css/all.css') }}" />
{{ config.iconImport|raw }}
{{ config.fontImport | raw }}
\ No newline at end of file
{{ config.fontImport | raw }}
{# Matomo user tracking, if enabled in .env file #}
{% if matomo_url and matomo_site_id and matomo_token %}
<script>
var _paq = window._paq = window._paq || [];
/* tracker methods like "setDocumentTitle" should be called before "trackPageView" */
_paq.push(["setDocumentTitle", "{{ helper.mainUrl }}"]); // we use the projectUrl as pageName in order to easily get stats for every project on saas instance
_paq.push(["setCookieDomain", "*.{{ base_url }}"]);
_paq.push(["setDomains", ["*.{{ base_url }}"]]);
_paq.push(['trackPageView']);
_paq.push(['enableLinkTracking']);
(function() {
var u="{{ matomo_url }}";
_paq.push(['setTrackerUrl', u+'matomo.php']);
_paq.push(['setSiteId', '{{ matomo_site_id }}']);
var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
g.type='text/javascript'; g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s);
})();
</script>
{% endif %}
\ No newline at end of file
......@@ -1306,6 +1306,19 @@ js: # Below keys are available to javascript
api:
placeholder: "Sélectionnez une ou plusieurs catégories"
charts:
period:
day: Jour
week: Semaine
month: Mois
year: Année
field:
nb_visits: Nombre de visites
avg_time_on_page: Temps moyen sur la page (secondes)
title_visitors: Statistiques des visiteurs
display: Afficher
last: Les derniers
reload: Recharger
mapping_ontology: # templates/admin/core_custom/custom-fields/mapping-ontology.html.twig
id: "Identifiant unique (dans l'ancienne base de donnée)"
name: "Titre de la fiche"
......
......@@ -4444,6 +4444,11 @@ hex-color-regex@^1.1.0:
resolved "https://registry.yarnpkg.com/hex-color-regex/-/hex-color-regex-1.1.0.tgz#4c06fccb4602fe2602b3c93df82d7e7dbf1a8a8e"
integrity sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ==
highcharts@^9.1.0:
version "9.1.0"
resolved "https://registry.yarnpkg.com/highcharts/-/highcharts-9.1.0.tgz#2cdb38e2e03530b4fde022bb05fbce5b34651e39"
integrity sha512-K7HUuKhEylZ1pMdzGR35kPgUmpp0MDNpaWhEMkGiC5Jfzg/endtTLHJN2lsFqEO+xoN7AykBK98XaJPEpsrLyA==
hmac-drbg@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1"
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment