@stokr/components-library
Version:
STOKR - Components Library
541 lines (539 loc) • 20.2 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = exports.Analytic = void 0;
var _Matomo = _interopRequireDefault(require("../MatomoConnect/Matomo"));
var Moment = _interopRequireWildcard(require("moment"));
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
const matomoConnect = new _Matomo.default();
const months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
const monthsShort = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
class Analytic {
constructor() {
_defineProperty(this, "CURRENT_DATE", void 0);
_defineProperty(this, "START_DATE", void 0);
_defineProperty(this, "VISITS_SUMMARY", {});
_defineProperty(this, "TOTAL_SUMMARY", {});
this.CURRENT_DATE = new Moment();
this.START_DATE = this.CURRENT_DATE.clone().subtract(2, 'months');
this.getSummary();
}
async getSummary() {
this.TOTAL_SUMMARY = {
visits: 0,
bounce_count: 0,
visit_length: 0,
unique_visitors: 0,
avg_time_on_site: 0
};
this.VISITS_SUMMARY = await matomoConnect.init(matomoConnect.GetVisitsSummary, 'month', "".concat(this.START_DATE.format('YYYY-MM-DD'), ",").concat(this.CURRENT_DATE.format('YYYY-MM-DD')));
Object.keys(this.VISITS_SUMMARY).forEach(key => {
this.TOTAL_SUMMARY.visits += this.VISITS_SUMMARY[key].nb_visits || 0;
this.TOTAL_SUMMARY.bounce_count += this.VISITS_SUMMARY[key].bounce_count || 0;
this.TOTAL_SUMMARY.visit_length += this.VISITS_SUMMARY[key].sum_visit_length || 0;
this.TOTAL_SUMMARY.unique_visitors += this.VISITS_SUMMARY[key].nb_uniq_visitors || 0;
this.TOTAL_SUMMARY.avg_time_on_site += this.VISITS_SUMMARY[key].avg_time_on_site || 0;
});
}
static async getRealTimeUsersBasicGraph() {
const lastMinute = await matomoConnect.init(matomoConnect.LiveGetCounters, 10, 'visitors');
const lastHour = await matomoConnect.init(matomoConnect.LiveGetCounters, 60, 'visitors');
const last2Hours = await matomoConnect.init(matomoConnect.LiveGetCounters, 120, 'visitors');
const increase = Analytic.getIncrease(last2Hours, lastMinute);
const object = {
id: 'realTimeUsersStat',
title: 'realtime users',
value: lastMinute.toString(),
percent: isNaN(increase) ? 0 : parseFloat(parseFloat(increase).toFixed(1)),
chart: {
id: 'realTimeUsersChart',
fill: '#e4ecf9',
stroke: '#0050ca',
data: [{
date: 1,
value: last2Hours
}, {
date: 2,
value: lastHour
}, {
date: 3,
value: lastMinute
}]
}
};
return object;
}
async getBasicGraphs() {
return [this.getTotalVisitsBasicGraph(), this.getBounceRateBasicGraph(), this.getVisitDurationBasicGraph()];
}
getTotalVisitsBasicGraph() {
const totalVisitsChartData = [];
Object.keys(this.VISITS_SUMMARY).forEach(key => {
totalVisitsChartData.push({
date: totalVisitsChartData.length + 1,
value: this.VISITS_SUMMARY[key].nb_visits ? this.VISITS_SUMMARY[key].nb_visits : 0
});
});
const visitsSummaryKeys = Object.keys(this.VISITS_SUMMARY);
const previousMonth = this.VISITS_SUMMARY[visitsSummaryKeys[visitsSummaryKeys.length - 2]];
const lastMonth = this.VISITS_SUMMARY[visitsSummaryKeys[visitsSummaryKeys.length - 1]];
const totalVisitsIncrease = Analytic.getIncrease(previousMonth && previousMonth.nb_visits ? previousMonth.nb_visits : 0, lastMonth && lastMonth.nb_visits ? lastMonth.nb_visits : 0);
return {
id: 'totalVisitsStat',
title: 'total visits',
value: this.TOTAL_SUMMARY.visits.toString(),
percent: isNaN(totalVisitsIncrease) ? 0 : parseFloat(parseFloat(totalVisitsIncrease).toFixed(1)),
chart: {
id: 'totalVisitsGraph',
fill: '#fee8e8',
stroke: '#ee220d',
data: totalVisitsChartData
}
};
}
getBounceRateBasicGraph() {
const bounceRateData = [];
Object.keys(this.VISITS_SUMMARY).forEach(key => {
bounceRateData.push({
date: bounceRateData.length + 1,
value: this.VISITS_SUMMARY[key].bounce_count ? this.VISITS_SUMMARY[key].bounce_count : 0
});
});
const visitsSummaryKeys = Object.keys(this.VISITS_SUMMARY);
const firstMonth = this.VISITS_SUMMARY[visitsSummaryKeys.shift()];
const lastMonth = this.VISITS_SUMMARY[visitsSummaryKeys[visitsSummaryKeys.length - 1]];
const bounceRateIncrease = Analytic.getIncrease(firstMonth && firstMonth.bounce_count ? firstMonth.bounce_count : 0, lastMonth && lastMonth.bounce_count ? lastMonth.bounce_count : 0);
const bounceRate = Analytic.getPercent(this.TOTAL_SUMMARY.bounce_count, this.TOTAL_SUMMARY.visits);
return {
id: 'bounceRateStat',
title: 'bounce rate',
value: "".concat(bounceRate, "%"),
percent: isNaN(bounceRateIncrease) ? 0 : parseFloat(parseFloat(bounceRateIncrease).toFixed(1)),
chart: {
id: 'bounceRateGraph',
fill: '#eff8ec',
stroke: '#69bd53',
data: bounceRateData
}
};
}
getVisitDurationBasicGraph() {
const visitDurationData = [];
Object.keys(this.VISITS_SUMMARY).forEach(key => {
visitDurationData.push({
date: visitDurationData.length + 1,
value: this.VISITS_SUMMARY[key].avg_time_on_site ? this.VISITS_SUMMARY[key].avg_time_on_site : 0
});
});
const visitsSummaryKeys = Object.keys(this.VISITS_SUMMARY);
const firstMonth = this.VISITS_SUMMARY[visitsSummaryKeys.shift()];
const lastMonth = this.VISITS_SUMMARY[visitsSummaryKeys[visitsSummaryKeys.length - 1]];
const visitDurationIncrease = Analytic.getIncrease(firstMonth && firstMonth.avg_time_on_site ? firstMonth.avg_time_on_site : 0, lastMonth && lastMonth.avg_time_on_site ? lastMonth.avg_time_on_site : 0);
const value = new Moment().startOf('day').seconds(this.TOTAL_SUMMARY.avg_time_on_site);
return {
id: 'visitDurationStat',
title: 'avg. visit duration',
value: Analytic.getTimeSpent(value),
percent: isNaN(visitDurationIncrease) ? 0 : parseFloat(parseFloat(visitDurationIncrease).toFixed(1)),
chart: {
id: 'visitDurationGraph',
fill: '#f0f0f0',
stroke: '#2f2f2f',
data: visitDurationData
}
};
}
async getCountryGraph() {
const graphData = [];
const countries = await matomoConnect.init(matomoConnect.GetCountrySummary, 'range', "".concat(this.START_DATE.format('YYYY-MM-DD'), ",").concat(this.CURRENT_DATE.format('YYYY-MM-DD')));
const countriesByMonth = await matomoConnect.init(matomoConnect.GetCountrySummary, 'month', "".concat(this.START_DATE.format('YYYY-MM-DD'), ",").concat(this.CURRENT_DATE.format('YYYY-MM-DD')));
countries.forEach((value, key) => {
const bounceRateData = [];
let bounceRate = value.bounce_count * 100 / value.nb_visits;
bounceRate = parseFloat(bounceRate).toFixed(2);
Object.keys(countriesByMonth).forEach(byMonthKey => {
const object = {
date: bounceRateData.length + 1
};
countriesByMonth[byMonthKey].forEach(cv => {
if (cv.code === value.code) {
object.value = cv && cv.bounce_count ? cv.bounce_count : 0;
}
});
if (!object.value) {
object.value = 0;
}
bounceRateData.push(object);
});
graphData.push({
id: key,
country: value.code,
country_name: value.label,
visits: value.nb_visits,
unique_visitors: value.sum_daily_nb_uniq_visitors,
flag_url: "".concat(matomoConnect.MATOMO_API_URL, "/").concat(value.logo),
bounce_rate: "".concat(bounceRate, "%"),
chart: {
id: "countryChart".concat(key),
fill: '#E4ECF9',
stroke: '#0050CA',
data: bounceRateData
}
});
});
return graphData;
}
async getSocialGraph() {
const graphData = [];
const socials = await matomoConnect.init(matomoConnect.GetSocialSummary, 'range', "".concat(this.START_DATE.format('YYYY-MM-DD'), ",").concat(this.CURRENT_DATE.format('YYYY-MM-DD')));
socials.forEach((value, key) => {
let progress = value.sum_daily_nb_uniq_visitors * 100 / this.TOTAL_SUMMARY.unique_visitors;
progress = parseFloat(progress).toFixed(2);
graphData.push({
id: key,
network: "".concat(value.label.charAt(0).toUpperCase()).concat(value.label.slice(1)),
visitors: value.sum_daily_nb_uniq_visitors,
progress: parseFloat(progress)
});
});
return graphData;
}
async getDeviceGraph() {
const devices = await matomoConnect.init(matomoConnect.GetDeviceOsFamilies, 'range', "".concat(this.START_DATE.format('YYYY-MM-DD'), ",").concat(this.CURRENT_DATE.format('YYYY-MM-DD')));
const browsers = await matomoConnect.init(matomoConnect.GetDeviceBrowsers, 'range', "".concat(this.START_DATE.format('YYYY-MM-DD'), ",").concat(this.CURRENT_DATE.format('YYYY-MM-DD')));
const models = await matomoConnect.init(matomoConnect.GetDeviceModels, 'range', "".concat(this.START_DATE.format('YYYY-MM-DD'), ",").concat(this.CURRENT_DATE.format('YYYY-MM-DD')));
let desktop = 0;
let android = 0;
let ios = 0;
let other = 0;
let total = 0;
devices.forEach((value, key) => {
if (value.label === 'Android') {
android += value.nb_visits;
}
if (value.label === 'iOS') {
ios += value.nb_visits;
}
if (value.label === 'Windows' || value.label === 'Mac' || value.label === 'GNU/Linux') {
desktop += value.nb_visits;
}
if (!['Windows', 'Mac', 'GNU/Linux', 'Android', 'iOS'].includes(value.label)) {
other += value.nb_visits;
}
});
total = android + ios + desktop + other;
const donutChart = [{
name: 'Android',
value: android,
color: '#0050CA'
}, {
name: 'Other',
value: other,
color: '#69BD53'
}, {
name: 'IOS',
value: ios,
color: '#CEDDF5'
}, {
name: 'Desktop',
value: desktop,
color: '#EE220D'
}];
const deviceData = {
Android: {
percent: Analytic.getPercent(android, total),
value: android
},
iOS: {
percent: Analytic.getPercent(ios, total),
value: ios
},
Desktop: {
percent: Analytic.getPercent(desktop, total),
value: desktop
},
Other: {
percent: Analytic.getPercent(other, total),
value: other
}
};
const desktopBrowsers = [];
let desktopBrowsersTotal = 0;
browsers.forEach((value, key) => {
if (['Chrome', 'Firefox', 'Safari', 'Opera', 'Internet Explorer', 'Microsoft Edge', 'Vivaldi'].includes(value.label)) {
desktopBrowsersTotal += value.nb_visits;
}
});
browsers.forEach((value, key) => {
if (['Chrome', 'Firefox', 'Safari', 'Opera', 'Internet Explorer', 'Microsoft Edge', 'Vivaldi'].includes(value.label)) {
desktopBrowsers.push({
label: value.label,
value: "".concat(value.nb_visits, " (").concat(Analytic.getPercent(value.nb_visits, desktopBrowsersTotal), "%)")
});
}
});
const iosModels = [];
let iosTotal = 0;
const androidModels = [];
let androidTotal = 0;
models.forEach((value, key) => {
if (!value.label.includes('Generic') && value.label.includes('Apple')) {
iosTotal += value.nb_visits;
}
if (!value.label.includes('Generic') && !value.label.includes('Apple')) {
androidTotal += value.nb_visits;
}
});
models.forEach((value, key) => {
if (!value.label.includes('Generic') && value.label.includes('Apple')) {
iosModels.push({
label: value.label,
value: "".concat(value.nb_visits, " (").concat(Analytic.getPercent(value.nb_visits, iosTotal), "%)")
});
}
if (!value.label.includes('Generic') && !value.label.includes('Apple')) {
androidModels.push({
label: value.label,
value: "".concat(value.nb_visits, " (").concat(Analytic.getPercent(value.nb_visits, androidTotal), "%)")
});
}
});
return {
donutChart,
deviceData,
desktopBrowsers,
iosModels,
androidModels
};
}
async getMonthSlider() {
const response = await matomoConnect.init(matomoConnect.GetVisitsSummary, 'day', "".concat(this.START_DATE.format('YYYY-MM-DD'), ",").concat(this.CURRENT_DATE.format('YYYY-MM-DD')));
const data = [];
Object.keys(response).forEach(key => {
const month = key.split('-');
let check = false;
data.forEach((value, k) => {
if (value.title === "".concat(months[parseInt(month[1], 10) - 1], " ").concat(month[0])) {
check = true;
}
});
if (!check) {
data.push({
title: "".concat(months[parseInt(month[1], 10) - 1], " ").concat(month[0]),
values: [],
total: 0
});
}
data.forEach((value, k) => {
if (value.title === "".concat(months[parseInt(month[1], 10) - 1], " ").concat(month[0])) {
value.values.push({
name: key.split('-')[2],
value: response[key].nb_uniq_visitors ? response[key].nb_uniq_visitors : 0
});
value.total += response[key].nb_uniq_visitors ? response[key].nb_uniq_visitors : 0;
}
});
});
return data.reverse();
}
async getYearSlider() {
const data = [];
const response = await this.getMonthSlider();
response && response.reverse().forEach(month => {
const year = month.title.split(' ');
let check = false;
data.forEach((value, k) => {
if (value.title === "".concat(year[1])) {
check = true;
}
});
if (!check) {
data.push({
title: "".concat(year[1]),
values: []
});
}
data.forEach((value, k) => {
if (value.title === "".concat(year[1])) {
value.values.push({
name: "".concat(year[0]),
value: month.total || 0
});
}
});
});
return data.reverse();
}
async getWeekSlider() {
const response = await matomoConnect.init(matomoConnect.GetVisitsSummary, 'day', "".concat(this.START_DATE.format('YYYY-MM-DD'), ",").concat(this.CURRENT_DATE.format('YYYY-MM-DD')));
const data = [];
Object.keys(response).forEach(key => {
const startOfWeek = Moment(key).startOf('isoWeek');
const endOfWeek = Moment(key).endOf('isoWeek');
const slicedStartOfWeek = startOfWeek.toString().slice(4, 10); //15)
const slicedEndOfWeek = endOfWeek.toString().slice(4, 10); //15)
const day = Moment(key).format('ddd');
let check = false;
data.forEach((value, k) => {
if (value.title === "".concat(slicedStartOfWeek, " - ").concat(slicedEndOfWeek)) {
check = true;
}
});
if (!check) {
data.push({
title: "".concat(slicedStartOfWeek, " - ").concat(slicedEndOfWeek),
values: []
});
}
data.forEach((value, k) => {
if (value.title === "".concat(slicedStartOfWeek, " - ").concat(slicedEndOfWeek)) {
value.values.push({
name: day,
value: response[key].nb_uniq_visitors ? response[key].nb_uniq_visitors : 0
});
}
});
});
return data.reverse();
}
async getHeatmap() {
const periods = {
'00': {
value: '12AM'
},
'01': {
value: '1AM'
},
'02': {
value: '2AM'
},
'03': {
value: '3AM'
},
'04': {
value: '4AM'
},
'05': {
value: '5AM'
},
'06': {
value: '6AM'
},
'07': {
value: '7AM'
},
'08': {
value: '8AM'
},
'09': {
value: '9AM'
},
10: {
value: '10AM'
},
11: {
value: '11AM'
},
12: {
value: '12PM'
},
13: {
value: '1PM'
},
14: {
value: '2PM'
},
15: {
value: '3PM'
},
16: {
value: '4PM'
},
17: {
value: '5PM'
},
18: {
value: '6PM'
},
19: {
value: '7PM'
},
20: {
value: '8PM'
},
21: {
value: '9PM'
},
22: {
value: '10PM'
},
23: {
value: '11PM'
},
24: {
value: '12PM'
}
};
const uniqueData = {};
const response = await matomoConnect.init(matomoConnect.GetVisitTimePerLocalTime, 'day', "".concat(this.START_DATE.format('YYYY-MM-DD'), ",").concat(this.CURRENT_DATE.format('YYYY-MM-DD')));
Object.keys(response).forEach(key => {
const time = new Moment(key);
response[key].forEach((hour, k) => {
const day = time.format('ddd').toUpperCase();
const uniqueId = "".concat(day, "-").concat(hour.label);
if (uniqueData[uniqueId] !== undefined) {
const datum = uniqueData[uniqueId];
// calculate an average value for all redundant data
datum.value = (datum.dataCount * datum.value + hour.nb_uniq_visitors) / (datum.dataCount + 1);
datum.dataCount += 1;
} else {
uniqueData[uniqueId] = {
group: day,
variable: periods[hour.label].value,
value: hour.nb_uniq_visitors,
dataCount: 1
};
}
});
});
const data = Object.keys(uniqueData).map(uniqueId => {
const datum = uniqueData[uniqueId];
return {
group: datum.group,
variable: datum.variable,
value: datum.value
};
});
return data;
}
static getPercent(number, total) {
let percent = number * 100 / total;
percent = parseFloat(percent).toFixed(2);
return isNaN(parseFloat(percent)) ? 0 : parseFloat(percent);
}
static getIncrease() {
let min = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
let max = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
let increase = max - min;
increase = increase / min * 100;
return increase === Infinity && increase > 100 ? 100 : increase;
}
static getTimeSpent(value) {
let hours = '';
let minutes = '';
if (value.format('H') !== 0) {
hours = "".concat(value.format('H'), "h ");
}
if (value.format('m') !== 0) {
minutes = "".concat(value.format('m'), "m ");
}
return "".concat(hours).concat(minutes).concat(value.format('s'), "s");
}
}
exports.Analytic = Analytic;
var _default = exports.default = Analytic;