ws-stat / simple-metrics-stats
Symfony data analytics and collection bundle
Package info
github.com/ladovod444/simple-metrics-stats
Type:symfony-bundle
pkg:composer/ws-stat/simple-metrics-stats
Requires
- php: >=8.3
- doctrine/dbal: ^3.0|^4.0
- symfony/console: ^6.4|^7.0|^8.0
- symfony/framework-bundle: ^6.4|^7.0|^8.0
- symfony/serializer: ^6.4 || ^7.2 || ^8.0
- symfony/yaml: ^6.4|^7.0|^8.0
Requires (Dev)
- phpunit/phpunit: ^10.0|^11.0
Suggests
None
Provides
None
Conflicts
None
Replaces
None
This package is auto-updated.
Last update: 2026-09-24 08:19:03 UTC
README
Demo package
Symfony-бандл для сбора и анализа данных по аналитике.
Возможности
- Сбор аналитики
- Режим
--dry-runдля предварительного просмотра - Интерактивное подтверждение
Установка
composer require ws/simple-metrics-stats
После установки пакета выполните
php bin/console doctrine:migrations:diff
php bin/console doctrine:migrations:migrate
в основном проекте
Описание сущностей Keyword и KeywordPosition
Keyword
Хранит метаданные о ключевой фразе. Сам по себе он не хранит историю изменений позиций (для этого есть связанная сущность KeywordPosition), он выступает как "якорь" или справочник, к которому привязываются ежедневные замеры позиций.
(Поля таблицы keywords БД / св-ва сущности)
-
$id (int): Первичный ключ (Primary Key). Генерируется автоматически базой данных (GeneratedValue).
-
$site (Site): Связь "Многие-к-одному" (ManyToOne). Указывает, какому именно сайту принадлежит это ключевое слово. onDelete: 'CASCADE' означает, что если сайт будет удален из системы, все привязанные к нему ключевые слова удалятся автоматически.
-
$phrase (string): Сама поисковая фраза (например, "купить iphone 18"). Ограничена 255 символами.
-
$region (string): Код региона для поиска (например, "ru", "213" для Москвы в Яндекс.Вебмастере, "saint-petersburg"). По умолчанию равен "ru".
-
$createdAt (\DateTimeImmutable): Дата и время добавления ключевого слова в систему. Используется неизменяемый объект даты (Immutable), что является хорошей практикой, чтобы случайно не изменить дату создания. По умолчанию ставится текущее время (CURRENT_TIMESTAMP).
-
$positions (Collection): Связь "Один-ко-многим" (OneToMany). Это коллекция объектов KeywordPosition, хранящих историю позиций данного ключевого слова по дням.
KeywordPosition
Фиксирует состояние поисковой выдачи для заданного ключевого слова в конкретный день. Он отвечает на вопросы: "На каком месте был сайт по фразе X вчера?", "Как менялась частотность запроса за последний месяц?".
(Поля таблицы keyword_positions БД / св-ва сущности)
-
$id (int): Первичный ключ (Primary Key). Автоинкремент.
-
$keyword (Keyword): Связь "Многие-к-одному" (ManyToOne). Указывает, к какому именно ключевому слову относится эта запись. onDelete: 'CASCADE' гарантирует, что при удалении ключевого слова вся его история позиций будет автоматически и безопасно удалена из базы данных, не оставляя "висячих" (orphan) записей.
-
$date (\DateTimeImmutable): Дата замера позиции. Используется тип DATE_IMMUTABLE (хранит только дату, без времени), что идеально подходит для ежедневной статистики и экономит место в БД. Неизменяемость (Immutable) защищает от случайных ошибок в коде, которые могли бы изменить дату исторической записи.
-
$position (?int): Текущая позиция в выдаче. Важная деталь: Поле nullable: true. Как указано в комментарии, NULL означает, что сайт не найден в ТОП-100 (или в другом заданном диапазоне парсинга).
-
$searchVolume (int): Поисковая частотность (объем поиска) на момент замера. Частотность запросов меняется со временем (сезонность, изменение алгоритмов Яндекса/Google). Хранение частотности в ежедневном снапшоте позволяет строить исторически точные отчеты: "В январе частотность была 1000, а в феврале упала до 500, хотя позиция осталась прежней".
Принцип работы
-
Система создает объект Keyword для фразы "купить iphone" и региона "Москва" для сайта example.com.
-
Раз в день скрипт проверяет позиции в Яндексе/Google.
-
Скрипт создает новый объект KeywordPosition (с датой, позицией 5, поисковиком "yandex") и добавляет его в этот Keyword через метод addPosition().
-
При вызове $entityManager->flush() Doctrine одним транзакционным запросом сохранит и ключевое слово (если оно новое), и его новую позицию в историю.
DailyStat
DailyStat - это агрегированный дашборд за день. Он объединяет в одной таблице метрики как из систем веб-аналитики (Яндекс.Метрика / Google Analytics), так и из панелей вебмастера (Яндекс.Вебмастер / Google Search Console). фиксирует "снимок" (снапшот) всех ключевых показателей сайта за конкретную дату. Это позволяет строить сводные графики трафика, видимости и поведенческих факторов без необходимости каждый раз делать сложные JOIN и агрегации (SUM, AVG) по миллионам записей таблицы keyword_positions.
(Поля таблицы daily_stats БД / св-ва сущности)
Поля логически делятся на 4 группы:
А. Идентификация и связи:
-
$id: Первичный ключ.
-
$site: Связь "Многие-к-одному" с сайтом. onDelete: 'CASCADE' гарантирует очистку статистики при удалении сайта.
-
$date: Дата, за которую собраны показатели (DATE_IMMUTABLE).
-
$createdAt: Время создания записи в базе (автоматически CURRENT_TIMESTAMP).
Б. Метрики трафика (Аналитика - Метрика/GA):
-
$visits: Количество визитов (сессий).
-
$pageviews: Количество просмотров страниц.
-
$bounceRate: Показатель отказов (в процентах).
-
$avgSessionSec: Средняя длительность сеанса в секундах.
В. Метрики поисковой выдачи (Вебмастер/GSC):
-
$impressions: Количество показов сайта в поисковой выдаче.
-
$clicks: Количество переходов из поиска.
-
$ctr: CTR (Click-Through Rate, кликабельность) в процентах (DECIMAL).
-
$avgPosition: Средняя позиция сайта по всем запросам за день (DECIMAL).
Г. SEO-здоровье (производные метрики):
-
$competitorsCount: Количество сайтов-конкурентов в ТОП-10 (полезно для оценки сложности ниши).
-
$top3Count: Количество ключевых слов сайта, находящихся в ТОП-3 выдачи.
Принцип работы
Система работает по принципу агрегации на записи (Write-heavy, Read-light):
- Раз в сутки (или по расписанию) скрипт собирает сырые данные из API Яндекса/Google.
- Он рассчитывает сводные показатели (общие клики, средний CTR, количество слов в ТОП-3).
- Он создает одну запись DailyStat за этот день и сохраняет её.
- Когда пользователь открывает дашборд, фронтенд делает один быстрый запрос к API, который отдает массив объектов DailyStat за выбранный период. График строится мгновенно.
Site
Представляет собой корневую сущность (Aggregate Root) всей SEO-системы. Является центральным узлом, который объединяет всё воедино.
(Поля таблицы sites БД / св-ва сущности)
-
$id: Первичный ключ.
-
$domain: Доменное имя (например, example.com). Важно: Атрибут unique: true гарантирует на уровне базы данных, что один и тот же домен нельзя добавить в систему дважды.
-
$name: Человеко-понятное название проекта (например, "Интернет-магазин шин"). Поле nullable: true, так как для некоторых проектов достаточно только домена.
-
$createdAt: Дата добавления сайта в систему (DATETIME_IMMUTABLE).
-
$keywords: Коллекция (OneToMany) всех ключевых слов, отслеживаемых для этого сайта.
-
$dailyStats: Коллекция (OneToMany) ежедневных сводных отчетов для этого сайта.
Итоговая архитектура вашей системы
Иерархия базы данных:
Site (Корень): Хранит домен. Управляет удалением всего, что с ним связано.
DailyStat (Ветвь 1): Хранит агрегированные цифры за день (трафик, клики, CTR) для этого сайта.
Keyword (Ветвь 2): Хранит конкретную фразу и регион для этого сайта.
KeywordPosition (Лист): Хранит историю позиций (снапшоты) для конкретного Keyword в конкретный день.