Refactoring and cleanup

This commit is contained in:
Sascha Leib
2025-09-16 23:08:54 +02:00
parent ba2210aa16
commit 9e932cfc9d
9 changed files with 178 additions and 212 deletions

View File

@@ -55,7 +55,7 @@ class admin_plugin_botmon extends AdminPlugin {
<header id="botmon__today__title">Loading&nbsp;&hellip;</header>
<div id="botmon__today__content">
<details id="botmon__today__overview" open>
<summary>Bot overview (page views)</summary>
<summary>Overview</summary>
<div class="botmon_bots_grid">
<dl id="botmon__today__botsvshumans"></dl>
<dl id="botmon__botslist"></dl>
@@ -63,7 +63,7 @@ class admin_plugin_botmon extends AdminPlugin {
</div>
</details>
<details id="botmon__today__webmetrics">
<summary>Web metrics</summary>
<summary>Web metrics (humans only)</summary>
<div class="botmon_webmetrics_grid">
<dl id="botmon__today__wm_overview"></dl>
<dl id="botmon__today__wm_clients"></dl>

View File

@@ -1,56 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
viewBox="0 0 24 24"
version="1.1"
id="svg1"
sodipodi:docname="bounce.svg"
inkscape:version="1.4 (86a8ad7, 2024-10-11)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/">
<defs
id="defs1" />
<sodipodi:namedview
id="namedview1"
pagecolor="#505050"
bordercolor="#ffffff"
borderopacity="1"
inkscape:showpageshadow="0"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="1"
inkscape:deskcolor="#505050"
showgrid="false"
showguides="true"
inkscape:zoom="45.17"
inkscape:cx="11.932699"
inkscape:cy="11.667036"
inkscape:window-width="2880"
inkscape:window-height="1526"
inkscape:window-x="2869"
inkscape:window-y="-11"
inkscape:window-maximized="1"
inkscape:current-layer="svg1" />
<title
id="title1">arrow-down-left</title>
<metadata
id="metadata1">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:title>arrow-down-left</dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<path
id="path5"
style="display:inline;stroke-linecap:round;stroke-linejoin:round;fill:#666666"
d="m 22.931849,5.9601427 -0.02539,0.011719 -5.8125,0.013672 0.855469,1.5898437 C 15.330756,9.3543246 12.785051,11.75936 11.345911,14.573424 10.624405,13.172349 9.7143282,11.824042 8.5177866,10.690612 6.6950096,8.9639776 4.4705243,7.660822 2.1720834,7.401549 a 1,1 0 0 0 -1.1054687,0.8828126 1,1 0 0 0 0.8808594,1.105469 c 1.6749782,0.188944 3.6084113,1.2487544 5.1953125,2.7519534 1.5869012,1.503199 2.8163316,3.434551 3.2421874,5.138672 a 1.0001,1.0001 0 0 0 1.941406,0 c 0.726056,-2.905413 3.583028,-5.850154 6.578125,-7.9296884 l 0.798828,1.4824224 3.210938,-4.8476566 0.02539,-0.013672 h -0.01563 z" />
<path
style="stroke-linecap:round;stroke-linejoin:round;fill:#666666"
d="m 15.587891,15.453125 a 1,1 0 0 0 -1.152344,0.818359 1,1 0 0 0 0.816406,1.152344 c 1.156437,0.197324 1.961737,0.544039 2.414063,0.867188 0.452326,0.323148 0.505938,0.560754 0.505859,0.61914 a 1.0001,1.0001 0 0 0 0,0.002 c 2e-6,-0.0463 0.02551,0.01787 -0.214844,0.210938 -0.240358,0.19307 -0.696402,0.437231 -1.300781,0.642578 -1.208759,0.410694 -2.997996,0.691337 -4.974609,0.691406 C 9.7050274,20.456962 7.9157902,20.176319 6.7070312,19.765625 6.1026518,19.560278 5.6466082,19.316117 5.40625,19.123047 5.1680967,18.931748 5.1929184,18.870194 5.1933594,18.914062 c 6.635e-4,-0.09587 0.046068,-0.303946 0.4648437,-0.609375 0.4202715,-0.306519 1.192284,-0.642512 2.3496094,-0.839843 A 1,1 0 0 0 8.8242188,16.310547 1,1 0 0 0 7.671875,15.492188 c -1.3720499,0.233943 -2.4228357,0.635294 -3.1933594,1.197265 -0.7705236,0.561972 -1.2840155,1.352686 -1.2871093,2.21875 a 1.0001,1.0001 0 0 0 0,0.0039 c 3.64e-5,0.749017 0.4452013,1.353693 0.9628906,1.769532 0.5176892,0.415838 1.1590879,0.721375 1.9101562,0.976562 1.5021367,0.510374 3.4569818,0.798753 5.6171879,0.798828 2.160205,-7.5e-5 4.115051,-0.288454 5.617187,-0.798828 0.751068,-0.255187 1.392467,-0.560723 1.910156,-0.976562 0.517226,-0.415467 0.96206,-1.019489 0.962891,-1.767579 0.0012,-0.904344 -0.553226,-1.687191 -1.34375,-2.251953 -0.790524,-0.564762 -1.864356,-0.974217 -3.240234,-1.208984 z"
id="path6" />
</svg>
<svg width="100%" height="100%" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M22.932,5.96l-0.008,0.012l0.016,-0l-0.026,0.014l-3.211,4.847l-0.798,-1.482c-2.996,2.079 -5.853,5.024 -6.579,7.929c-0.11,0.445 -0.512,0.76 -0.97,0.76c-0.458,-0 -0.861,-0.315 -0.971,-0.76c-0.426,-1.704 -1.655,-3.635 -3.242,-5.138c-1.587,-1.503 -3.521,-2.563 -5.196,-2.752c-0.544,-0.062 -0.942,-0.561 -0.88,-1.106c0.056,-0.503 0.487,-0.889 0.993,-0.889c0.038,0 0.075,0.002 0.112,0.007c2.299,0.259 4.523,1.562 6.346,3.289c1.196,1.133 2.106,2.481 2.828,3.882c1.439,-2.814 3.985,-5.219 6.603,-6.998l-0.855,-1.589l5.812,-0.014l0.026,-0.012Zm-17.738,12.943c0.006,0.012 0.042,0.083 0.212,0.22c0.241,0.193 0.697,0.437 1.301,0.643c1.209,0.41 2.998,0.691 4.975,0.691c1.976,0 3.765,-0.281 4.974,-0.691c0.605,-0.206 1.061,-0.45 1.301,-0.643c0.173,-0.139 0.208,-0.211 0.214,-0.223c-0.006,-0.073 -0.076,-0.302 -0.505,-0.609c-0.452,-0.323 -1.258,-0.67 -2.414,-0.867c-0.54,-0.093 -0.908,-0.613 -0.816,-1.153c0.091,-0.54 0.611,-0.909 1.152,-0.818c1.376,0.235 2.45,0.644 3.24,1.209c0.791,0.565 1.345,1.348 1.344,2.252c-0.001,0.748 -0.446,1.352 -0.963,1.768c-0.518,0.415 -1.159,0.721 -1.91,0.976c-1.502,0.511 -3.457,0.799 -5.617,0.799c-2.161,-0 -4.115,-0.288 -5.618,-0.799c-0.751,-0.255 -1.392,-0.561 -1.91,-0.976c-0.517,-0.416 -0.963,-1.021 -0.963,-1.77l0,-0.004c0.004,-0.866 0.517,-1.657 1.288,-2.219c0.77,-0.562 1.821,-0.963 3.193,-1.197c0.54,-0.091 1.06,0.278 1.152,0.819c0.093,0.54 -0.276,1.061 -0.816,1.154c-1.158,0.197 -1.93,0.533 -2.35,0.84c-0.403,0.294 -0.46,0.497 -0.464,0.598Z" style="fill:#777;"/></svg>

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><title>information</title><path d="M11,9H13V7H11M12,20C7.59,20 4,16.41 4,12C4,7.59 7.59,4 12,4C16.41,4 20,7.59 20,12C20,16.41 16.41,20 12,20M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2M11,17H13V11H11V17Z" style="fill:#9E9E9E"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><title>information</title><path d="M11,9H13V7H11M12,20C7.59,20 4,16.41 4,12C4,7.59 7.59,4 12,4C16.41,4 20,7.59 20,12C20,16.41 16.41,20 12,20M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2M11,17H13V11H11V17Z" style="fill:#777"/></svg>

Before

Width:  |  Height:  |  Size: 324 B

After

Width:  |  Height:  |  Size: 321 B

1
img/more.svg Normal file
View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><title>Others</title><path d="M4,2A2,2 0 0,0 2,4V14H4V4H14V2H4M8,6A2,2 0 0,0 6,8V18H8V8H18V6H8M20,12V20H12V12H20M20,10H12A2,2 0 0,0 10,12V20A2,2 0 0,0 12,22H20A2,2 0 0,0 22,20V12A2,2 0 0,0 20,10M19,17H17V19H15V17H13V15H15V13H17V15H19V17Z" style="fill:#777"/></svg>

After

Width:  |  Height:  |  Size: 324 B

View File

@@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><title>page</title><path d="M6,2A2,2 0 0,0 4,4V20A2,2 0 0,0 6,22H18A2,2 0 0,0 20,20V8L14,2H6M6,4H13V9H18V20H6V4M8,12V14H16V12H8M8,16V18H13V16H8Z" style="fill:#999"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><title>page</title><path d="M6,2A2,2 0 0,0 4,4V20A2,2 0 0,0 6,22H18A2,2 0 0,0 20,20V8L14,2H6M6,4H13V9H18V20H6V4M8,12V14H16V12H8M8,16V18H13V16H8Z" style="fill:#777"/></svg>

Before

Width:  |  Height:  |  Size: 231 B

After

Width:  |  Height:  |  Size: 231 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.3 KiB

After

Width:  |  Height:  |  Size: 10 KiB

View File

@@ -1,7 +1,7 @@
base botmon
author Sascha Leib
email ad@hominem.com
date 2025-09-15
date 2025-09-16
name Bot Monitoring
desc A tool for monitoring and analysing bot traffic to your wiki (under development)
url https://www.dokuwiki.org/plugin:botmon

302
script.js
View File

@@ -578,9 +578,55 @@ BotMon.live = {
BotMon.live.gui.status.hideBusy('Done.');
},
// get a list of known bots:
getTopBots: function(max) {
//console.info('BotMon.live.data.analytics.getTopBots('+max+')');
//console.log(BotMon.live.data.analytics.groups.knownBots);
let botsList = BotMon.live.data.analytics.groups.knownBots.toSorted( (a, b) => {
return b._pageViews.length - a._pageViews.length;
});
const other = {
'id': 'other',
'name': "Others",
'count': 0
};
const rList = [];
const max2 = ( botsList.length > max ? max-1 : botsList.length );
let total = 0; // adding up the items
for (let i=0; i<botsList.length; i++) {
const it = botsList[i];
if (it && it._bot) {
if (i < max2) {
rList.push({
id: it._bot.id,
name: (it._bot.n ? it._bot.n : it._bot.id),
count: it._pageViews.length
});
} else {
other.count += it._pageViews.length;
};
total += it._pageViews.length;
}
};
// add the "other" item, if needed:
if (botsList.length > max2) {
rList.push(other);
};
rList.forEach( it => {
it.pct = (it.count * 100 / total);
});
return rList;
},
// Referer List:
_refererList: [],
_refererListCount: 0,
addToRefererList: function(ref) {
//console.log('BotMon.live.data.analytics.addToRefererList',ref);
@@ -592,18 +638,12 @@ BotMon.live = {
return;
}
// find the referer ID:
let refId = 'null';
if (ref && ref.host) {
const hArr = ref.host.split('.');
const tld = hArr[hArr.length-1];
refId = ( tld == 'localhost' ? tld : hArr[hArr.length-2] + ( tld.length > 3 ? '.' + tld : '' ) );
}
const refInfo = me.getRefererInfo(ref);
// already exists?
let refObj = null;
for (let i = 0; i < me._refererList.length; i++) {
if (me._refererList[i].id == refId) {
if (me._refererList[i].id == refInfo.id) {
refObj = me._refererList[i];
break;
}
@@ -611,16 +651,31 @@ BotMon.live = {
// if not exists, create it:
if (!refObj) {
refObj = {
id: refId,
count: 0
};
refObj = refInfo;
refObj.count = 1;
me._refererList.push(refObj);
} else {
refObj.count += 1;
}
// add to total count:
me._refererListCount += 1;
},
getRefererInfo: function(url) {
//console.log('BotMon.live.data.analytics.getRefererInfo',url);
// find the referer ID:
let refId = 'null';
let refName = 'No Referer';
if (url && url.host) {
const hArr = url.host.split('.');
const tld = hArr[hArr.length-1];
refId = ( tld == 'localhost' ? tld : hArr[hArr.length-2] + ( tld.length > 3 ? '.' + tld : '' ) );
refName = hArr[hArr.length-2] + '.' + tld;
}
return {
'id': refId,
'n': refName
};
},
getTopReferers: function(max) {
@@ -628,23 +683,52 @@ BotMon.live = {
const me = BotMon.live.data.analytics;
const rList = []; // return array
return me._makeTopList(me._refererList, max);
},
_makeTopList: function(arr, max) {
//console.info(('BotMon.live.data.analytics._makeTopList(arr,' + max + ')'));
const me = BotMon.live.data.analytics;
// sort the list:
me._refererList.sort( (a,b) => {
arr.sort( (a,b) => {
return b.count - a.count;
});
// get the top:
for (let i = 0; i < max; i++) {
const it = me._refererList[i];
const rList = []; // return array
const max2 = ( arr.length >= max ? max-1 : arr.length );
const other = {
'id': 'other',
'name': "Others",
'count': 0
};
let total = 0; // adding up the items
for (let i=0; Math.min(max, arr.length) > i; i++) {
const it = arr[i];
if (it) {
if (i < max2) {
const rIt = {
id: it.id,
count: it.count,
pct: (it.count / me._refererListCount * 100).toFixed(0)
name: (it.n ? it.n : it.id),
count: it.count
};
rList.push(rIt);
} else {
other.count += it.count;
}
total += it.count;
}
}
// add the "other" item, if needed:
if (arr.length > max2) {
rList.push(other);
};
rList.forEach( it => {
it.pct = (it.count * 100 / total);
});
return rList;
},
@@ -687,11 +771,11 @@ BotMon.live = {
}
if (arr) {
let cRec = arr.find( it => it.iso == iso);
let cRec = arr.find( it => it.id == iso);
if (!cRec) {
cRec = {
'iso': iso,
'name': name,
'id': iso,
'n': name,
'count': 1
};
arr.push(cRec);
@@ -730,25 +814,10 @@ BotMon.live = {
break;
default:
console.warn(`Unknown user type ${type} in function getCountryList.`);
return;
}
if (arr) {
// sort by visit count:
arr.sort( (a,b) => b.count - a.count);
// reduce to only the top (max) items and create the target format:
let rList = [];
for (let i=0; Math.min(max, arr.length) > i; i++) {
const cRec = arr[i];
rList.push({
'iso': cRec.iso,
'name': cRec.name,
'count': cRec.count
});
}
return rList;
}
return [];
return me._makeTopList(arr, max);
},
/* browser and platform of human visitors */
@@ -766,8 +835,9 @@ BotMon.live = {
let bRec = me._browsers.find( it => it.id == browserRec.id);
if (!bRec) {
bRec = {
'id': browserRec.id,
'count': 1
id: browserRec.id,
n: browserRec.n,
count: 1
};
me._browsers.push(bRec);
} else {
@@ -781,8 +851,9 @@ BotMon.live = {
let pRec = me._platforms.find( it => it.id == platformRec.id);
if (!pRec) {
pRec = {
'id': platformRec.id,
'count': 1
id: platformRec.id,
n: platformRec.n,
count: 1
};
me._platforms.push(pRec);
} else {
@@ -796,83 +867,14 @@ BotMon.live = {
const me = BotMon.live.data.analytics;
me._browsers.sort( (a,b) => b.count - a.count);
// how many browsers to show:
const max2 = ( me._browsers.length >= max ? max-1 : max );
const rArr = []; // return array
let total = 0;
const others = {
'id': 'other',
'name': "Others",
'count': 0
};
for (let i=0; i < me._browsers.length; i++) {
if (i < max2) {
rArr.push({
'id': me._browsers[i].id,
'name': BotMon.live.data.clients.getName(me._browsers[i].id),
'count': me._browsers[i].count
});
total += me._browsers[i].count;
} else {
others.count += me._browsers[i].count;
total += me._browsers[i].count;
}
};
if (me._browsers.length > (max-1)) {
rArr.push(others);
};
// update percentages:
rArr.forEach( it => {
it.pct = Math.round(it.count * 100 / total);
});
return rArr;
return me._makeTopList(me._browsers, max);
},
getTopPlatforms: function(max) {
const me = BotMon.live.data.analytics;
me._platforms.sort( (a,b) => b.count - a.count);
// how many browsers to show:
const max2 = ( me._platforms.length >= max ? max-1 : max );
const rArr = []; // return array
let total = 0;
const others = {
'id': 'other',
'name': "Others",
'count': 0
};
for (let i=0; i < me._platforms.length; i++) {
if (i < max2) {
rArr.push({
'id': me._platforms[i].id,
'name': BotMon.live.data.platforms.getName(me._platforms[i].id),
'count': me._platforms[i].count
});
total += me._platforms[i].count;
} else {
others.count += me._platforms[i].count;
total += me._platforms[i].count;
}
};
if (me._platforms.length > (max-1)) {
rArr.push(others);
};
// update percentages:
rArr.forEach( it => {
it.pct = Math.round(it.count * 100 / total);
});
return rArr;
return me._makeTopList(me._platforms, max);
}
},
@@ -1490,14 +1492,16 @@ BotMon.live = {
const data = BotMon.live.data.analytics.data;
const maxItemsPerList = 5; // how many list items to show?
// shortcut for neater code:
const makeElement = BotMon.t._makeElement;
const botsVsHumans = document.getElementById('botmon__today__botsvshumans');
if (botsVsHumans) {
botsVsHumans.appendChild(makeElement('dt', {}, "Bots vs. Humans"));
botsVsHumans.appendChild(makeElement('dt', {}, "Page views by category:"));
for (let i = 3; i >= 0; i--) {
for (let i = 0; i <= 4; i++) {
const dd = makeElement('dd');
let title = '';
let value = '';
@@ -1518,6 +1522,10 @@ BotMon.live = {
title = "Known bots:";
value = data.bots.known;
break;
case 4:
title = "Total:";
value = data.totalPageViews;
break;
default:
console.warn(`Unknown list type ${i}.`);
}
@@ -1528,20 +1536,20 @@ BotMon.live = {
}
// update known bots list:
const botlist = document.getElementById('botmon__botslist'); /* Known bots */
botlist.innerHTML = "<dt>Known bots (top 5)</dt>";
const botElement = document.getElementById('botmon__botslist'); /* Known bots */
if (botElement) {
botElement.innerHTML = `<dt>Known bots (top ${maxItemsPerList})</dt>`;
let bots = BotMon.live.data.analytics.groups.knownBots.toSorted( (a, b) => {
return b._pageViews.length - a._pageViews.length;
let botList = BotMon.live.data.analytics.getTopBots(maxItemsPerList);
botList.forEach( (botInfo) => {
const bli = makeElement('dd');
bli.appendChild(makeElement('span', {'class': 'has_icon bot bot_' + botInfo.id }, botInfo.name));
bli.appendChild(makeElement('span', {'class': 'count' }, botInfo.count));
botElement.append(bli)
});
for (let i=0; i < Math.min(bots.length, 5); i++) {
const dd = makeElement('dd');
dd.appendChild(makeElement('span', {'class': 'has_icon bot bot_' + bots[i]._bot.id }, bots[i]._bot.n));
dd.appendChild(makeElement('span', undefined, bots[i]._pageViews.length));
botlist.appendChild(dd);
}
// update the suspected bot IP ranges list:
/*const botIps = document.getElementById('botmon__today__botips');
if (botIps) {
@@ -1559,11 +1567,11 @@ BotMon.live = {
// update the top bot countries list:
const botCountries = document.getElementById('botmon__today__countries');
if (botCountries) {
botCountries.appendChild(makeElement('dt', {}, "Bot Countries (top 5)"));
botCountries.appendChild(makeElement('dt', {}, `Bot Countries (top ${maxItemsPerList})`));
const countryList = BotMon.live.data.analytics.getCountryList('likely_bot', 5);
countryList.forEach( (cInfo) => {
const cLi = makeElement('dd');
cLi.appendChild(makeElement('span', {'class': 'has_icon country ctry_' + cInfo.iso.toLowerCase() }, cInfo.name));
cLi.appendChild(makeElement('span', {'class': 'has_icon country ctry_' + cInfo.id.toLowerCase() }, cInfo.name));
cLi.appendChild(makeElement('span', {'class': 'count' }, cInfo.count));
botCountries.appendChild(cLi);
});
@@ -1605,9 +1613,9 @@ BotMon.live = {
const wmclients = document.getElementById('botmon__today__wm_clients');
if (wmclients) {
wmclients.appendChild(makeElement('dt', {}, "Top browsers"));
wmclients.appendChild(makeElement('dt', {}, "Browsers"));
const clientList = BotMon.live.data.analytics.getTopBrowsers(5);
const clientList = BotMon.live.data.analytics.getTopBrowsers(maxItemsPerList);
if (clientList) {
clientList.forEach( (cInfo) => {
const cDd = makeElement('dd');
@@ -1615,7 +1623,7 @@ BotMon.live = {
cDd.appendChild(makeElement('span', {
'class': 'count',
'title': cInfo.count + " page views"
}, Math.round(cInfo.pct) + '%'));
}, cInfo.pct.toFixed(1) + '%'));
wmclients.appendChild(cDd);
});
}
@@ -1625,9 +1633,9 @@ BotMon.live = {
const wmplatforms = document.getElementById('botmon__today__wm_platforms');
if (wmplatforms) {
wmplatforms.appendChild(makeElement('dt', {}, "Top platforms"));
wmplatforms.appendChild(makeElement('dt', {}, "Platforms"));
const pfList = BotMon.live.data.analytics.getTopPlatforms(5);
const pfList = BotMon.live.data.analytics.getTopPlatforms(maxItemsPerList);
if (pfList) {
pfList.forEach( (pInfo) => {
const pDd = makeElement('dd');
@@ -1635,7 +1643,7 @@ BotMon.live = {
pDd.appendChild(makeElement('span', {
'class': 'count',
'title': pInfo.count + " page views"
}, Math.round(pInfo.pct) + '%'));
}, pInfo.pct.toFixed(1) + '%'));
wmplatforms.appendChild(pDd);
});
}
@@ -1645,17 +1653,17 @@ BotMon.live = {
const wmreferers = document.getElementById('botmon__today__wm_referers');
if (wmreferers) {
wmreferers.appendChild(makeElement('dt', {}, "Top Referers"));
wmreferers.appendChild(makeElement('dt', {}, "Referers"));
const refList = BotMon.live.data.analytics.getTopReferers(5);
const refList = BotMon.live.data.analytics.getTopReferers(maxItemsPerList);
if (refList) {
refList.forEach( (rInfo) => {
const rDd = makeElement('dd');
rDd.appendChild(makeElement('span', {'class': 'has_icon referer ref_' + rInfo.id }, rInfo.id));
rDd.appendChild(makeElement('span', {'class': 'has_icon referer ref_' + rInfo.id }, rInfo.name));
rDd.appendChild(makeElement('span', {
'class': 'count',
'title': rInfo.count + " references"
}, Math.round(rInfo.pct) + '%'));
}, rInfo.pct.toFixed(1) + '%'));
wmreferers.appendChild(rDd);
});
}
@@ -1859,6 +1867,15 @@ BotMon.live = {
}, ( data._country || "Unknown") ));
}
// referer icons:
if ((data._type == BM_USERTYPE.HUMAN || data._type == BM_USERTYPE.LIKELY_BOT) && data.ref) {
const refInfo = BotMon.live.data.analytics.getRefererInfo(new URL(data.ref));
span1.appendChild(make('span', {
'class': 'icon_only referer ref_' + refInfo.id,
'title': "Referer: " + data.ref
}, refInfo.n));
}
summary.appendChild(span1);
const span2 = make('span'); /* right-hand group */
@@ -1965,9 +1982,6 @@ BotMon.live = {
}, data._country + ' (' + data.geo + ')'));
}
/*dl.appendChild(make('dt', {}, "Visitor Type:"));
dl.appendChild(make('dd', undefined, data._type ));*/
dl.appendChild(make('dt', {}, "Session ID:"));
dl.appendChild(make('dd', {'class': 'has_icon session typ_' + data.typ}, data.id));

View File

@@ -51,6 +51,7 @@
&.bot_claude::before { background-position-y: -160px }
&.bot_applemsgs::before { background-position-y: -180px }
&.bot_reddit::before { background-position-y: -200px }
&.bot_other::before { background-image: url('img/more.svg') }
/* platform icons */
&.platform::before { background-image: url('img/platforms.png') }
@@ -68,6 +69,7 @@
&.pf_hmos::before { background-position-y: -220px }
&.pf_tizen::before { background-position-y: -240px }
&.pf_fire::before { background-position-y: -260px }
&.pf_other::before { background-image: url('img/more.svg') }
/* browser icons */
&.client::before { background-image: url('img/clients.png') }
@@ -89,6 +91,7 @@
&.cl_chromeold::before { background-position-y: -320px }
&.cl_ecosia::before { background-position-y: -340px }
&.cl_webkit::before { background-position-y: -360px }
&.cl_other::before { background-image: url('img/more.svg') }
/* Country flags */
/* Note: flag images and CSS adapted from: https://github.com/lafeber/world-flags-sprite/ */
@@ -353,6 +356,9 @@
&.ref_duckduckgo::before { background-position-y: -120px }
&.ref_ecosia::before { background-position-y: -140px }
&.ref_yandex::before { background-position-y: -160px }
&.ref_chatgpt::before { background-position-y: -180px }
&.ref_brave::before { background-position-y: -200px }
&.ref_other::before { background-image: url('img/more.svg') }
}
/* grid layout for the overview: */