UNPKG

@stokr/components-library

Version:

STOKR - Components Library

541 lines (539 loc) 20.2 kB
"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;