#JS и PHP трекер по токену
Статус: Доступно.
Назначение: минимальный способ учитывать посещения на любом сайте без модуля: один тег <script> либо серверная отправка из PHP. Передаются путь, источник и UTM; роботов видит только серверный вариант.
#Содержание
- Когда использовать
- Доступ
- JS-тег
- Серверный вариант (PHP)
- Запрос
POST /api/v1/track/visit - Ответы
- Пределы
- Что записывается
- Чего трекер не делает
- Проверка
- Открытые вопросы
#Когда использовать
| Нужно | Путь |
|---|---|
| Счётчик посещений на произвольном сайте | JS-тег |
| Видеть заходы роботов и ИИ-краулеров на PHP-сайте | PHP-вариант |
| Чат, поведение, согласие | Загрузчик или модуль |
| События, формы, SPA, мобильное приложение | API событий — Планируется |
#Доступ
| Токен | 32 hex-символа; в таблице токенов бывает двух видов: tracker (обычный) и connector (создан привязкой модуля) |
| Выдача | кабинет, право seo.manage |
| Платно | нет |
| Персональные данные | хеши IP и User-Agent; значения не хранятся (см. Обзор) |
| Секретность | токен публичен: он стоит в теге на странице. От злоупотреблений защищают пределы и суточная квота |
#JS-тег
<script async src="https://formula-cream.pro/api/v1/track/js?t=0123456789abcdef0123456789abcdef"></script>
Замените домен на адрес вашей ячейки: RU https://formula-cream.pro, EN https://wfacademy.org, ID https://wfacademy.id. Токен выдаёт кабинет.
#Параметры GET /api/v1/track/js
| Параметр | Тип | Обязателен | Ограничения | Пример |
|---|---|---|---|---|
t | string | да | 32 hex-символа | 0123456789abcdef0123456789abcdef |
#Ответ
| Условие | Код | Тело |
|---|---|---|
| Токен имеет неверный вид | 400 | /* bad token */ |
| Иначе | 200 | скрипт, Cache-Control: public, max-age=3600, Access-Control-Allow-Origin: * |
Наличие токена в базе при отдаче скрипта не проверяется: проверяет приёмник хитов.
#Что отправляет скрипт
Один запрос на загрузку страницы через navigator.sendBeacon (Blob text/plain), запасной путь — fetch в режиме no-cors с keepalive.
{
"t": "0123456789abcdef0123456789abcdef",
"kind": "js",
"path": "/blog/emulsions",
"host": "example.ru",
"ref": "https://www.google.com/",
"utm": { "source": "newsletter", "medium": "email", "campaign": "october" }
}
#Серверный вариант (PHP)
Вставляется в init.php Bitrix (или начало любого PHP-приложения). Исходник выдаёт GET /api/v1/track/php?t=<токен>.
Что делает фрагмент: после обработки запроса отправляет хит с параметрами и не задерживает страницу — неблокирующий curl_multi с подключением 150 мс и общим таймаутом 200 мс.
Хит не отправляется, если:
- скрипт запущен из CLI;
- путь начинается с
/bitrix,uploadилиlocal/templates; - запрос — статический файл (по расширению);
- запрос ajax (
X-Requested-With); - метод не GET;
Acceptне содержитtext/htmlили*/*.
Отключить на время: добавьте define('SAPPORT_TRACKER_DISABLED', true); выше вставленного блока.
IP посетителя берётся из первого элемента X-Forwarded-For (если заголовок есть), иначе из REMOTE_ADDR. Если сайт доступен напрямую, заголовок может подделать посетитель: ставьте сервер за доверенным прокси.
#Запрос POST /api/v1/track/visit
Приёмник общий для JS-тега, PHP-кода и подписанного маячка модулей. Подпись для модулей описана в протоколе коннектора; для токена подпись не нужна.
Заголовки: Content-Type: application/json (допустим и text/plain, как у sendBeacon). CORS: *.
#Тело запроса
| Поле | Тип | Обязательно | Ограничения | Пример |
|---|---|---|---|---|
t | string | да | токен трекера, 32 hex | 0123456789abcdef0123456789abcdef |
kind | string | нет | js (по умолчанию) или server. server доверяется только если host входит в домены арендатора; иначе хит считается JS-хитом | server |
path | string | да | путь страницы; query отбрасывается, итог ≤ 512 символов (PHP присылает до 600, с query: UTM берутся из неё) | /blog/emulsions |
host | string | да | хост страницы | example.ru |
ref | string | нет | реферер, ≤ 600 | https://www.google.com/ |
utm | object | нет | source, medium, campaign, каждое ≤ 100 символов | {"source":"newsletter"} |
ua | string | только server | User-Agent, ≤ 1000 | Mozilla/5.0 … |
ip | string | только server | IP посетителя | 203.0.113.7 |
country | string | нет | двухбуквенный код; для JS страна берётся из заголовка cf-ipcountry | RU |
status | integer | нет | 100–599, HTTP-код ответа страницы | 200 |
Тело — не более 8192 байт; больше — ответ 204 без записи.
curl -i -X POST 'https://formula-cream.pro/api/v1/track/visit' \
-H 'Content-Type: application/json' \
-d '{"t":"0123456789abcdef0123456789abcdef","kind":"js","path":"/blog/emulsions","host":"example.ru","ref":"","utm":{"source":"newsletter"}}'
#Ответы
Успешный приём и большинство отказов выглядят одинаково — 204 без тела, чтобы нельзя было подбирать токены.
| Код | Когда |
|---|---|
204 | принято; либо тело не JSON; либо токен неверный, неизвестный или отозван; либо превышена суточная квота; либо тело больше 8192 байт |
403 | ключ загрузчика (connector) использован для kind: server; либо сайт не привязан, счётчик выключен или нет доступа у арендатора |
429 | превышен предел частоты по адресу или по токену |
500 | ошибка базы данных (запись не выполнена) |
Ошибки не возвращают application/problem+json: это отдельный приёмник счётчика, а не часть публичного API (см. Соглашения API для серверного API).
#Пределы
| Предел | Значение |
|---|---|
| По адресу отправителя (без подписи) | 1 запрос в секунду, всплеск до 60 |
| По токену | 10 запросов в секунду, всплеск до 100 |
| Суточная квота токена | 200 000 хитов за сутки (UTC); сверх квоты 204 без записи |
| Размер тела | 8192 байт |
| Подписанный маячок модуля | 1200 запросов в минуту с адреса |
Квота и пределы считаются в памяти процесса: при нескольких процессах эффективный предел мягче номинального.
Хиты хранятся 180 дней.
#Что записывается
| Поле хита | Откуда |
|---|---|
kind | bot или human — по User-Agent |
bot_family | семейство бота из закрытого списка |
path, host | из запроса |
referrer_host | хост реферера |
ai_referrer | метка ИИ-ассистента по хосту реферера |
utm_source, utm_medium, utm_campaign | из utm или из query пути |
ua_hash, ip_hash | sha256(соль | значение), обрезанный до 32 hex |
country | из cf-ipcountry или из тела доверенного серверного хита |
status | HTTP-код |
sample_ua | образец User-Agent, только для ботов, до 300 символов |
beacon | js или server |
#Классификация
- Бот определяется по User-Agent по закрытому списку семейств. Неизвестный бот считается человеком.
- ИИ-ассистент определяется по суффиксу хоста реферера. У ботов реферер ИИ не учитывается.
| Метка | Хосты реферера |
|---|---|
chatgpt | chatgpt.com, chat.openai.com |
perplexity | perplexity.ai |
gemini | gemini.google.com, bard.google.com |
copilot | copilot.microsoft.com, bing.com/chat |
you | you.com |
claude | claude.ai |
alice | ya.ru/alice, alice.yandex.ru, yandex.ru/alice |
duckassist | duckduckgo.com/aichat |
mistral | mistral.ai |
deepseek | chat.deepseek.com |
Просто ya.ru — не Алиса: переход с него не помечается как ИИ.
#Чего трекер не делает
- SPA: учитывается загрузка страницы, а не смена адреса через History API.
- События: нет
track('purchase'), кнопок и форм. Для этого предназначен API событий (Планируется). - Сессии и посетители: нет идентификатора сессии, cookies и localStorage. «Уникальных посетителей» оценивает облако по хешам IP и User-Agent за день.
- UTM: только
source,medium,campaign. Поляutm_contentиutm_termне передаются. - Роботы по JS-тегу: боты JS не исполняют, их видит только серверный вариант.
- Согласие: JS-тег не ждёт согласия и не управляется
window.sapport.consent. Если для вашей юрисдикции нужно согласие, подключайте тег после него или используйте загрузчик.
#Проверка
- Откройте страницу; во вкладке «Сеть» найдите запрос
track/js?t=…(200) и затемtrack/visit. - Ответ
204не означает, что хит записан (см. таблицу ответов); проверьте счётчик в кабинете «Продвижение → Обзор». - Для PHP:
curl -A "Googlebot" https://ваш-сайт/— в «ИИ-ассистенты и роботы» появится заход бота.
#Открытые вопросы
- Техническое. В комментариях кода приёмника сказано «ответ всегда 204» и приведены пределы «~60/мин по адресу и ~600/мин по токену»; фактические значения иные (токен-бакеты, коды
429/403/500). Страница описывает фактическое поведение; комментарии в коде стоит поправить. - Техническое. Квота и пределы живут в памяти процесса — нужна ли общая (Redis) квота для публичных гарантий.
- Техническое. Единица «посетитель» невозможна в режиме
anonymousсерверного маячка: в публичном APIvisitorsв этом режиме равноnull(Чтение аналитики).