Почему Umami не видит ботов, а логи видят всех

Заходишь в свою веб-аналитику, а там тишина. За сутки — горстка просмотров и пара посетителей. Вроде сайт живой, статьи публикуются, кто-то их читает. Но панель упорно показывает, что кроме тебя и пары друзей никто не заходит.
Знакомо? У меня так было с блогом. Пока я не полез в access-логи веб-сервера и не обнаружил, что на сайт ходят толпы ботов, а аналитика их просто не видит. Дальше — почему так вышло и что я с этим сделал.
Как Umami считает визиты
Umami (и почти любая JS-аналитика) работает через скрипт на странице:
<script async src="https://analytics.example/script.js"
data-website-id="..."></script>
Логика простая: браузер загружает страницу → выполняет скрипт → скрипт шлёт событие на api/send. Всё считает клиент, на стороне сервера — только приём.
И вот тут первая ловушка: боты не исполняют JavaScript. Поисковики, AI-краулеры, SEO-сканеры скачивают HTML и уходят. Они не запускают скрипт аналитики, поэтому для Umami их просто не существует.
Вторая ловушка: Umami по умолчанию фильтрует ботов по User-Agent. Даже если какой-то краулер решит выполнить скрипт, встроенная детекция ботов его отсеет. То есть панель намеренно показывает только «настоящих» людей.
Звучит разумно, пока тебе не нужно понять: а кто вообще стучится в мой сайт?
Что я увидел в логах
Когда я сравнил картину из Umami и из access-логов Caddy, разница оказалась смешной.
Umami за сутки: около полусотни просмотров, двадцать с лишним посетителей.
А в логах веб-сервера за тот же день — толпа. Вот кто приходил:
- AhrefsBot — SEO-краулер
- GPTBot, ChatGPT-User — краулеры OpenAI
- ClaudeBot — Anthropic
- PerplexityBot — Perplexity
- Googlebot, Yandex, Bing — поисковики
- TelegramBot — превью ссылок в мессенджере
- плюс всякая мелочь вроде сканеров уязвимостей
Суммарно — под сотню обращений в день. И ни одного из них в Umami.
Вывод простой: JS-аналитика считает людей, а не трафик. Если хочешь видеть всех — надо смотреть логи сервера.
GoAccess вместо панели
GoAccess — это терминальный (и не только) анализатор логов, который гоняет access-лог и выдаёт отчёт: кто, откуда, сколько, какие страницы, какие статусы, какие боты. Никакого JS — только то, что реально дошло до сервера.
Ставится элементарно:
apt install goaccess
Но есть нюанс. Caddy по умолчанию пишет логи в stderr, а не в файл. Чтобы GoAccess их увидел, нужен файл:
log {
output file /var/log/caddy/access.log
}
Тут я наступил на граблю: Caddy в systemd крутится под ProtectSystem=full, и файл лога вне разрешённых путей он создать не может — падает с «permission denied». Лечится drop-in'ом:
# /etc/systemd/system/caddy.service.d/rw-logs.conf
[Service]
ReadWritePaths=/var/log/caddy
Потом systemctl daemon-reload && systemctl reload caddy.
JSON-логи Caddy — не для GoAccess
Вторая засада: Caddy пишет логи в JSON, а GoAccess ест классический Combined Log Format. Приходится конвертировать. Я сделал это через jq:
jq -r 'select(.request != null)
| select((.request.headers["User-Agent"][0] // "") | test("Uptime-Kuma|curl/|Python-urllib"; "i") | not)
| "\(.request.client_ip // .request.remote_ip) - - [\(.ts|strftime("%d/%b/%Y:%H:%M:%S %z"))] \"\(.request.method) \(.request.uri) \(.request.proto)\" \(.status) \(.size // 0) \"\(.request.headers.Referer[0] // "-")\" \"\(.request.headers["User-Agent"][0] // "-")\""' \
access.log > access.clf
Заметили фильтр? Я отсекаю собственный мониторинг (Uptime-Kuma долбит сайт каждые 30 секунд — за сутки это тысячи строк шума) и свои же curl-запросы. Иначе отчёт превращается в статистику «сколько раз мой мониторинг пинговал самого себя».
Дальше — рендер:
goaccess --log-format='%h %^[%d:%t %^] "%r" %s %b "%R" "%u"' \
--date-format='%d/%b/%Y' --time-format='%H:%M:%S' \
-f access.clf -o /var/www/logs/index.html --no-global-config
Обновляю отчёт по cron раз в пять минут. Финальный штрих — отдаю HTML через Caddy на поддомен logs.example, закрытый тем же allow-list'ом, что и админки (снаружи пускаю только свои IP).
Что в итоге
Теперь у меня два инструмента, и каждый на своём месте:
- Umami — чтобы видеть живых людей: что читают, откуда пришли, что держится на странице. Тут чистота важнее полноты.
- GoAccess по логам — чтобы видеть весь трафик: людей, ботов, сканеры, статусы 404 и 500, откуда реально ломятся.
Один не заменяет другой. Панель аналитики молчит про ботов не потому, что их нет, а потому что она про них не должна знать. А логи не знают про поведение человека на странице, зато честно показывают каждый запрос.
Мораль: если кажется, что «на сайт никто не заходит» — проверьте логи, прежде чем расстраиваться. Возможно, там как раз наоборот — заходят, и ещё как.
А у вас чем смотрите трафик? Только панель, или логи тоже смотрите?
#selfhosting #analytics #monitoring #network #goaccess #umami