counter improvements

This commit is contained in:
isstuev
2025-08-21 13:26:00 +02:00
parent cdc8b3b59a
commit 1cc45e1859
2 changed files with 102 additions and 20 deletions
+22 -20
View File
@@ -8,7 +8,7 @@ import config from 'configs/app';
import * as cookies from 'lib/cookies';
import type * as metadata from 'lib/metadata';
import detectBotRequest from '../utils/detectBotRequest';
import { isLikelyHumanBrowser, isKnownBotRequest } from '../utils/checkRealBrowser';
const adBannerFeature = config.features.adsBanner;
@@ -45,28 +45,30 @@ Promise<GetServerSidePropsResult<Props<Pathname>>> => {
}
const isTrackingDisabled = process.env.DISABLE_TRACKING === 'true';
const isBot = Boolean(detectBotRequest(req));
if (!isTrackingDisabled && !isBot) {
if (!isTrackingDisabled) {
const isRealUser = isLikelyHumanBrowser(req) && !isKnownBotRequest(req);
if (isRealUser) {
// log pageview
const hostname = req.headers.host;
const timestamp = new Date().toISOString();
const chainId = process.env.NEXT_PUBLIC_NETWORK_ID;
const chainName = process.env.NEXT_PUBLIC_NETWORK_NAME;
const publicRPC = process.env.NEXT_PUBLIC_NETWORK_RPC_URL;
const hostname = req.headers.host;
const timestamp = new Date().toISOString();
const chainId = process.env.NEXT_PUBLIC_NETWORK_ID;
const chainName = process.env.NEXT_PUBLIC_NETWORK_NAME;
const publicRPC = process.env.NEXT_PUBLIC_NETWORK_RPC_URL;
fetch('https://monitor.blockscout.com/count', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
hostname,
timestamp,
chainId,
chainName,
publicRPC,
uuid,
}),
});
fetch('https://monitor.blockscout.com/count', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
hostname,
timestamp,
chainId,
chainName,
publicRPC,
uuid,
}),
});
}
}
return {
+80
View File
@@ -0,0 +1,80 @@
import type { GetServerSidePropsContext } from 'next';
const GENERIC_BOT_MARKERS = [
'bot',
'spider',
'crawler',
'httpclient',
'headlesschrome',
'phantomjs',
'puppeteer',
'playwright',
'node-fetch',
'axios',
'curl',
'wget',
'python-requests',
'go-http-client',
'libwww-perl',
'okhttp',
'postman',
'insomnia',
];
function toLower(input: string | null | undefined): string {
return (input || '').toLowerCase();
}
function isGenericBotUA(userAgent: string): boolean {
const ua = toLower(userAgent);
return GENERIC_BOT_MARKERS.some((m) => ua.includes(m));
}
function hasBrowserHeuristics(req: GetServerSidePropsContext['req']): boolean {
const acceptLanguage = req.headers['accept-language'];
const secChUa = req.headers['sec-ch-ua'];
const secFetchSite = req.headers['sec-fetch-site'];
const secFetchMode = req.headers['sec-fetch-mode'];
const upgradeInsecure = req.headers['upgrade-insecure-requests'];
const hasLang = Boolean(acceptLanguage);
const hasSecHeaders = Boolean(secChUa || secFetchSite || secFetchMode || upgradeInsecure);
return hasLang && hasSecHeaders;
}
export function isLikelyHumanBrowser(req: GetServerSidePropsContext['req']): boolean {
const userAgent = req.headers['user-agent'];
if (!userAgent) return false;
if (isGenericBotUA(userAgent)) return false;
if (!hasBrowserHeuristics(req)) return false;
// Inclusive check for common engines + brands across desktop and mobile
const hasEngineToken = /applewebkit|gecko/i.test(userAgent);
const hasKnownBrowserBrand = /chrome|safari|firefox|crios|fxios|edg|opr|samsungbrowser|vivaldi|whale|duckduckgo/i.test(userAgent);
return hasEngineToken && hasKnownBrowserBrand;
}
export function isKnownBotRequest(req: GetServerSidePropsContext['req']): boolean {
const ua = toLower(req.headers['user-agent']);
if (!ua) return false;
// Social preview bots
if (ua.includes('twitter')) return true;
if (ua.includes('facebook')) return true;
if (ua.includes('telegram')) return true;
if (ua.includes('slack')) return true;
// Search engine bots
if (ua.includes('googlebot')) return true;
if (ua.includes('bingbot')) return true;
if (ua.includes('yahoo')) return true;
if (ua.includes('duckduck')) return true;
// Generic markers
if (isGenericBotUA(ua)) return true;
return false;
}