From 9ee332aa26e5a68c95bd9de8e7d1c7bcf99b7e1c Mon Sep 17 00:00:00 2001 From: Steven Tey Date: Sun, 29 Oct 2023 20:36:51 -0700 Subject: [PATCH] Don't track bot clicks --- apps/web/lib/middleware/link.ts | 2 +- apps/web/lib/middleware/root.ts | 2 +- apps/web/lib/stats.ts | 36 +------------------------------ apps/web/lib/tinybird.ts | 9 ++++++-- apps/web/ui/stats/device-icon.tsx | 17 --------------- apps/web/ui/stats/devices.tsx | 14 ++++-------- 6 files changed, 14 insertions(+), 66 deletions(-) diff --git a/apps/web/lib/middleware/link.ts b/apps/web/lib/middleware/link.ts index dcec598b4f..06e535ae6c 100644 --- a/apps/web/lib/middleware/link.ts +++ b/apps/web/lib/middleware/link.ts @@ -94,7 +94,7 @@ export default async function LinkMiddleware( // only track the click when there is no `dub-no-track` header if (!req.headers.get("dub-no-track")) { - ev.waitUntil(recordClick({ domain, req, key })); + ev.waitUntil(recordClick({ req, domain, key })); } const isBot = detectBot(req); diff --git a/apps/web/lib/middleware/root.ts b/apps/web/lib/middleware/root.ts index 7dd2d742e6..e0b42b0c9d 100644 --- a/apps/web/lib/middleware/root.ts +++ b/apps/web/lib/middleware/root.ts @@ -15,7 +15,7 @@ export default async function RootMiddleware( } // record clicks on root page - ev.waitUntil(recordClick({ domain, req })); + ev.waitUntil(recordClick({ req, domain })); const response = await redis.get<{ target: string; diff --git a/apps/web/lib/stats.ts b/apps/web/lib/stats.ts index 0af503e374..a5371bd474 100644 --- a/apps/web/lib/stats.ts +++ b/apps/web/lib/stats.ts @@ -59,40 +59,7 @@ export const intervalData = { export type LocationTabs = "country" | "city" | "region"; -export type DeviceTabs = "device" | "browser" | "os" | "bot" | "ua"; - -export const uaToBot = (ua: string): string => { - if (!ua) return "Unknown Bot"; - if (ua.includes("curl")) { - return "Curl Request"; - } else if (ua.includes("Slackbot")) { - return "Slack Bot"; - } else if (ua.includes("Twitterbot")) { - return "Twitter Bot"; - } else if (ua.includes("facebookexternalhit")) { - return "Facebook Bot"; - } else if (ua.includes("LinkedInBot")) { - return "LinkedIn Bot"; - } else if (ua.includes("WhatsApp")) { - return "WhatsApp Bot"; - } else if (ua.includes("TelegramBot")) { - return "Telegram Bot"; - } else if (ua.includes("Discordbot")) { - return "Discord Bot"; - } else if (ua.includes("Googlebot")) { - return "Google Bot"; - } else if (ua.includes("Baiduspider")) { - return "Baidu Bot"; - } else if (ua.includes("bingbot")) { - return "Bing Bot"; - } else if (ua.includes("YandexBot")) { - return "Yandex Bot"; - } else if (ua.includes("DuckDuckBot")) { - return "DuckDuckGo Bot"; - } else { - return "Unknown Bot"; - } -}; +export type DeviceTabs = "device" | "browser" | "os" | "ua"; const VALID_TINYBIRD_ENDPOINTS = new Set([ "timeseries", @@ -102,7 +69,6 @@ const VALID_TINYBIRD_ENDPOINTS = new Set([ "device", "browser", "os", - "bot", "referer", ]); diff --git a/apps/web/lib/tinybird.ts b/apps/web/lib/tinybird.ts index 55520e3178..84ed6f976d 100644 --- a/apps/web/lib/tinybird.ts +++ b/apps/web/lib/tinybird.ts @@ -8,20 +8,25 @@ import { ipAddress } from "@vercel/edge"; import { NextRequest, userAgent } from "next/server"; import { conn } from "./planetscale"; import { ratelimit } from "./upstash"; +import { detectBot } from "./middleware/utils"; /** * Recording clicks with geo, ua, referer and timestamp data * If key is not specified, record click as the root click ("_root", e.g. dub.sh, vercel.fyi) **/ export async function recordClick({ - domain, req, + domain, key, }: { - domain: string; req: NextRequest; + domain: string; key?: string; }) { + const isBot = detectBot(req); + if (isBot) { + return null; + } const geo = process.env.VERCEL === "1" ? req.geo : LOCALHOST_GEO_DATA; const ua = userAgent(req); const referer = req.headers.get("referer"); diff --git a/apps/web/ui/stats/device-icon.tsx b/apps/web/ui/stats/device-icon.tsx index de6ca92ef7..c69f56c8cc 100644 --- a/apps/web/ui/stats/device-icon.tsx +++ b/apps/web/ui/stats/device-icon.tsx @@ -11,15 +11,6 @@ export default function DeviceIcon({ tab: DeviceTabs; className: string; }) { - if (display === "Bot") { - return ( - {display} - ); - } if (tab === "device") { return ( ); } - } else if (tab === "bot") { - return ( - {display} - ); } else { return ( ({ - icon: ( - - ), - title: tab === "bot" ? uaToBot(d.ua) : d[tab], + icon: , + title: d[tab], clicks: d.clicks, })) || [] } @@ -60,7 +54,7 @@ export default function Devices() {

Devices