#Модули для сайтов
Статус: Доступно — Bitrix
sapport.connector1.2.1 и WordPresssapport-connector-wp1.1.1. Бета — FastAPIsapport-connector1.0.0 и Nuxt@sapport/nuxt-connector1.0.0: пакеты готовы, но в кабинете помечены «скоро» (не опубликованы).
Назначение: подключить сайт на CMS или фреймворке к Формула ИИ одним модулем: счётчик посещений, серверный маячок (виден роботам и ИИ-краулерам), чат, сбор поведения и публикация статей из Формула ИИ.
#Содержание
- Когда использовать
- Общее для всех модулей
- Bitrix
- WordPress
- FastAPI
- Nuxt
- Протокол коннектора для собственных модулей
- Открытые вопросы
#Когда использовать
| Ситуация | Решение |
|---|---|
| Сайт на Bitrix (не облачный Битрикс24) | модуль Bitrix |
| Сайт на WordPress | модуль WordPress |
| Сайт на FastAPI + PostgreSQL | модуль FastAPI (+ Nuxt для фронта) — Бета |
| Другая платформа, нужен только счётчик | JS-трекер по токену |
| Другая платформа, нужны чат и поведение | Загрузчик |
| Собственный модуль для нестандартной платформы | раздел Протокол коннектора |
#Общее для всех модулей
#Доступ
| Кто привязывает | пользователь кабинета с доступом к разделу «Продвижение → Система → Сайты (модуль)»; ключ трекера выдаёт право seo.manage |
| Платно | нет, отдельной платы за модуль нет |
| Персональные данные | хеши IP и User-Agent, страна (в режиме full); см. Обзор |
#Что делает модуль
| Возможность | Описание |
|---|---|
| Серверный маячок | после ответа страницы модуль отправляет на облако подписанный хит (путь, реферер, User-Agent, IP). Видит роботов, которые JS не исполняют |
| Загрузчик | в <head> выводится тег loader.js (счётчик, поведение, чат) |
| Heartbeat | раз в час модуль сообщает о состоянии и получает конфигурацию |
| Публикатор | забирает у облака задания на публикацию статей и применяет их (по умолчанию — черновиками) |
| Выключатель | отключение сайта в кабинете останавливает все части |
#Как привязать сайт: код привязки
- В кабинете: «Продвижение → Система → Сайты (модуль)» → добавьте домен → получите код привязки.
- Код имеет префикс ячейки:
RU-…,EN-…илиID-…. Он живёт 15 минут и одноразовый. Код чужой ячейки даёт ошибку «код не найден». - Введите код в модуле. Модуль обменивает его на
site_id, публичный ключ, секрет и ключ маячка (секрет отдаётся один раз). - Если код истёк или использован, нажмите «Новый код». «Отключить» отвязывает сайт на стороне облака.
Состояния сайта в кабинете: pending (код выдан, привязки нет), bound (привязан), disabled (выключен).
Привязка допускает только зарегистрированный домен. Алиас домена или другой хост даёт ошибку domain_mismatch (при привязке) или 400 (на серверном маячке); www. поддерживается, если модуль его учитывает.
#Скачивание
Архивы и контрольные суммы SHA-256 — в кабинете: «Настройки → Интеграции → Модули для сайтов». Сверяйте сумму перед установкой.
| Модуль | Версия | Файл | Статус |
|---|---|---|---|
| Bitrix | 1.2.1 | /connector/sapport.connector-1.2.1.zip | Доступно |
| WordPress | 1.1.1 | /connector/sapport-connector-wp-1.1.1.zip | Доступно |
| FastAPI | 1.0.0 | sapport_connector-1.0.0-py3-none-any.whl + архив документации | Бета, не опубликован |
| Nuxt | 1.0.0 | sapport-nuxt-connector-1.0.0.tgz | Бета, не опубликован |
Файлы берутся с домена своей ячейки (RU https://formula-cream.pro, EN https://wfacademy.org, ID https://wfacademy.id).
#Режимы серверного маячка
server_beacon | Что отправляется | Для кого по умолчанию |
|---|---|---|
full | путь, реферер, User-Agent, IP, страна | RU |
anonymous | то же, но облако не хранит хеши IP/UA, образец UA и страну | EN, ID |
off | ничего | — |
#Bitrix: sapport.connector 1.2.1
Статус: Доступно.
#Требования
| Редакция | любая, начиная с «Старт» (не облачный Битрикс24) |
| PHP | 7.4–8.3 с расширением curl |
| Сеть | исходящий HTTPS к домену вашей ячейки |
| Для публикатора | модуль iblock, расширение sodium, право CREATE TABLE |
#Установка
- Распакуйте архив в
/local/modules/. - В административной части откройте «Marketplace → Установленные решения» (
/bitrix/admin/partner_modules.php) и нажмите «Установить» у «Sapport: коннектор». - Получите в кабинете Формула ИИ код привязки (см. выше).
- «Настройки → Настройки продукта → Настройки модулей → Sapport: коннектор» → введите код → «Привязать».
- Нажмите «Проверить связь».
Рекомендации:
- Включите агенты Bitrix на cron (иначе heartbeat и публикатор запаздывают).
- Если сайт работает за прокси и передаёт
X-Forwarded-For, отметьте «Сайт работает за прокси» — иначе IP посетителя заменится адресом прокси.
#Что делает модуль
| Функция | Описание |
|---|---|
| Маячок | на init.php-цикле отправляет подписанный хит; пропускает CLI, /bitrix, upload, local/templates, статику, ajax, не-GET и запросы без text/html в Accept |
| Загрузчик | выводит тег loader.js |
| Контекст страницы | \Sapport\Connector\Loader::setPage('iblock_element', $id); сообщает чату, о какой странице речь |
| Публикатор | создаёт материалы в инфоблоках из заданий облака. По умолчанию — режим черновика; служебные свойства SAPPORT_SOURCE_ID, SAPPORT_SOURCE_HASH, SAPPORT_VERSION, SAPPORT_JOB; журнал в таблице b_sapport_connector_ledger |
| Разделы | разрешённые разделы инфоблока (до 500) |
| IndexNow | уведомляет поисковики о новых страницах (до 100 за запуск) |
| Карта сайта | /sapport-sitemap.xml (до 50 000 адресов); отдаёт 404, если модуль SEO обновляет карту автоматически |
#Настройки
| Параметр | Назначение |
|---|---|
| Код привязки | одноразовый, из кабинета |
| Сайт работает за прокси | доверять X-Forwarded-For |
| Режим публикатора | черновик (по умолчанию) или публикация, если разрешено потолком |
| Разрешённые разделы | куда публикатор вправе создавать материалы |
| Индексация | IndexNow, карта сайта |
Включённость частей (tracker, behaviour, chat, режим согласия, режим маячка) задаётся в кабинете.
#Проверка
- Кнопка «Проверить связь» → успех.
- В кабинете состояние сайта —
bound. - После визита с обычного браузера в «Обзоре» растёт счётчик; бот-хит можно проверить
curl -A "Googlebot" https://ваш-сайт/. - Страница отдаёт тег
loader.js?k=…в<head>.
#Обновление и удаление
- Обновление: замените содержимое папки модуля новой версией; перепривязка не нужна. Если облако ответит
update_required(unknown_kidилиkid_wrong_cell), обновите модуль: он не знает ключ подписи заданий. - Удаление: Marketplace → «Удалить». Отвяжите сайт заранее («Отключить» в кабинете), иначе привязка останется на стороне облака.
#Частые проблемы
| Симптом | Причина и решение |
|---|---|
| Нет хитов от роботов | композитный кэш Bitrix отдаёт страницы, не вызывая PHP; маячок их не видит |
| Состояние «ошибка ключа» | облако отклонило подпись 3 раза подряд. Секрет повреждён или сайт переиздан: отвяжите и привяжите заново |
code_not_found | код истёк, использован или от другой ячейки (чужой префикс) |
| IP посетителей одинаков | включите «Сайт работает за прокси» |
#Безопасность
Секрет привязки хранится в таблице b_option в открытом виде, поэтому резервные копии базы содержат его. Перевыпуск секрета — только отвязкой и новой привязкой.
#WordPress: sapport-connector-wp 1.1.1
Статус: Доступно.
#Требования
| WordPress | 6.0 и выше |
| PHP | 7.4 и выше (в кабинете указано 7.4–8.3) |
| Cron | WP-Cron должен работать: heartbeat раз в час, публикатор раз в 10 минут |
| Сеть | исходящий HTTPS к домену ячейки |
#Установка
- «Плагины → Добавить новый → Загрузить плагин», выберите zip, нажмите «Установить» и «Активировать».
- «Настройки → Формула ИИ».
- Вставьте код привязки → «Подключить».
- Нажмите «Проверить связь».
#Что делает плагин
| Функция | Описание |
|---|---|
| Маячок | хук template_redirect |
| Загрузчик | тег в wp_head |
| Контекст страницы | window.sapportPage заполняется автоматически; изменить можно фильтром sapport_connector_page_context |
| Публикатор | создаёт записи из заданий облака; назначается автор (Author/Editor), тип записи, разрешённые рубрики, предел режима; подпись заданий (Ed25519) проверяется |
| Индексация | карты сайта WordPress Core, Yoast, Rank Math, AIOSEO; IndexNow (файл ключа требует «красивых» ссылок) |
#Особенности
| Тема | Что учесть |
|---|---|
Режим anonymous | плагин отправляет путь и реферер без query-строки, поэтому UTM из серверного маячка теряются; UTM придут только от JS-счётчика |
| Мультисайт | работает по сайту; мультисайт с подкаталогами не поддерживается |
| Автообновление | не выполняется, обновляйте вручную |
| Внешние сервисы | IndexNow отправляет адреса на api.indexnow.org |
#Проверка, обновление, удаление
- Проверка: «Проверить связь» → успех; в кабинете состояние
bound; в<head>присутствуетloader.js?k=…. - Обновление: загрузите новый zip поверх (автообновления нет).
- Удаление: сначала «Отключить» в кабинете, затем деактивируйте и удалите плагин.
#Частые проблемы
| Симптом | Причина и решение |
|---|---|
| Heartbeat не приходит | WP-Cron отключён или сайт без трафика: настройте системный cron на wp-cron.php |
Нет UTM в режиме anonymous | ожидаемо, см. выше |
| IndexNow не работает | отключены «красивые» ссылки |
#FastAPI: sapport-connector 1.0.0 (Бета)
Статус: Бета. Пакет собран и описан, но в кабинете помечен «скоро / Пакет готовится»; файлов на странице скачивания пока нет.
#Требования
Python 3.11 и новее, PostgreSQL (та же база, где лежат статьи сайта), исходящий HTTPS к домену ячейки. Модуль не открывает входящих адресов для облака.
#Установка и привязка
# 1. Проверьте контрольную сумму файла из кабинета
sha256sum sapport_connector-1.0.0-py3-none-any.whl
# 2. Установите
pip install "./sapport_connector-1.0.0-py3-none-any.whl[postgres]"
# 3. Создайте таблицы модуля
sapport-connector migrate
# 4. Привяжите домен кодом из кабинета
SAPPORT_SITE__RU_MAIN__HOST=example.ru \
sapport-connector bind --site ru_main --code RU-XXXXXXXXXX \
--secret-file /run/secrets/sapport_ru_main --env-file /etc/sapport/sapport.env
# 5. Самопроверка: все строки [OK]
sapport-connector selftest
# 6. Запустите worker (systemd/supervisor) или cron: sapport-connector run-once
sapport-connector worker
Команды CLI: bind, migrate, selftest, run-once, status, worker, unbind (необратима). Имя на PyPI занято заглушкой — ставьте только архив из кабинета.
#Переменные окружения
| Переменная | Обязательна | Смысл |
|---|---|---|
SAPPORT_SITES | да | ключи привязок через запятую, например ru_main |
SAPPORT_SITE__<KEY>__HOST | да | домен без схемы и порта |
SAPPORT_SITE__<KEY>__CELL | да | ru | en | id |
SAPPORT_SITE__<KEY>__ID | после bind | site_id |
SAPPORT_SITE__<KEY>__SECRET_FILE | да (worker) | путь к файлу секрета с правами 0600 |
SAPPORT_SITE__<KEY>__PUBLISHER | нет | on включает публикатор (по умолчанию off) |
SAPPORT_SITE__<KEY>__CEILING | нет | потолок режима: draft (по умолчанию) или publish |
SAPPORT_DATABASE_URL | да | строка подключения PostgreSQL |
SAPPORT_ADAPTER | для публикатора | модуль:фабрика, возвращающая адаптер ваших статей |
Секрет записывается в файл, а не в переменную окружения. Полный перечень и контракт адаптера статей — в документации пакета (README, INTEGRATION, ADAPTER, PROTOCOL, ERRORS, ACCEPTANCE, SECURITY, CSP, OPERATIONS, COMPATIBILITY, TROUBLESHOOTING).
#Что нужно написать вам
Публикатор требует адаптер под вашу таблицу статей (контракт — ADAPTER), а обложки — класс медиахранилища на общем для реплик хранилище. Без медиахранилища статьи публикуются без обложки. Пока публикатор выключен, модуль только поддерживает связь и heartbeat.
#Проверка
sapport-connector status и selftest; в кабинете сайт bound. Для подробной диагностики веб-процесса подключите healthz_router() и закройте адрес на обратном прокси.
#Nuxt: @sapport/nuxt-connector 1.0.0 (Бета)
Статус: Бета. Пакет не опубликован.
Nuxt-часть работает вместе с Python-worker: привязывает сайт worker, а Nuxt получает только производный ключ маячка. Им нельзя забрать задания или отвязать сайт.
#Требования
Nuxt 3.13+ или 4.x в режиме Node-сервера (Nitro 2, Node 18.17+; для Nuxt 4 — Node 20+). Nuxt 5 не поддерживается.
#Установка
sha256sum sapport-nuxt-connector-1.0.0.tgz
npm install ./sapport-nuxt-connector-1.0.0.tgz
// nuxt.config.ts
export default defineNuxtConfig({
modules: ['@sapport/nuxt-connector'],
sapport: {
exclude: ['/admin'],
trustedProxies: ['127.0.0.1'],
},
});
Ключ не пишется в nuxt.config. Переменные окружения сервера Nuxt:
SAPPORT_SITES=ru_main
SAPPORT_SITE__RU_MAIN__HOST=example.ru
SAPPORT_SITE__RU_MAIN__CELL=ru
SAPPORT_SITE__RU_MAIN__ID=<site_id>
SAPPORT_SITE__RU_MAIN__BEACON_KEY_FILE=/run/secrets/beacon/sapport_ru_main.beacon
NUXT_SAPPORT_DIAGNOSTICS_TOKEN=<случайная строка не короче 16 знаков>
Worker и Nuxt запускайте под разными пользователями ОС: файл корневого секрета не должен читаться процессом Nuxt.
#Использование в страницах
<script setup lang="ts">
useSapportPage({ type: 'article', id: article.id });
const consent = useSapportConsent();
</script>
<template>
<button @click="consent.grant()">Принять</button>
<button @click="consent.deny()">Отклонить</button>
</template>
#Диагностика
curl -s -H "Authorization: Bearer $NUXT_SAPPORT_DIAGNOSTICS_TOKEN" https://ваш-сайт/_sapport/health
Ожидается "ok": true, у привязки config.state: "valid", после первого просмотра beacon.sent ≥ 1.
#Ограничения
| Ограничение | Следствие |
|---|---|
SPA-переходы (NuxtLink) не делают запроса к серверу | серверный маячок их не видит; видит первую загрузку и перезагрузки |
| Prerender/SSG, ISR/SWR, кэш CDN и nginx | заходы из кэша не видны |
| Статический хостинг без Node | маячка нет, остаётся JS-счётчик загрузчика |
| Нет подписанной конфигурации | всё выключено (отказ закрыто); первая отрисовка ждёт облако до 1 с |
| Выключатель в кабинете | действует до 1 часа (срок снимка конфигурации) |
| Предел облака | 1200 хитов в минуту с адреса сервера; модуль ограничивает себя ~1000 в минуту на процесс |
| Очередь | 200 хитов, лишнее отбрасывается; повторов нет |
#Протокол коннектора для собственных модулей
Статус: Доступно для модулей, которые вы пишете сами. Протокол используют четыре готовых модуля; его перечень может расширяться совместимо.
Адрес: https://<домен ячейки>/api/v1/connector/…. Все запросы, кроме bind, подписываются HMAC.
#Подпись запроса
Заголовки:
| Заголовок | Значение |
|---|---|
X-Sapport-Site | site_id |
X-Sapport-Ts | unix-время в секундах |
X-Sapport-Nonce | 16–32 символа [A-Za-z0-9], одноразовый |
X-Sapport-Sig | hex HMAC-SHA256 от строки подписи |
Строка подписи (пять строк через \n):
<ts>
<nonce>
<METHOD>
<path без query-строки>
<sha256hex(тело запроса)>
- Допустимое расхождение времени — ±300 секунд.
- Nonce хранится 600 секунд; повтор даёт
401. Если хранилище nonce недоступно, ответ503. - Ключ HMAC — корневой секрет привязки. Для
track/visitиbeacon-configдопустим производный ключ маячка:
beacon_key = hex(HMAC-SHA256(secret, "sapport-beacon-v1:" + site_id))
Тестовые векторы подписи и заданий лежат в поставке модулей (tests/_vectors/, файлы signing-vectors.json, job-vectors.json). Не копируйте секреты из примеров документации в рабочие системы.
#Методы
| Метод и путь | Подпись | Назначение | Частота и лимиты |
|---|---|---|---|
POST /connector/bind | нет | обмен кода привязки на реквизиты сайта | 10 в минуту с адреса; тело ≤ 4096 байт |
POST /connector/heartbeat | да | состояние, получение конфигурации | раз в час; 120 в минуту; тело ≤ 512 КиБ |
GET /connector/jobs | да | задания публикации | 120 в минуту; не идемпотентен |
POST /connector/result | да | итог задания | 120 в минуту |
POST /connector/unbind | да | отвязка ({"reason":"manual"|"uninstall"}) | 120 в минуту |
GET /connector/beacon-config | да (допустим ключ маячка) | настройки маячка и загрузчика | 120 в минуту; Cache-Control: no-store |
POST /track/visit | да (допустим ключ маячка) | серверный хит | 1200 в минуту с адреса |
GET /connector/loader.js?k= | нет | загрузчик | кэш 5 минут |
#bind
POST /api/v1/connector/bind
Content-Type: application/json
{
"code": "RU-XXXXXXXXXX",
"site_url": "https://example.ru",
"cms": "fastapi_nuxt",
"module_version": "1.0.0"
}
| Поле | Тип | Обязательно | Ограничения | Пример |
|---|---|---|---|---|
code | string | да | код привязки; чужой префикс ячейки даёт 404 code_not_found | RU-XXXXXXXXXX |
site_url | string | да | адрес сайта; из него берётся хост | https://example.ru |
cms | string | да | bitrix | wordpress | fastapi_nuxt | bitrix |
module_version | string | нет | версия модуля | 1.2.1 |
cms_version, php_version, charset | string | нет | сведения об окружении, короткие строки | 8.2.0 |
Ответ 200:
{
"site_id": "00000000-0000-4000-8000-000000000000",
"public_key": "0123456789abcdef0123456789abcdef",
"secret": "EXAMPLE_SECRET_SHOWN_ONCE",
"beacon_key": "0000000000000000000000000000000000000000000000000000000000000000",
"api_base": "https://formula-cream.pro/api/v1",
"loader_url": "https://formula-cream.pro/api/v1/connector/loader.js?k=0123456789abcdef0123456789abcdef",
"config": { "tracker": true, "behaviour": false, "chat": false, "consent_mode": "wait", "server_beacon": "full" },
"disabled": false
}
secret возвращается один раз. Ошибки: 400/413 bad_request, 404 code_not_found (код неизвестен, истёк, использован или принадлежит другой ячейке), 409 domain_mismatch, 429 rate_limited, 500 internal.
#heartbeat
Ответ 200: { "config": {…}, "min_module_version": "1.2.1", "disabled": false, "pending_jobs": 0 }. Ответ 403 с { "disabled": true } означает, что сайт выключен.
#beacon-config
{
"tracker": true,
"server_beacon": "full",
"disabled": false,
"consent_mode": "wait",
"loader_url": "https://formula-cream.pro/api/v1/connector/loader.js?k=0123456789abcdef0123456789abcdef",
"public_key": "0123456789abcdef0123456789abcdef",
"ttl_seconds": 3600
}
Кэшируйте снимок на ttl_seconds.
#track/visit (серверный хит)
Поля тела описаны на странице JS/PHP-трекер. Особенности подписанного вызова:
- Хост хита берётся из реестра привязок. Если он не совпадает с зарегистрированным доменом, ответ
400. - Режим
server_beacon=off, выключенныйtrackerили отсутствие доступа арендатора дают403. - Режим
anonymousобнуляет хеши IP и User-Agent, образец UA и страну. - Дневная квота токена даёт
204без записи.
#jobs и result
Задания подписываются Ed25519 (поле kid с префиксом ячейки ru-/en-/id-, канонический JSON с сортировкой ключей в порядке UTF-16). Ответ на GET /jobs не идемпотентен: выданное, но не подтверждённое задание выдаётся повторно через 15 минут. Ошибка 503 signing_unavailable означает временную недоступность подписи заданий.
result принимает статус applied, skipped, conflict, failed. Первый присланный итог окончателен.
| Предел | Значение |
|---|---|
| HTML статьи | 2 000 000 байт |
| Полезная нагрузка задания | 3 000 000 байт |
Ответ /jobs | 4 МиБ |
| Обложка | 5 МиБ, до 12 000 px, до 50 Мп |
| Возраст подписи | до 7 дней; issued_at из будущего более чем на 5 минут отклоняется |
Пределы статьи едины для облака и модулей: HTML не более 2 000 000 байт, полезная нагрузка задания не более 3 000 000 байт. Подробнее — Статьи.
#Рекомендации для собственного модуля
- Подписывайте тело ровно теми байтами, что отправляете.
- Считайте серверный хит статистикой: не повторяйте при ошибке, не блокируйте ответ страницы (разумный таймаут — 150–200 мс).
- Не отдавайте корневой секрет фронтенду: для маячка достаточно производного ключа.
#Открытые вопросы
- Техническое. FastAPI и Nuxt: реальное наличие файлов в каталоге раздачи не проверялось; в кабинете модуль помечен «скоро». До публикации пакетов страницы остаются Бета.
- Техническое. Модуль Bitrix, режим
anonymous: WordPress обнуляет query-строку на своей стороне, а облако в режимеfullчитает UTM из query. Нужно решить единое правило для всех модулей. - К владельцу. Значение
cmsдля собственных модулей: допустимы толькоbitrix,wordpress,fastapi_nuxt. Как регистрировать модуль на другой платформе, не определено. - Техническое. Путь к настройкам в Bitrix: README модуля называет раздел кабинета «подключение сайтов» без пути; здесь использован путь из интерфейса «Продвижение → Система → Сайты (модуль)».