From ec0b0cd92a3d72ccbeeaa8798d821d071dacc8d4 Mon Sep 17 00:00:00 2001 From: sgiehl Date: Mon, 17 Nov 2025 14:02:40 +0100 Subject: [PATCH 01/13] Adds archiving for new report(s) --- config/global.ini.php | 5 + plugins/BotTracking/Archiver.php | 23 ++ plugins/BotTracking/Metrics.php | 20 ++ .../RecordBuilders/AIAssistantReports.php | 219 ++++++++++++++++++ 4 files changed, 267 insertions(+) create mode 100644 plugins/BotTracking/Archiver.php create mode 100644 plugins/BotTracking/Metrics.php create mode 100644 plugins/BotTracking/RecordBuilders/AIAssistantReports.php diff --git a/config/global.ini.php b/config/global.ini.php index 9e471c0cd78..eef5511a0d3 100644 --- a/config/global.ini.php +++ b/config/global.ini.php @@ -632,6 +632,11 @@ ; maximum number of rows for the Products reports datatable_archiving_maximum_rows_products = 10000 +; maximum number of AI Assistants listed in Bot Tracking reports +datatable_archiving_maximum_rows_bots = 250 +; maximum number of page/document rows listed per AI Assistant in Bot Tracking reports +datatable_archiving_maximum_rows_subtable_bots = 250 + ; maximum number of rows for other tables (Providers, User settings configurations) datatable_archiving_maximum_rows_standard = 500 diff --git a/plugins/BotTracking/Archiver.php b/plugins/BotTracking/Archiver.php new file mode 100644 index 00000000000..d52fd62b7f8 --- /dev/null +++ b/plugins/BotTracking/Archiver.php @@ -0,0 +1,23 @@ + + */ + private const ASSISTANT_MAPPING = [ + 'ChatGPT-User' => 'ChatGPT', + 'MistralAI-User' => 'Le Chat', + 'Gemini-Deep-Research' => 'Gemini', + 'Claude-User' => 'Claude', + 'Perplexity-User' => 'Perplexity', + 'Google-NotebookLM' => 'NotebookLM', + 'Devin' => '', + ]; + + public function __construct() + { + parent::__construct(); + + $this->columnToSortByBeforeTruncation = Metrics::COLUMN_REQUESTS; + $this->maxRowsInTable = (int)GeneralConfig::getConfigValue('datatable_archiving_maximum_rows_bots'); + $this->maxRowsInSubtable = (int)GeneralConfig::getConfigValue('datatable_archiving_maximum_rows_subtable_bots'); + } + + public function getRecordMetadata(ArchiveProcessor $archiveProcessor): array + { + return [ + Record::make(Record::TYPE_BLOB, Archiver::AI_ASSISTANTS_PAGES_RECORD), + Record::make(Record::TYPE_BLOB, Archiver::AI_ASSISTANTS_DOCUMENTS_RECORD), + ]; + } + + public function isEnabled(ArchiveProcessor $archiveProcessor): bool + { + // don't process reports for any segment + return $archiveProcessor->getParams()->getSegment()->isEmpty(); + } + + protected function aggregate(ArchiveProcessor $archiveProcessor): array + { + $tables = [ + Archiver::AI_ASSISTANTS_PAGES_RECORD => new DataTable(), + Archiver::AI_ASSISTANTS_DOCUMENTS_RECORD => new DataTable(), + ]; + + $this->populateTables($archiveProcessor, $tables); + + return $tables; + } + + /** + * @param array $tables + */ + private function populateTables(ArchiveProcessor $archiveProcessor, array &$tables): void + { + $logAggregator = $archiveProcessor->getLogAggregator(); + $params = $archiveProcessor->getParams(); + $sites = $params->getIdSites(); + + if (empty($sites)) { + return; + } + + $visits = $this->queryAcquiredVisitsByAIAssistant($logAggregator); + + $this->populateTableForActionType($tables, Action::TYPE_PAGE_URL, $logAggregator, $visits); + $this->populateTableForActionType($tables, Action::TYPE_DOWNLOAD, $logAggregator, $visits); + } + + /** + * @return array + */ + private function queryAcquiredVisitsByAIAssistant(LogAggregator $logAggregator): array + { + $where = $logAggregator->getWhereStatement('log_visit', 'visit_last_action_time'); + $bindBase = $logAggregator->getGeneralQueryBindParams(); + + $sql = sprintf( + "SELECT `referer_name`, COUNT(*) AS `visits` + FROM %s AS `log_visit` + WHERE `referer_type` = %d + AND `referer_name` <> '' + AND %s + GROUP BY `referer_name`", + Common::prefixTable('log_visit'), + Common::REFERRER_TYPE_AI_ASSISTANT, + $where + ); + + $stmt = Db::query($sql, $bindBase); + $result = []; + + while ($row = $stmt->fetch()) { + /** + * @var array{visits: string|int, referer_name: string} $row + */ + if (in_array($row['referer_name'], self::ASSISTANT_MAPPING)) { + $key = (string)array_search($row['referer_name'], self::ASSISTANT_MAPPING); + $result[$key] = (int)$row['visits']; + } + } + + return $result; + } + + /** + * @param array $tables + * @param array $visits + * @return void + */ + private function populateTableForActionType(array $tables, int $actionType, LogAggregator $logAggregator, array $visits): void + { + $where = $logAggregator->getWhereStatement('bot', 'server_time'); + $bindBase = $logAggregator->getGeneralQueryBindParams(); + + $sql = sprintf( + "SELECT * FROM (SELECT bot.bot_name, log_action.name AS url, COUNT(*) AS requests + FROM %s AS bot + INNER JOIN %s AS log_action ON log_action.idaction = bot.idaction_url + WHERE log_action.name IS NOT NULL + AND log_action.name <> '' + AND log_action.type = %d + AND %s + GROUP BY bot.bot_name, url WITH ROLLUP) AS rollupQuery + ORDER BY bot_name, requests DESC, url", + BotRequestsDao::getPrefixedTableName(), + Common::prefixTable('log_action'), + $actionType, + $where + ); + + $resultSet = Db::query($sql, $bindBase); + $actionRows = []; + + while ($row = $resultSet->fetch()) { + /** + * @var array{requests: int, bot_name: ?string, url: ?string} $row + */ + $label = $row['bot_name']; + $url = $row['url']; + + if (is_null($label)) { + continue; + } + + if (!is_null($url)) { + $actionRows[] = $row; + continue; + } + + $metrics = [ + Metrics::COLUMN_REQUESTS => $row['requests'], + Metrics::COLUMN_DOCUMENT_REQUESTS => $actionType === Action::TYPE_DOWNLOAD ? $row['requests'] : 0, + Metrics::COLUMN_PAGE_REQUESTS => $actionType === Action::TYPE_PAGE_URL ? $row['requests'] : 0, + Metrics::COLUMN_ACQUIRED_VISITS => $visits[$label] ?? 0, + ]; + + // we add all records to both tables, so we in the end have the total count of pages & documents in the main table + $tables[Archiver::AI_ASSISTANTS_PAGES_RECORD]->sumRowWithLabel($label, $metrics); + $tables[Archiver::AI_ASSISTANTS_DOCUMENTS_RECORD]->sumRowWithLabel($label, $metrics); + } + + $table = $tables[Archiver::AI_ASSISTANTS_PAGES_RECORD]; + + if ($actionType === Action::TYPE_DOWNLOAD) { + $table = $tables[Archiver::AI_ASSISTANTS_DOCUMENTS_RECORD]; + } + + // use while / array_shift combination instead of foreach to save memory + while (is_array($actionRows) && count($actionRows)) { + /** + * @var array{requests: int, bot_name: string, url: string} $row + */ + $row = array_shift($actionRows); + $label = $row['bot_name']; + $url = $row['url']; + + $tableRow = $table->getRowFromLabel($label); + + if (empty($tableRow)) { + continue; + } + + $normalized = PageUrl::normalizeUrl($url); + $url = $normalized['url']; + + $tableRow->sumRowWithLabelToSubtable($url, [ + Metrics::COLUMN_REQUESTS => $row['requests'], + ]); + } + } +} From 893fde85f105c11fc000f1adebc34711d9b2fdca Mon Sep 17 00:00:00 2001 From: sgiehl Date: Mon, 17 Nov 2025 14:04:05 +0100 Subject: [PATCH 02/13] Add API methods for new report --- plugins/BotTracking/API.php | 76 +++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 plugins/BotTracking/API.php diff --git a/plugins/BotTracking/API.php b/plugins/BotTracking/API.php new file mode 100644 index 00000000000..b9717847782 --- /dev/null +++ b/plugins/BotTracking/API.php @@ -0,0 +1,76 @@ +filter(function (DataTable $table) { + foreach ($table->getRows() as $key => $row) { + if (!$row->getIdSubDataTable()) { + $table->deleteRow($key); + } + } + }); + } + + return $dataTable; + } + + /** + * @param string|int|int[] $idSite + * @return DataTable|DataTable\Map + */ + public function getPageUrlsForAIAssistant($idSite, string $period, string $date, int $idSubtable): DataTableInterface + { + Piwik::checkUserHasViewAccess($idSite); + + return Archive::createDataTableFromArchive(Archiver::AI_ASSISTANTS_PAGES_RECORD, $idSite, $period, $date, '', false, false, $idSubtable); + } + + /** + * @param string|int|int[] $idSite + * @return DataTable|DataTable\Map + */ + public function getDocumentUrlsForAIAssistant($idSite, string $period, string $date, int $idSubtable): DataTableInterface + { + Piwik::checkUserHasViewAccess($idSite); + + return Archive::createDataTableFromArchive(Archiver::AI_ASSISTANTS_DOCUMENTS_RECORD, $idSite, $period, $date, '', false, false, $idSubtable); + } +} From a9f07deb0253cb36a4e46c105257022c13564bb9 Mon Sep 17 00:00:00 2001 From: sgiehl Date: Mon, 17 Nov 2025 14:05:26 +0100 Subject: [PATCH 03/13] Add report classes --- .../BotTracking/Columns/AIAssistantName.php | 20 ++++ plugins/BotTracking/Columns/DocumentUrl.php | 20 ++++ .../Columns/Metrics/AcquiredVisits.php | 46 +++++++++ .../Columns/Metrics/DocumentRequests.php | 46 +++++++++ .../Columns/Metrics/PageRequests.php | 46 +++++++++ .../BotTracking/Columns/Metrics/Requests.php | 46 +++++++++ plugins/BotTracking/Columns/PageUrl.php | 20 ++++ .../Reports/GetAIAssistantRequests.php | 96 +++++++++++++++++++ .../Reports/GetDocumentUrlsForAIAssistant.php | 32 +++++++ .../Reports/GetPageUrlsForAIAssistant.php | 32 +++++++ plugins/BotTracking/lang/en.json | 16 +++- 11 files changed, 419 insertions(+), 1 deletion(-) create mode 100644 plugins/BotTracking/Columns/AIAssistantName.php create mode 100644 plugins/BotTracking/Columns/DocumentUrl.php create mode 100644 plugins/BotTracking/Columns/Metrics/AcquiredVisits.php create mode 100644 plugins/BotTracking/Columns/Metrics/DocumentRequests.php create mode 100644 plugins/BotTracking/Columns/Metrics/PageRequests.php create mode 100644 plugins/BotTracking/Columns/Metrics/Requests.php create mode 100644 plugins/BotTracking/Columns/PageUrl.php create mode 100644 plugins/BotTracking/Reports/GetAIAssistantRequests.php create mode 100644 plugins/BotTracking/Reports/GetDocumentUrlsForAIAssistant.php create mode 100644 plugins/BotTracking/Reports/GetPageUrlsForAIAssistant.php diff --git a/plugins/BotTracking/Columns/AIAssistantName.php b/plugins/BotTracking/Columns/AIAssistantName.php new file mode 100644 index 00000000000..d5e87bed7aa --- /dev/null +++ b/plugins/BotTracking/Columns/AIAssistantName.php @@ -0,0 +1,20 @@ +getPrettyNumber($value); + } + + public function getSemanticType(): ?string + { + return Dimension::TYPE_NUMBER; + } +} diff --git a/plugins/BotTracking/Columns/Metrics/DocumentRequests.php b/plugins/BotTracking/Columns/Metrics/DocumentRequests.php new file mode 100644 index 00000000000..16ffb9ceedd --- /dev/null +++ b/plugins/BotTracking/Columns/Metrics/DocumentRequests.php @@ -0,0 +1,46 @@ +getPrettyNumber($value); + } + + public function getSemanticType(): ?string + { + return Dimension::TYPE_NUMBER; + } +} diff --git a/plugins/BotTracking/Columns/Metrics/PageRequests.php b/plugins/BotTracking/Columns/Metrics/PageRequests.php new file mode 100644 index 00000000000..87dc458df95 --- /dev/null +++ b/plugins/BotTracking/Columns/Metrics/PageRequests.php @@ -0,0 +1,46 @@ +getPrettyNumber($value); + } + + public function getSemanticType(): ?string + { + return Dimension::TYPE_NUMBER; + } +} diff --git a/plugins/BotTracking/Columns/Metrics/Requests.php b/plugins/BotTracking/Columns/Metrics/Requests.php new file mode 100644 index 00000000000..657c7286a14 --- /dev/null +++ b/plugins/BotTracking/Columns/Metrics/Requests.php @@ -0,0 +1,46 @@ +getPrettyNumber($value); + } + + public function getSemanticType(): ?string + { + return Dimension::TYPE_NUMBER; + } +} diff --git a/plugins/BotTracking/Columns/PageUrl.php b/plugins/BotTracking/Columns/PageUrl.php new file mode 100644 index 00000000000..cf6515736e8 --- /dev/null +++ b/plugins/BotTracking/Columns/PageUrl.php @@ -0,0 +1,20 @@ +name = Piwik::translate('BotTracking_AIAssistantsReportTitle'); + $this->documentation = Piwik::translate('BotTracking_AIAssistantsReportDocumentation'); + $this->categoryId = 'AIAgents_AIAssistants'; + $this->subcategoryId = 'General_Overview'; + $this->dimension = new AIAssistantName(); + $this->metrics = [ + new Requests(), + new PageRequests(), + new DocumentRequests(), + new AcquiredVisits(), + ]; + $this->processedMetrics = []; + $this->order = 30; + $this->defaultSortColumn = Metrics::COLUMN_ACQUIRED_VISITS; + if (\Piwik\Request::fromRequest()->getStringParameter('secondaryDimension', '') === 'documents') { + $this->actionToLoadSubTables = 'getDocumentUrlsForAIAssistant'; + } else { + $this->actionToLoadSubTables = 'getPageUrlsForAIAssistant'; + } + } + + public function configureView(ViewDataTable $view): void + { + parent::configureView($view); + + $view->config->show_table_all_columns = false; + $view->config->show_insights = false; + + // Show segment not supported message when a segment is selected + if (!empty(Request::getRawSegmentFromRequest())) { + $message = '

' . Piwik::translate('BotTracking_SegmentNotSupported') . '

'; + $view->config->show_header_message = $message; + } + + $view->config->setDefaultColumnsToDisplay( + ['label', Metrics::COLUMN_REQUESTS, Metrics::COLUMN_PAGE_REQUESTS, Metrics::COLUMN_DOCUMENT_REQUESTS, Metrics::COLUMN_ACQUIRED_VISITS], + false, + false + ); + + // only show request count for flat table, as subtable doesn't have other metrics + if ((int)$view->requestConfig->getRequestParam('flat') === 1) { + $view->config->setDefaultColumnsToDisplay( + ['label', Metrics::COLUMN_REQUESTS], + false, + false + ); + } + + $secondaryDimensions = [ + 'pages' => Piwik::translate('BotTracking_ColumnPageRequests'), + 'documents' => Piwik::translate('BotTracking_ColumnDocumentRequests'), + ]; + $view->config->setSecondaryDimensions($secondaryDimensions, 'pages'); + } + + /** + * @return void + */ + public function configureWidgets(WidgetsList $widgetsList, ReportWidgetFactory $factory) + { + $widgetsList->addWidgetConfig($factory->createWidget()->setOrder($this->order)); + } +} diff --git a/plugins/BotTracking/Reports/GetDocumentUrlsForAIAssistant.php b/plugins/BotTracking/Reports/GetDocumentUrlsForAIAssistant.php new file mode 100644 index 00000000000..8a0e994a90c --- /dev/null +++ b/plugins/BotTracking/Reports/GetDocumentUrlsForAIAssistant.php @@ -0,0 +1,32 @@ +name = Piwik::translate('BotTracking_AIAssistantsReportTitle'); + $this->categoryId = 'AIAgents_AIAssistants'; + $this->metrics = [new Requests()]; + $this->processedMetrics = []; + $this->dimension = new DocumentUrl(); + $this->isSubtableReport = true; + } +} diff --git a/plugins/BotTracking/Reports/GetPageUrlsForAIAssistant.php b/plugins/BotTracking/Reports/GetPageUrlsForAIAssistant.php new file mode 100644 index 00000000000..74f04bcff94 --- /dev/null +++ b/plugins/BotTracking/Reports/GetPageUrlsForAIAssistant.php @@ -0,0 +1,32 @@ +name = Piwik::translate('BotTracking_AIAssistantsReportTitle'); + $this->categoryId = 'AIAgents_AIAssistants'; + $this->metrics = [new Requests()]; + $this->processedMetrics = []; + $this->dimension = new PageUrl(); + $this->isSubtableReport = true; + } +} diff --git a/plugins/BotTracking/lang/en.json b/plugins/BotTracking/lang/en.json index 5ab7d81b4bf..95ba3d16a8a 100644 --- a/plugins/BotTracking/lang/en.json +++ b/plugins/BotTracking/lang/en.json @@ -1,5 +1,19 @@ { "BotTracking": { - "PluginDescription": "Track and analyze visits from AI bots such as ChatGPT-User and similar. This plugin helps you understand how AI-driven tools interact with your website by logging and reporting bot-triggered requests." + "AIAssistantsReportDocumentation": "Discover which AI assistants are crawling your site and how many hits each one generates. Expand a bot to review the most frequently requested pages or documents.", + "AIAssistantsReportTitle": "AI Assistants - Bots", + "ColumnAIAssistantName": "AI Assistant Name", + "ColumnAcquiredVisits": "Acquired visits", + "ColumnAcquiredVisitsDocumentation": "Visits that started after someone clicked from an AI assistant (Referrers \u2192 AI Assistants).", + "ColumnDocumentRequests": "Document Requests", + "ColumnDocumentRequestsDocumentation": "Total number of bot requests to document URLs recorded during the selected period.", + "ColumnPageRequests": "Page Requests", + "ColumnPageRequestsDocumentation": "Total number of bot requests to page URLs recorded during the selected period.", + "ColumnRequests": "Requests", + "ColumnRequestsDocumentation": "Total number of bot requests recorded during the selected period. Includes both page and document URLs.", + "DocumentUrl": "Document URL", + "PageUrl": "Page URL", + "PluginDescription": "Track and analyze visits from AI bots such as ChatGPT-User and similar. This plugin helps you understand how AI-driven tools interact with your website by logging and reporting bot-triggered requests.", + "SegmentNotSupported": "Report does not support segmentation. The data displayed is your standard, unsegmented report data." } } From 373aec590786b35dac5c0d8bc8092e626643a238 Mon Sep 17 00:00:00 2001 From: sgiehl Date: Mon, 17 Nov 2025 14:06:20 +0100 Subject: [PATCH 04/13] Move AI Agent reports to bottom --- plugins/AIAgents/Reports/Get.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/AIAgents/Reports/Get.php b/plugins/AIAgents/Reports/Get.php index 73a912d751b..33f60ff54c5 100644 --- a/plugins/AIAgents/Reports/Get.php +++ b/plugins/AIAgents/Reports/Get.php @@ -33,7 +33,7 @@ protected function init() $this->name = Piwik::translate('AIAgents_AIAgentVisits'); $this->categoryId = 'AIAgents_AIAssistants'; $this->subcategoryId = 'General_Overview'; - $this->order = 10; + $this->order = 90; $this->processedMetrics = [ new AIAgentMetric(new AverageTimeOnSite(), API::AI_AGENT_COLUMN_SUFFIX), @@ -66,14 +66,14 @@ public function configureWidgets(WidgetsList $widgetsList, ReportWidgetFactory $ ->setName('AIAgents_WidgetGraphAIAgents') ->forceViewDataTable(Evolution::ID) ->setAction('getEvolutionGraph') - ->setOrder(1) + ->setOrder(90) ); $widgetsList->addWidgetConfig( $factory->createWidget() ->forceViewDataTable(Sparklines::ID) ->setName('AIAgents_WidgetOverviewAIAgents') - ->setOrder(2) + ->setOrder(91) ); } From 89c6a3ea810337dc75f55f5be87561c11e135d7c Mon Sep 17 00:00:00 2001 From: sgiehl Date: Mon, 17 Nov 2025 14:51:21 +0100 Subject: [PATCH 05/13] Add system tests for new report --- .../BotTracking/tests/Fixtures/BotTraffic.php | 173 ++++++++++++++++++ plugins/BotTracking/tests/System/ApiTest.php | 95 ++++++++++ ...BotTracking.getAIAssistantRequests_day.xml | 41 +++++ ...otTracking.getAIAssistantRequests_week.xml | 94 ++++++++++ ...BotTracking.getAIAssistantRequests_day.xml | 27 +++ ...otTracking.getAIAssistantRequests_week.xml | 87 +++++++++ ...BotTracking.getAIAssistantRequests_day.xml | 53 ++++++ ...otTracking.getAIAssistantRequests_week.xml | 120 ++++++++++++ 8 files changed, 690 insertions(+) create mode 100644 plugins/BotTracking/tests/Fixtures/BotTraffic.php create mode 100644 plugins/BotTracking/tests/System/ApiTest.php create mode 100644 plugins/BotTracking/tests/System/expected/test__documents__BotTracking.getAIAssistantRequests_day.xml create mode 100644 plugins/BotTracking/tests/System/expected/test__documents__BotTracking.getAIAssistantRequests_week.xml create mode 100644 plugins/BotTracking/tests/System/expected/test__flat__BotTracking.getAIAssistantRequests_day.xml create mode 100644 plugins/BotTracking/tests/System/expected/test__flat__BotTracking.getAIAssistantRequests_week.xml create mode 100644 plugins/BotTracking/tests/System/expected/test__pages__BotTracking.getAIAssistantRequests_day.xml create mode 100644 plugins/BotTracking/tests/System/expected/test__pages__BotTracking.getAIAssistantRequests_week.xml diff --git a/plugins/BotTracking/tests/Fixtures/BotTraffic.php b/plugins/BotTracking/tests/Fixtures/BotTraffic.php new file mode 100644 index 00000000000..e0b5210d289 --- /dev/null +++ b/plugins/BotTracking/tests/Fixtures/BotTraffic.php @@ -0,0 +1,173 @@ +setUpWebsite(); + $this->trackBotRequests(); + $this->trackAcquiredVisits(); + } + + public function tearDown(): void + { + // nothing to clean up + } + + private function setUpWebsite(): void + { + if (!self::siteCreated($this->idSite)) { + self::createWebsite($this->dateTime, true, 'https://example.com'); + } + } + + private function trackBotRequests(): void + { + $pages = [ + 'https://example.com/article-1', + 'https://example.com/article-2', + 'https://example.com/article-3', + 'https://example.com/article-4', + 'https://example.com/article-5', + 'https://example.com/article-6', + ]; + + $downloads = [ + 'https://example.com/resources/doc.pdf', + 'https://example.com/resources/guide.pdf', + 'https://example.com/resources/whitepaper.pdf', + 'https://example.com/resources/datasheet.pdf', + 'https://example.com/resources/case-study.pdf', + ]; + + $dailyPlans = [ + 0 => [ + ['ChatGPT-User/1.0', $pages[0], 200, 12005, false], + ['Gemini-Deep-Research/1.0', $pages[1], 200, 29658, false], + ['Perplexity-User/1.0', $downloads[0], 503, 1365955, true], + ['Google-NotebookLM/1.0', $downloads[1], 404, 36522, true], + ['ChatGPT-User/1.0', $pages[0], 200, 12584, false], + ['Gemini-Deep-Research/1.0', $pages[1], 200, 36598, false], + ['Perplexity-User/1.0', $downloads[0], 200, 99562, true], + ['Google-NotebookLM/1.0', $pages[2], 200, 25489, false], + ], + 1 => [ + ['MistralAI-User/2.0', $pages[2], 200, 32485, false], + ['Claude-User/3.0', $downloads[2], 200, 123456, true], + ['ChatGPT-User/1.0', $pages[1], 500, 25896, false], + ['Perplexity-User/1.0', $pages[2], 200, 36985, false], + ['MistralAI-User/2.0', $pages[3], 200, 85236, false], + ['Claude-User/3.0', $downloads[3], 200, 12456, true], + ], + 2 => [ + ['Perplexity-User/1.0', $downloads[3], 200, 84269, true], + ['Gemini-Deep-Research/1.0', $pages[3], 200, 3265, false], + ['Devin/1.0', 'https://example.com/api', 200, 33366, false], + ['ChatGPT-User/1.0', $pages[3], 200, 5454, false], + ['Perplexity-User/1.0', $downloads[2], 200, 69856, true], + ['Gemini-Deep-Research/1.0', $pages[4], 200, 63256, false], + ['Devin/1.0', 'https://example.com/api', 200, 25486, false], + ], + 3 => [ + ['MistralAI-User/2.0', $pages[4], 200, 12568, false], + ['Google-NotebookLM/1.0', $downloads[4], 404, 25648, true], + ['ChatGPT-User/1.0', $pages[4], 200, 12548, false], + ['Claude-User/3.0', $pages[5], 503, 36598, false], + ['Perplexity-User/1.0', $downloads[0], 200, 225445, true], + ['MistralAI-User/2.0', $pages[2], 200, 12456, false], + ['Google-NotebookLM/1.0', $downloads[1], 200, 258741, true], + ], + 4 => [ + ['Perplexity-User/1.0', $downloads[1], 200, 36985, true], + ['Gemini-Deep-Research/1.0', $pages[5], 200, 95147, false], + ['ChatGPT-User/1.0', $pages[0], 200, 25412, false], + ['Claude-User/3.0', $pages[3], 200, 36985, false], + ['Perplexity-User/1.0', $downloads[4], 200, 145811, true], + ], + ]; + + foreach ($dailyPlans as $dayOffset => $requests) { + foreach ($requests as $index => $request) { + [$userAgent, $url, $status, $bytes, $isDownload] = $request; + $date = Date::factory($this->dateTime) + ->addDay($dayOffset) + ->addHour(($index + 1) * 2) + ->getDatetime(); + + if ($isDownload) { + $this->logBotDownload($userAgent, $url, $status, $bytes, $date); + } else { + $this->logBot($userAgent, $url, $status, $bytes, $date); + } + } + } + } + + private function trackAcquiredVisits(): void + { + $sources = [ + 'https://chatgpt.com/thread/12345', + 'https://perplexity.ai/share/6789', + 'https://copilot.microsoft.com/answer/abc', + 'https://claude.ai/share/987', + 'https://gemini.google.com/share/notes', + 'https://chat.qwen.ai/share/insight', + 'https://chatgpt.com/thread/8888', + 'https://perplexity.ai/share/2222', + 'https://copilot.microsoft.com/answer/xyz', + 'https://claude.ai/share/1111', + ]; + + foreach ($sources as $index => $referrer) { + $date = Date::factory($this->dateTime) + ->addDay($index % 5) + ->addHour(($index % 4) * 3) + ->getDatetime(); + $tracker = self::getTracker($this->idSite, $date, true); + $tracker->setUrl('https://example.com/article-' . (($index % 4) + 1)); + $tracker->setUrlReferrer($referrer); + self::checkResponse($tracker->doTrackPageView('Article From AI Assistant ' . ($index + 1))); + } + } + + private function logBot(string $userAgent, string $url, int $statusCode, int $bytes, string $dateTime): void + { + $tracker = self::getTracker($this->idSite, $dateTime, true); + $tracker->setUserAgent($userAgent); + $tracker->setUrl($url); + $tracker->setCustomTrackingParameter('recMode', '1'); + $tracker->setCustomTrackingParameter('http_status', (string) $statusCode); + $tracker->setCustomTrackingParameter('bw_bytes', (string) $bytes); + self::checkResponse($tracker->doTrackPageView('')); + } + + private function logBotDownload(string $userAgent, string $url, int $statusCode, int $bytes, string $dateTime): void + { + $tracker = self::getTracker($this->idSite, $dateTime, true); + $tracker->setUserAgent($userAgent); + $tracker->setCustomTrackingParameter('recMode', '1'); + $tracker->setCustomTrackingParameter('http_status', (string) $statusCode); + $tracker->setCustomTrackingParameter('bw_bytes', (string) $bytes); + self::checkResponse($tracker->doTrackAction($url, 'download')); + } +} diff --git a/plugins/BotTracking/tests/System/ApiTest.php b/plugins/BotTracking/tests/System/ApiTest.php new file mode 100644 index 00000000000..cdc01495d2a --- /dev/null +++ b/plugins/BotTracking/tests/System/ApiTest.php @@ -0,0 +1,95 @@ +runApiTests($api, $params); + } + + public function getApiForTesting() + { + return [ + [ + [ + 'BotTracking.getAIAssistantRequests', + ], + [ + 'idSite' => 1, + 'date' => '2025-02-03', + 'periods' => ['day', 'week'], + 'otherRequestParameters' => [ + 'expanded' => 1, + 'secondaryDimension' => 'pages', + ], + 'testSuffix' => '_pages', + ], + ], + [ + [ + 'BotTracking.getAIAssistantRequests', + ], + [ + 'idSite' => 1, + 'date' => '2025-02-03', + 'periods' => ['day', 'week'], + 'otherRequestParameters' => [ + 'flat' => 1, + ], + 'testSuffix' => '_flat', + ], + ], + [ + [ + 'BotTracking.getAIAssistantRequests', + ], [ + 'idSite' => 1, + 'date' => '2025-02-03', + 'periods' => ['day', 'week'], + 'otherRequestParameters' => [ + 'expanded' => 1, + 'secondaryDimension' => 'documents', + ], + 'testSuffix' => '_documents', + ], + ], + ]; + } + + public static function getOutputPrefix() + { + return ''; + } + + public static function getPathToTestDirectory() + { + return __DIR__; + } +} + +ApiTest::$fixture = new BotTraffic(); diff --git a/plugins/BotTracking/tests/System/expected/test__documents__BotTracking.getAIAssistantRequests_day.xml b/plugins/BotTracking/tests/System/expected/test__documents__BotTracking.getAIAssistantRequests_day.xml new file mode 100644 index 00000000000..076b59811ba --- /dev/null +++ b/plugins/BotTracking/tests/System/expected/test__documents__BotTracking.getAIAssistantRequests_day.xml @@ -0,0 +1,41 @@ + + + + + 1 + 0 + 1 + 1 + + + + 1 + 0 + 1 + 1 + + + + 2 + 2 + 0 + 0 + + + + 1 + + + + 1 + + + + + + 2 + 0 + 2 + 0 + + \ No newline at end of file diff --git a/plugins/BotTracking/tests/System/expected/test__documents__BotTracking.getAIAssistantRequests_week.xml b/plugins/BotTracking/tests/System/expected/test__documents__BotTracking.getAIAssistantRequests_week.xml new file mode 100644 index 00000000000..d04ec64529a --- /dev/null +++ b/plugins/BotTracking/tests/System/expected/test__documents__BotTracking.getAIAssistantRequests_week.xml @@ -0,0 +1,94 @@ + + + + + 4 + 2 + 2 + 2 + + + + 1 + + + + 1 + + + + + + 6 + 5 + 1 + 2 + + + + 1 + + + + 1 + + + + 1 + + + + 1 + + + + 1 + + + + + + 4 + 0 + 4 + 1 + + + + 3 + 0 + 3 + 1 + + + + 2 + 0 + 2 + 0 + + + + 2 + 2 + 0 + 0 + + + + 1 + + + + 1 + + + + + + 4 + 0 + 4 + 0 + + \ No newline at end of file diff --git a/plugins/BotTracking/tests/System/expected/test__flat__BotTracking.getAIAssistantRequests_day.xml b/plugins/BotTracking/tests/System/expected/test__flat__BotTracking.getAIAssistantRequests_day.xml new file mode 100644 index 00000000000..34d65cf9a1f --- /dev/null +++ b/plugins/BotTracking/tests/System/expected/test__flat__BotTracking.getAIAssistantRequests_day.xml @@ -0,0 +1,27 @@ + + + + + 1 + ChatGPT-User + example.com/article-2 + + + + 1 + MistralAI-User + example.com/article-3 + + + + 1 + MistralAI-User + example.com/article-4 + + + + 1 + Perplexity-User + example.com/article-3 + + \ No newline at end of file diff --git a/plugins/BotTracking/tests/System/expected/test__flat__BotTracking.getAIAssistantRequests_week.xml b/plugins/BotTracking/tests/System/expected/test__flat__BotTracking.getAIAssistantRequests_week.xml new file mode 100644 index 00000000000..4e73ccb6c5c --- /dev/null +++ b/plugins/BotTracking/tests/System/expected/test__flat__BotTracking.getAIAssistantRequests_week.xml @@ -0,0 +1,87 @@ + + + + + 1 + ChatGPT-User + example.com/article-1 + + + + 1 + ChatGPT-User + example.com/article-2 + + + + 1 + ChatGPT-User + example.com/article-4 + + + + 1 + ChatGPT-User + example.com/article-5 + + + + 1 + Claude-User + example.com/article-4 + + + + 1 + Claude-User + example.com/article-6 + + + + 2 + Devin + example.com/api + + + + 1 + Gemini-Deep-Research + example.com/article-4 + + + + 1 + Gemini-Deep-Research + example.com/article-5 + + + + 1 + Gemini-Deep-Research + example.com/article-6 + + + + 2 + MistralAI-User + example.com/article-3 + + + + 1 + MistralAI-User + example.com/article-4 + + + + 1 + MistralAI-User + example.com/article-5 + + + + 1 + Perplexity-User + example.com/article-3 + + \ No newline at end of file diff --git a/plugins/BotTracking/tests/System/expected/test__pages__BotTracking.getAIAssistantRequests_day.xml b/plugins/BotTracking/tests/System/expected/test__pages__BotTracking.getAIAssistantRequests_day.xml new file mode 100644 index 00000000000..1d5123afc75 --- /dev/null +++ b/plugins/BotTracking/tests/System/expected/test__pages__BotTracking.getAIAssistantRequests_day.xml @@ -0,0 +1,53 @@ + + + + + 1 + 0 + 1 + 1 + + + + 1 + + + + + + 1 + 0 + 1 + 1 + + + + 1 + + + + + + 2 + 2 + 0 + 0 + + + + 2 + 0 + 2 + 0 + + + + 1 + + + + 1 + + + + \ No newline at end of file diff --git a/plugins/BotTracking/tests/System/expected/test__pages__BotTracking.getAIAssistantRequests_week.xml b/plugins/BotTracking/tests/System/expected/test__pages__BotTracking.getAIAssistantRequests_week.xml new file mode 100644 index 00000000000..172b5ab3a4a --- /dev/null +++ b/plugins/BotTracking/tests/System/expected/test__pages__BotTracking.getAIAssistantRequests_week.xml @@ -0,0 +1,120 @@ + + + + + 4 + 2 + 2 + 2 + + + + 1 + + + + 1 + + + + + + 6 + 5 + 1 + 2 + + + + 1 + + + + + + 4 + 0 + 4 + 1 + + + + 1 + + + + 1 + + + + 1 + + + + 1 + + + + + + 3 + 0 + 3 + 1 + + + + 1 + + + + 1 + + + + 1 + + + + + + 2 + 0 + 2 + 0 + + + + 2 + + + + + + 2 + 2 + 0 + 0 + + + + 4 + 0 + 4 + 0 + + + + 2 + + + + 1 + + + + 1 + + + + \ No newline at end of file From eff6c6159950a8ad97420a108e99f69e1393a7ae Mon Sep 17 00:00:00 2001 From: sgiehl Date: Mon, 17 Nov 2025 15:34:03 +0100 Subject: [PATCH 06/13] Adds UI tests for new report --- .../BotTracking/tests/UI/BotTracking_spec.js | 52 +++++++++++++++++++ .../BotTracking_bot_requests.png | 3 ++ .../BotTracking_bot_requests_documents.png | 3 ++ 3 files changed, 58 insertions(+) create mode 100644 plugins/BotTracking/tests/UI/BotTracking_spec.js create mode 100644 plugins/BotTracking/tests/UI/expected-screenshots/BotTracking_bot_requests.png create mode 100644 plugins/BotTracking/tests/UI/expected-screenshots/BotTracking_bot_requests_documents.png diff --git a/plugins/BotTracking/tests/UI/BotTracking_spec.js b/plugins/BotTracking/tests/UI/BotTracking_spec.js new file mode 100644 index 00000000000..b1561627f1f --- /dev/null +++ b/plugins/BotTracking/tests/UI/BotTracking_spec.js @@ -0,0 +1,52 @@ +/*! + * Matomo - free/libre analytics platform + * + * Screenshot integration tests. + * + * @link https://matomo.org + * @license https://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + +describe("BotTracking", function () { + this.timeout(0); + + this.fixture = "Piwik\\Plugins\\BotTracking\\tests\\Fixtures\\BotTraffic"; + + var generalParams = 'idSite=1&period=day&date=2025-02-02', + urlBase = 'module=CoreHome&action=index&' + generalParams; + + before(function () { + testEnvironment.pluginsToLoad = ['BotTracking', 'AIAgents']; + testEnvironment.save(); + }); + + it('should render AI Assistants > Overview bot detail report', async function () { + await page.goto("?" + urlBase + "#?" + generalParams + "&category=AIAgents_AIAssistants&subcategory=General_Overview"); + await page.waitForNetworkIdle(); + + const row = await page.jQuery('tr.subDataTable:first'); + await row.click(); + await page.mouse.move(-10, -10); + + await page.waitForNetworkIdle(); + await page.waitForTimeout(250); // rendering + + var elem = await page.$('#widgetBotTrackinggetAIAssistantRequests'); + expect(await elem.screenshot()).to.matchImage('bot_requests'); + }); + + it('should switch to secondary dimension when clicked', async function () { + await page.evaluate(() => $('.datatableRelatedReports li span:contains("Document Requests")').click()); + await page.waitForNetworkIdle(); + + const row = await page.jQuery('tr.subDataTable:first'); + await row.click(); + await page.mouse.move(-10, -10); + + await page.waitForNetworkIdle(); + await page.waitForTimeout(250); // rendering + + var elem = await page.$('#widgetBotTrackinggetAIAssistantRequests'); + expect(await elem.screenshot()).to.matchImage('bot_requests_documents'); + }); +}); diff --git a/plugins/BotTracking/tests/UI/expected-screenshots/BotTracking_bot_requests.png b/plugins/BotTracking/tests/UI/expected-screenshots/BotTracking_bot_requests.png new file mode 100644 index 00000000000..f367cb2ec39 --- /dev/null +++ b/plugins/BotTracking/tests/UI/expected-screenshots/BotTracking_bot_requests.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:813f5f5b495475d05ab395b813bfa641600f6986c0b66e79827de8fae95a2ef6 +size 42632 diff --git a/plugins/BotTracking/tests/UI/expected-screenshots/BotTracking_bot_requests_documents.png b/plugins/BotTracking/tests/UI/expected-screenshots/BotTracking_bot_requests_documents.png new file mode 100644 index 00000000000..871412033dd --- /dev/null +++ b/plugins/BotTracking/tests/UI/expected-screenshots/BotTracking_bot_requests_documents.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:47dac1bdce82422c29fde6f1d1a825ca86cd9b7a30b2cb969dc47d6fbc0f4426 +size 43785 From 3075d5bec9175f764bea82d0e2a91b9a7515bcc7 Mon Sep 17 00:00:00 2001 From: sgiehl Date: Mon, 17 Nov 2025 16:15:27 +0100 Subject: [PATCH 07/13] updates expected UI test files --- .../AIAgents_overview.png | Bin 61055 -> 75654 bytes .../BotTracking_bot_requests.png | 4 ++-- .../BotTracking_bot_requests_documents.png | 4 ++-- .../DashboardManager_expanded.png | 4 ++-- .../DashboardManager_widget_list_shown.png | 4 ++-- .../DashboardManager_widget_preview.png | 4 ++-- .../Dashboard_dashboard2.png | 4 ++-- .../Dashboard_dashboard3.png | 4 ++-- .../Dashboard_dashboard4.png | 4 ++-- .../Dashboard_dashboard5.png | 4 ++-- ...ationTest_admin_diagnostics_configfile.png | 4 ++-- ...UIIntegrationTest_email_reports_editor.png | 4 ++-- .../UIIntegrationTest_glossary.png | 4 ++-- .../UIIntegrationTest_glossary_widgetized.png | 4 ++-- .../UIIntegrationTest_widgets_listing.png | 4 ++-- 15 files changed, 28 insertions(+), 28 deletions(-) diff --git a/plugins/AIAgents/tests/UI/expected-ui-screenshots/AIAgents_overview.png b/plugins/AIAgents/tests/UI/expected-ui-screenshots/AIAgents_overview.png index 4e03bf0c85264b49e08897f66ef1fb32cba38a0c..20dc8236c93d5b2e2197cdaa0446f059c1be582c 100644 GIT binary patch literal 75654 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 z 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 literal 61055 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 Date: Mon, 17 Nov 2025 15:35:22 +0100 Subject: [PATCH 08/13] fix other tests --- plugins/AIAgents/tests/UI/AIAgents_spec.js | 2 +- .../Commands/AnalyzeArchiveTableTest.php | 6 +-- ...dReports.generateReport_week.original.html | 11 ++++++ ...dReports.generateReport_week.original.html | 11 ++++++ ...edReports.generateReport_week.original.csv | 3 ++ ...edReports.generateReport_week.original.pdf | Bin 577476 -> 577785 bytes ...edReports.generateReport_week.original.tsv | 3 ++ .../Framework/TestRequest/Collection.php | 1 + .../Archive/PartialArchiveTest.php | 4 +- tests/PHPUnit/Integration/WidgetsListTest.php | 2 +- ...Reports.generateReport_month.original.html | 11 ++++++ ...Reports.generateReport_month.original.html | 11 ++++++ ...dReports.generateReport_month.original.csv | 3 ++ ...dReports.generateReport_month.original.pdf | Bin 552553 -> 552831 bytes ...dReports.generateReport_month.original.tsv | 3 ++ ...ReportMetadata__API.getGlossaryMetrics.xml | 20 ++++++++++ ...ReportMetadata__API.getGlossaryReports.xml | 4 ++ ...ortMetadata__API.getReportMetadata_day.xml | 35 ++++++++++++++++++ ...rtMetadata__API.getReportPagesMetadata.xml | 18 ++++++++- ...tReportMetadata__API.getWidgetMetadata.xml | 32 +++++++++++++++- 20 files changed, 169 insertions(+), 11 deletions(-) diff --git a/plugins/AIAgents/tests/UI/AIAgents_spec.js b/plugins/AIAgents/tests/UI/AIAgents_spec.js index 86b466b4184..b3945817fab 100644 --- a/plugins/AIAgents/tests/UI/AIAgents_spec.js +++ b/plugins/AIAgents/tests/UI/AIAgents_spec.js @@ -17,7 +17,7 @@ describe('AIAgents', function () { await page.waitForNetworkIdle(); const widgets = await page.$$('.matomo-widget'); - expect(widgets.length).to.equal(2); + expect(widgets.length).to.equal(3); }); it('should show the AI assistants report menu items', async function () { diff --git a/plugins/Diagnostics/tests/Integration/Commands/AnalyzeArchiveTableTest.php b/plugins/Diagnostics/tests/Integration/Commands/AnalyzeArchiveTableTest.php index fa3813ba92f..5c0f9da5706 100644 --- a/plugins/Diagnostics/tests/Integration/Commands/AnalyzeArchiveTableTest.php +++ b/plugins/Diagnostics/tests/Integration/Commands/AnalyzeArchiveTableTest.php @@ -42,9 +42,9 @@ public function testCommandOutputIsAsExpected() +-------------------------------------------+------------+---------------+-------------+---------+-----------+----------------+-------------+-------------+ | Group | # Archives | # Invalidated | # Temporary | # Error | # Segment | # Numeric Rows | # Blob Rows | # Blob Data | +-------------------------------------------+------------+---------------+-------------+---------+-----------+----------------+-------------+-------------+ -| day[2010-03-06 - 2010-03-06] idSite = 1 | 9 | 0 | 0 | 0 | 8 | 115 | 77 | %d | -| week[2010-03-01 - 2010-03-07] idSite = 1 | 9 | 0 | 0 | 0 | 8 | 157 | 99 | %d | -| month[2010-03-01 - 2010-03-31] idSite = 1 | 9 | 0 | 0 | 0 | 8 | 157 | 99 | %d | +| day[2010-03-06 - 2010-03-06] idSite = 1 | 9 | 0 | 0 | 0 | 8 | 115 | 79 | %d | +| week[2010-03-01 - 2010-03-07] idSite = 1 | 9 | 0 | 0 | 0 | 8 | 157 | 101 | %d | +| month[2010-03-01 - 2010-03-31] idSite = 1 | 9 | 0 | 0 | 0 | 8 | 157 | 101 | %d | +-------------------------------------------+------------+---------------+-------------+---------+-----------+----------------+-------------+-------------+ Total # Archives: 27 diff --git a/plugins/Ecommerce/tests/System/expected/test_ecommerceOrderWithItems_schedrep_html_tables_and_graph__ScheduledReports.generateReport_week.original.html b/plugins/Ecommerce/tests/System/expected/test_ecommerceOrderWithItems_schedrep_html_tables_and_graph__ScheduledReports.generateReport_week.original.html index 7105c448dde..91fbb808c60 100644 --- a/plugins/Ecommerce/tests/System/expected/test_ecommerceOrderWithItems_schedrep_html_tables_and_graph__ScheduledReports.generateReport_week.original.html +++ b/plugins/Ecommerce/tests/System/expected/test_ecommerceOrderWithItems_schedrep_html_tables_and_graph__ScheduledReports.generateReport_week.original.html @@ -427,6 +427,11 @@

title match, triggered ONCE - Days to Conversion + +
  • + + AI Assistants - Bots +
  • @@ -7806,6 +7811,12 @@

    + AI Assistants - Bots +

    + + There is no data for this report. +

    AI Agent Visits

    diff --git a/plugins/Ecommerce/tests/System/expected/test_ecommerceOrderWithItems_schedrep_html_tables_only__ScheduledReports.generateReport_week.original.html b/plugins/Ecommerce/tests/System/expected/test_ecommerceOrderWithItems_schedrep_html_tables_only__ScheduledReports.generateReport_week.original.html index 14a6b4cfdf9..50567524e10 100644 --- a/plugins/Ecommerce/tests/System/expected/test_ecommerceOrderWithItems_schedrep_html_tables_only__ScheduledReports.generateReport_week.original.html +++ b/plugins/Ecommerce/tests/System/expected/test_ecommerceOrderWithItems_schedrep_html_tables_only__ScheduledReports.generateReport_week.original.html @@ -427,6 +427,11 @@

    title match, triggered ONCE - Days to Conversion +

  • +
  • + + AI Assistants - Bots +
  • @@ -7407,6 +7412,12 @@

    + AI Assistants - Bots +

    + + There is no data for this report. +

    AI Agent Visits

    diff --git a/plugins/Ecommerce/tests/System/expected/test_ecommerceOrderWithItems_schedrep_in_csv__ScheduledReports.generateReport_week.original.csv b/plugins/Ecommerce/tests/System/expected/test_ecommerceOrderWithItems_schedrep_in_csv__ScheduledReports.generateReport_week.original.csv index f1ad995b4e9..f6fc7c06c48 100644 --- a/plugins/Ecommerce/tests/System/expected/test_ecommerceOrderWithItems_schedrep_in_csv__ScheduledReports.generateReport_week.original.csv +++ b/plugins/Ecommerce/tests/System/expected/test_ecommerceOrderWithItems_schedrep_in_csv__ScheduledReports.generateReport_week.original.csv @@ -548,6 +548,9 @@ label,nb_conversions 121-364 days,0 365+ days,0 +AI Assistants - Bots +No data available + AI Agent Visits nb_uniq_visitors_ai_agent,nb_users_ai_agent,nb_visits_ai_agent,nb_actions_ai_agent,max_actions_ai_agent,bounce_rate_ai_agent,nb_actions_per_visit_ai_agent,avg_time_on_site_ai_agent,nb_uniq_visitors_human,nb_users_human,nb_visits_human,nb_actions_human,max_actions_human,bounce_rate_human,nb_actions_per_visit_human,avg_time_on_site_human 0,0,0,0,0,0%,0,00:00:00,1,0,5,16,6,20%,3.2,00:22:50 diff --git a/plugins/Ecommerce/tests/System/expected/test_ecommerceOrderWithItems_schedrep_in_pdf_tables_only__ScheduledReports.generateReport_week.original.pdf b/plugins/Ecommerce/tests/System/expected/test_ecommerceOrderWithItems_schedrep_in_pdf_tables_only__ScheduledReports.generateReport_week.original.pdf index be81bb22ba70aa287374b5de0d29e045acf610d4..3b51c48b6af337f4c11a9e1a0b549d124776f23a 100644 GIT binary patch delta 6717 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 JT)$<5*xzqpKw1C* delta 6479 zcmZuz2{={h8=u?MINj|2mO*GtDUx%~cF!%eXhw^uh=yDVQz|=IQb!?FBFe2O+H4o8 zEG?FVNRz^#m?TB25!sdae~xC#J>z-K^Iq@wuD^HrzLE2qWr>u>BIc&aRF9D^I4ve}LaN!_P!p=HQSfx7ov@-AHZFa?v7ni<+HhSH@gCS*2|? zQkqgSH{~|(iP+6kEQ<(>ruJ=N2G2f=?cXgvbJgL_ORM*cl5an}+i+}Lx%iV>QK72S z*t)~l+!PKMEdJ5pr~UdpCtFk zJXrlMIR2eX0!z%*vpEx0FA@B;^Thg^b>G7QG8vnqJ0A#M`WCAhijRj-SHgt$sx9Jr zt;6c2Ql;IkDN>~pqwkf+_$4*$f*CY=P>)&xsu}I((dPGuZt7;|$0zc@H?f8S@n5ud?VZoaM5>;3Csf#T4-?l~_T{e}bkk^+3GiknLYOpho9N4bit zeT?f{Q_dSOexn(&IG$>l>2{%NjJKfR=dovc?V2lZo2S)@x1>l&;kG{(C@fAld9?%! z$Ufq$7%$)Q@r~zo$t>y0o^zqKYoD&jdPYFq=Cy}y)hxc_t`J8Bg8XDHWva7yTbpv_ab|a8Zo)#( z!oszUo`ip#P$zzL+d-YRP0cz-N zChNB-Rz_qQHNUj@wNfc37Y&31snc7EUNwX~3R$^r?~e-kU7c%;hW}EysLh@go0Qt2 zmcAg+Qg9(wdsDU4BO9MgKVRd_ReSelBBr%2e9LY3B|YxuGz%)m+*jPKyE~h5^|0&m z+Izvwl$`NG=a_nqmHN^h@e-PCYrIA)GcpPL(>&XVXHS)Z}&-Xrz4Uid9p&|1h{Lk{p!+$?4H(iCC4V~&wdMzhIy%0NHqzg)N>w& z$=s?{UD^`S>J0_FugS6(i=6GNR;?<(=KG$hSG_T1JufOok#G>FYIkIc!pk|?z`G$dU8UA?Rcw_(b!sO?Wx&yz?ZJ)I1kAk?I>wo6jK9Wk6 zYm$3DCf3-ueP2w3zg*No!^9rzv5R*M%X3E?)=AYjOFY6JYTf;%A@!ByBW(6lVNqP- zli!7ZMCfET_Sy)kmC^Ux9P}QS*tP5#_R4ytmDZFOlX%~n*t~D<(#DgZiRHyUSwE4q z>ht{D0~ zCe(lJT;tWVN>BADPf^OZyV|xd!#uYO)t)CPc4R40^&Sa7ENhSJa^5jK!r3d~aqc?< zuoq^vt=ZLoN@+&F*_*iZzY=5&E+=qKSKZ8rl1-KaO;^X7YrMiIT$XOSFj<9je{Lwx z+%*(A^g!YM{|w6bKK;_oss_Ms|Ma;TF-^KUvb*Ec!!GT#sV{ZZRmnJ}ouvcjKNa{1QnkyRFJ?c;!?4jeB>{3~+1?>fCg)jg`%0|3$=lB~&7u(8>;E#&ot%+FdHrD(mVp=3#msZB zzCC{pY!zeqx|2DATMjH~P5Cy9Upt+aD6176pI0WgPdwWvg{`rQeajDx8KPQe4m%lqecbq)ODm^tIU%x@;Q z_xb-V^;;;Jso?zd(4jEB_CIajX+kc2_6M>s^auRX2r+J7p( z6Uqzrbn*`gy61nqK>1{c@YVBYR|Cef@PR15_$7H~gB;sgWXJeVcRCAReX@M?D5cQ9 zw`x4`Mdv`y;JEU!mb+U6(XQ`$*-fskpJokK6&O>M%_E&V{iN(F{Ha8te@e7^@>!!^ z|0^%J{-q%W4wXlo^^OM~IyH8zRIe{&AYff)Wky4hdg8ckdtRNp$W$ z-srx&;?X_3$i#KGXSEO2)-5vHnKxjS?QZZCscRTsx?=hWscSIQX0dgFaL~?X*>eut z$<@)zJIo`11-@zE`yPDL!8ZeZKjeD^h)sLXA_d+%pnHHUafZqPVeN$S0lB#ox($fW zE+`ieo!w9kAfI5AjbP&$_X}3596@s%qidHBLqR;jnpo2F%2)zVnXfX5|5S0+98<1I{v|eK;dGi!;k1=A5plj7Sh;Wt>H{S1G%d+L zLxW`z4}Ad4UlVB4&{;a%%Cody%sJ@##91O8i&7FDOGgszHsd^PEa?J`MD#`I4U5bV zxCBYC01dwk%>+~slME#b*s0JQ@Y^v3S|GTc4#^8zPeH2%?@}N|LDl5Z!c@pmpq&P- z738LZ^TXg5Q209)S}KrFht>#u(g4>x9hwce4QW93aXOH-o3I57AsZ=D1J>B6p|{@C zX^#fNAp}|Jkfxwe2sBlM5L+OV0nL}=(lUmI6K(CbZ6_Py@B}6qP^DmP1|*)ZkqN2D zus8z!BIp8e^1KK#R)$41{5+k0XTur@f(VusL#h;x0f~t}4Ob2J1jR8P&f!euVO*R` zU<@9~W$N-s5aYz(zxHq#;V^j^M)Rbn2ohXw{<~sm+7A>*#2d`xA|!*yBMD-vH;hZb zqTVnrmrDS2zl{pxaXARW;Gw)pd$wQ0hq*iipDKuRcpy>+kB5uOAux>cMC1?{6`a2Z z$x#?05)+QVJkgkNgoBU_vmBHw5<8G1nXUlv3^@cL=&DiQAdet8M+8V5LAZ=kA}C6V zv<8l#B+1ATgE592MouXV@DJk%f$>DDiX&VUVHhO;14tf@GJ@vu82yaG2q}s*%7G~c ztSARzG&G8!qK%KED2j_#A4Rzs!wH5l0z`2Fo|L1$wirr)5fNzhe;ka zB^nS6&VdQhsBzH!s0cDR2XqpHM-ZZk;2aWX=z{6{B1e5)PzZuClo1SJDia(=fCwqN zEO8tK*@y;+a(Gj9DUdOW!3-xT!E}t0@Kj}>i^2cFLtxR;;TVQ6c?80xL?gsVrXbE7 zI~->&BpkKMfph**{;JDmIwp8bWVo;h{4j;% zT$C|lI2Zdj!hfA`xy&+gc_<@0l0z^8B>$ttBmokh*ni)Q6HbDAMzka(k7SGvk3%x# zcqmtN`QSX9vCMGZH@7(T<+{gtJjQ&2JCqQ0LcpLiMFJ$iq7hxeV84CYa9MLHTl{iQ1Tn*7aqo8LWrR_BRdRCw`j%~mvQNUOBQ7W zLxEQwgNdVzM+q^prbL~9(P8w$M0bhG0sNUfj80?%|F7^9;JRZdgXf(nkIVTF9<%!i zF6b_XF8OVL(Dla&@UUPwAvrK3V-jU78n8alZ-Vyrw0GX^getArchiveInfo('2020_04', Range::PERIOD_ID, false); $this->assertEquals([ - ['idsite' => 1, 'date1' => '2020-04-06', 'date2' => '2020-04-09', 'period' => Range::PERIOD_ID, 'name' => 'done', 'value' => ArchiveWriter::DONE_OK, 'blob_count' => 60], + ['idsite' => 1, 'date1' => '2020-04-06', 'date2' => '2020-04-09', 'period' => Range::PERIOD_ID, 'name' => 'done', 'value' => ArchiveWriter::DONE_OK, 'blob_count' => 62], ], $archiveInfo); $maxIdArchive = $this->getMaxIdArchive('2020_04'); @@ -124,7 +124,7 @@ public function testRangeArchivingOnlyArchivesSingleRecordWhenQueryingBlobs() // check archive is all plugins archive as expected [$idArchives, $archiveInfo] = $this->getArchiveInfo('2020_04', Range::PERIOD_ID, false); $this->assertEquals([ - ['idsite' => 1, 'date1' => '2020-04-06', 'date2' => '2020-04-09', 'period' => Range::PERIOD_ID, 'name' => 'done', 'value' => ArchiveWriter::DONE_OK, 'blob_count' => 60], + ['idsite' => 1, 'date1' => '2020-04-06', 'date2' => '2020-04-09', 'period' => Range::PERIOD_ID, 'name' => 'done', 'value' => ArchiveWriter::DONE_OK, 'blob_count' => 62], ], $archiveInfo); $maxIdArchive = $this->getMaxIdArchive('2020_04'); diff --git a/tests/PHPUnit/Integration/WidgetsListTest.php b/tests/PHPUnit/Integration/WidgetsListTest.php index e46ffa40b69..82fd947595a 100644 --- a/tests/PHPUnit/Integration/WidgetsListTest.php +++ b/tests/PHPUnit/Integration/WidgetsListTest.php @@ -52,7 +52,7 @@ public function testGet() 'Referrers_Referrers' => 11, 'About Matomo' => 11, 'Marketplace_Marketplace' => 3, - 'AIAgents_AIAssistants' => 2, + 'AIAgents_AIAssistants' => 3, // widgets provided by Professional Services plugin for plugin promos 'ProfessionalServices_PromoAbTesting' => 1, diff --git a/tests/PHPUnit/System/expected/test_TwoVisitors_twoWebsites_differentDays_schedrep_html_tables_and_graph__ScheduledReports.generateReport_month.original.html b/tests/PHPUnit/System/expected/test_TwoVisitors_twoWebsites_differentDays_schedrep_html_tables_and_graph__ScheduledReports.generateReport_month.original.html index ab572f8cfcf..f11ea481cb5 100644 --- a/tests/PHPUnit/System/expected/test_TwoVisitors_twoWebsites_differentDays_schedrep_html_tables_and_graph__ScheduledReports.generateReport_month.original.html +++ b/tests/PHPUnit/System/expected/test_TwoVisitors_twoWebsites_differentDays_schedrep_html_tables_and_graph__ScheduledReports.generateReport_month.original.html @@ -367,6 +367,11 @@

    Goals Overview - Days to Conversion +

  • +
  • + + AI Assistants - Bots +
  • @@ -5947,6 +5952,12 @@

    + AI Assistants - Bots +

    + + There is no data for this report. +

    AI Agent Visits

    diff --git a/tests/PHPUnit/System/expected/test_TwoVisitors_twoWebsites_differentDays_schedrep_html_tables_only__ScheduledReports.generateReport_month.original.html b/tests/PHPUnit/System/expected/test_TwoVisitors_twoWebsites_differentDays_schedrep_html_tables_only__ScheduledReports.generateReport_month.original.html index cb9f4312d76..16e07412ed0 100644 --- a/tests/PHPUnit/System/expected/test_TwoVisitors_twoWebsites_differentDays_schedrep_html_tables_only__ScheduledReports.generateReport_month.original.html +++ b/tests/PHPUnit/System/expected/test_TwoVisitors_twoWebsites_differentDays_schedrep_html_tables_only__ScheduledReports.generateReport_month.original.html @@ -367,6 +367,11 @@

    Goals Overview - Days to Conversion +

  • +
  • + + AI Assistants - Bots +
  • @@ -5646,6 +5651,12 @@

    + AI Assistants - Bots +

    + + There is no data for this report. +

    AI Agent Visits

    diff --git a/tests/PHPUnit/System/expected/test_TwoVisitors_twoWebsites_differentDays_schedrep_in_csv__ScheduledReports.generateReport_month.original.csv b/tests/PHPUnit/System/expected/test_TwoVisitors_twoWebsites_differentDays_schedrep_in_csv__ScheduledReports.generateReport_month.original.csv index d41700aa45d..19e4cf6c04e 100644 --- a/tests/PHPUnit/System/expected/test_TwoVisitors_twoWebsites_differentDays_schedrep_in_csv__ScheduledReports.generateReport_month.original.csv +++ b/tests/PHPUnit/System/expected/test_TwoVisitors_twoWebsites_differentDays_schedrep_in_csv__ScheduledReports.generateReport_month.original.csv @@ -374,6 +374,9 @@ No data available Goals Overview - Days to Conversion No data available +AI Assistants - Bots +No data available + AI Agent Visits nb_uniq_visitors_ai_agent,nb_users_ai_agent,nb_visits_ai_agent,nb_actions_ai_agent,max_actions_ai_agent,bounce_rate_ai_agent,nb_actions_per_visit_ai_agent,avg_time_on_site_ai_agent,nb_uniq_visitors_human,nb_users_human,nb_visits_human,nb_actions_human,max_actions_human,bounce_rate_human,nb_actions_per_visit_human,avg_time_on_site_human 0,0,0,0,0,0%,0,00:00:00,2,0,11,43,5,27%,3.9,00:10:55 diff --git a/tests/PHPUnit/System/expected/test_TwoVisitors_twoWebsites_differentDays_schedrep_in_pdf_tables_only__ScheduledReports.generateReport_month.original.pdf b/tests/PHPUnit/System/expected/test_TwoVisitors_twoWebsites_differentDays_schedrep_in_pdf_tables_only__ScheduledReports.generateReport_month.original.pdf index 31e6fdf5412decc6e102c4a633725a2885ccf190..f92319cf87cb5d9da4dff5b00b243ae1ebc4f2cb 100644 GIT binary patch delta 4874 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 P4)6u+;P2l%I?Un!J;C(N diff --git a/tests/PHPUnit/System/expected/test_TwoVisitors_twoWebsites_differentDays_schedrep_in_tsv__ScheduledReports.generateReport_month.original.tsv b/tests/PHPUnit/System/expected/test_TwoVisitors_twoWebsites_differentDays_schedrep_in_tsv__ScheduledReports.generateReport_month.original.tsv index be63321aed7..c78ee976125 100644 --- a/tests/PHPUnit/System/expected/test_TwoVisitors_twoWebsites_differentDays_schedrep_in_tsv__ScheduledReports.generateReport_month.original.tsv +++ b/tests/PHPUnit/System/expected/test_TwoVisitors_twoWebsites_differentDays_schedrep_in_tsv__ScheduledReports.generateReport_month.original.tsv @@ -374,6 +374,9 @@ No data available Goals Overview - Days to Conversion No data available +AI Assistants - Bots +No data available + AI Agent Visits nb_uniq_visitors_ai_agent nb_users_ai_agent nb_visits_ai_agent nb_actions_ai_agent max_actions_ai_agent bounce_rate_ai_agent nb_actions_per_visit_ai_agent avg_time_on_site_ai_agent nb_uniq_visitors_human nb_users_human nb_visits_human nb_actions_human max_actions_human bounce_rate_human nb_actions_per_visit_human avg_time_on_site_human 0 0 0 0 0 0% 0 00:00:00 2 0 11 43 5 27% 3.9 00:10:55 diff --git a/tests/PHPUnit/System/expected/test_apiGetReportMetadata__API.getGlossaryMetrics.xml b/tests/PHPUnit/System/expected/test_apiGetReportMetadata__API.getGlossaryMetrics.xml index fcc1fee9470..53a9889d0a6 100644 --- a/tests/PHPUnit/System/expected/test_apiGetReportMetadata__API.getGlossaryMetrics.xml +++ b/tests/PHPUnit/System/expected/test_apiGetReportMetadata__API.getGlossaryMetrics.xml @@ -1,5 +1,10 @@ + + Acquired visits + visits_acquired + Visits that started after someone clicked from an AI assistant (Referrers → AI Assistants). + Actions nb_actions @@ -90,6 +95,11 @@ conversion_rate The percentage of visits that triggered a conversion. The conversion rate is calculated using the number of visits that converted at least one goal. Visits converting multiple goals are only counted once in the conversion rate. + + Document Requests + document_requests + Total number of bot requests to document URLs recorded during the selected period. + Downloads nb_downloads @@ -155,6 +165,11 @@ nb_outlinks The number of times this link was clicked. + + Page Requests + page_requests + Total number of bot requests to page URLs recorded during the selected period. + Pageviews nb_hits @@ -170,6 +185,11 @@ revenue The total revenue generated by Product sales. Excludes tax, shipping and discount. + + Requests + requests + Total number of bot requests recorded during the selected period. Includes both page and document URLs. + Search Results pages nb_pages_per_search diff --git a/tests/PHPUnit/System/expected/test_apiGetReportMetadata__API.getGlossaryReports.xml b/tests/PHPUnit/System/expected/test_apiGetReportMetadata__API.getGlossaryReports.xml index 1bda0adfddd..a4db69521ee 100644 --- a/tests/PHPUnit/System/expected/test_apiGetReportMetadata__API.getGlossaryReports.xml +++ b/tests/PHPUnit/System/expected/test_apiGetReportMetadata__API.getGlossaryReports.xml @@ -4,6 +4,10 @@ AI Assistants (Referrers) This report shows which AI assistants led visitors to your website.<br />By clicking on a row in the table, you can see from which AI assistant pages visitors came to your website. + + AI Assistants - Bots (AI Assistants) + Discover which AI assistants are crawling your site and how many hits each one generates. Expand a bot to review the most frequently requested pages or documents. + Actions - Main metrics (Actions) This report provides a very basic overview of what actions your visitors take on your website. diff --git a/tests/PHPUnit/System/expected/test_apiGetReportMetadata__API.getReportMetadata_day.xml b/tests/PHPUnit/System/expected/test_apiGetReportMetadata__API.getReportMetadata_day.xml index c596128c45b..ff8c81d4527 100644 --- a/tests/PHPUnit/System/expected/test_apiGetReportMetadata__API.getReportMetadata_day.xml +++ b/tests/PHPUnit/System/expected/test_apiGetReportMetadata__API.getReportMetadata_day.xml @@ -3544,6 +3544,41 @@ index.php?module=API&method=ImageGraph.get&idSite=1&apiModule=Goals&apiAction=getDaysToConversion&idGoal=3&period=day&date=2009-01-04 Goals_getDaysToConversion_idGoal--3 + + AI Assistants + Overview + AI Assistants - Bots + BotTracking + getAIAssistantRequests + AI Assistant Name + Discover which AI assistants are crawling your site and how many hits each one generates. Expand a bot to review the most frequently requested pages or documents. + + AI Assistant Name + Page URL + + + Requests + Page Requests + Document Requests + Acquired visits + + + Total number of bot requests recorded during the selected period. Includes both page and document URLs. + Total number of bot requests to page URLs recorded during the selected period. + Total number of bot requests to document URLs recorded during the selected period. + Visits that started after someone clicked from an AI assistant (Referrers → AI Assistants). + + + number + number + number + number + + getPageUrlsForAIAssistant + index.php?module=API&method=ImageGraph.get&idSite=1&apiModule=BotTracking&apiAction=getAIAssistantRequests&period=day&date=2009-01-04 + index.php?module=API&method=ImageGraph.get&idSite=1&apiModule=BotTracking&apiAction=getAIAssistantRequests&period=day&date=2008-12-06,2009-01-04 + BotTracking_getAIAssistantRequests + AI Assistants Overview diff --git a/tests/PHPUnit/System/expected/test_apiGetReportMetadata__API.getReportPagesMetadata.xml b/tests/PHPUnit/System/expected/test_apiGetReportMetadata__API.getReportPagesMetadata.xml index 368430b7169..5eb417e82eb 100644 --- a/tests/PHPUnit/System/expected/test_apiGetReportMetadata__API.getReportPagesMetadata.xml +++ b/tests/PHPUnit/System/expected/test_apiGetReportMetadata__API.getReportPagesMetadata.xml @@ -6730,11 +6730,25 @@ <p>The AI Assistant Overview page provide insights into website traffic originating from AI Assistants such as ChatGPT and other large language model–based assistants. These reports track key metrics including the number of requests made by these bots, the pages and documents they access, and any errors encountered. They also offer detailed breakdowns showing which bots visit specific page URLs, helping you understand how AI assistants interact with your content and identify opportunities to improve visibility and accessibility for AI-driven users.</p><p>It’s important to note that none of these pages were actually viewed by humans in the traditional way — all requests originate from AI assistants fetching content automatically.</p><p>Currently, these reports exclusively include requests from AI bots that do not execute JavaScript. They do not include traffic from AI crawlers used for training AI models or from AI agents capable of executing JavaScript.</p> + + AI Assistants - Bots + BotTracking + getAIAssistantRequests + 30 + + BotTracking + getAIAssistantRequests + + widgetBotTrackinggetAIAssistantRequests + 0 + table + 1 + AI Agents Over Time AIAgents getEvolutionGraph - 1 + 90 1 graphEvolution @@ -6750,7 +6764,7 @@ AI Agent Overview AIAgents get - 2 + 91 1 sparklines diff --git a/tests/PHPUnit/System/expected/test_apiGetReportMetadata__API.getWidgetMetadata.xml b/tests/PHPUnit/System/expected/test_apiGetReportMetadata__API.getWidgetMetadata.xml index 3b4a0bbf891..b0334271f7f 100644 --- a/tests/PHPUnit/System/expected/test_apiGetReportMetadata__API.getWidgetMetadata.xml +++ b/tests/PHPUnit/System/expected/test_apiGetReportMetadata__API.getWidgetMetadata.xml @@ -3666,7 +3666,7 @@ AIAgents getEvolutionGraph - 1 + 90 1 graphEvolution @@ -3696,7 +3696,7 @@ AIAgents get - 2 + 91 1 sparklines @@ -3708,6 +3708,34 @@ sparklines 1 + + AI Assistants - Bots + + AIAgents_AIAssistants + AI Assistants + 80 + icon-admin-platform + + + + + General_Overview + Overview + 10 + <p>The AI Assistant Overview page provide insights into website traffic originating from AI Assistants such as ChatGPT and other large language model–based assistants. These reports track key metrics including the number of requests made by these bots, the pages and documents they access, and any errors encountered. They also offer detailed breakdowns showing which bots visit specific page URLs, helping you understand how AI assistants interact with your content and identify opportunities to improve visibility and accessibility for AI-driven users.</p><p>It’s important to note that none of these pages were actually viewed by humans in the traditional way — all requests originate from AI assistants fetching content automatically.</p><p>Currently, these reports exclusively include requests from AI bots that do not execute JavaScript. They do not include traffic from AI crawlers used for training AI models or from AI agents capable of executing JavaScript.</p> + + BotTracking + getAIAssistantRequests + 30 + + BotTracking + getAIAssistantRequests + + widgetBotTrackinggetAIAssistantRequests + 0 + table + 1 + Pie graph From 04c2e2a0b7a40a81058dd7781cb35125778bd6b4 Mon Sep 17 00:00:00 2001 From: sgiehl Date: Tue, 2 Dec 2025 14:14:27 +0100 Subject: [PATCH 09/13] do not double count acquired visits --- .../BotTracking/RecordBuilders/AIAssistantReports.php | 4 ++-- plugins/BotTracking/tests/Fixtures/BotTraffic.php | 1 + ...cuments__BotTracking.getAIAssistantRequests_day.xml | 10 ++++++++-- ...uments__BotTracking.getAIAssistantRequests_week.xml | 10 ++++++++-- ...__pages__BotTracking.getAIAssistantRequests_day.xml | 4 ++-- ..._pages__BotTracking.getAIAssistantRequests_week.xml | 4 ++-- 6 files changed, 23 insertions(+), 10 deletions(-) diff --git a/plugins/BotTracking/RecordBuilders/AIAssistantReports.php b/plugins/BotTracking/RecordBuilders/AIAssistantReports.php index ec0fd08429b..e3d644e5cec 100644 --- a/plugins/BotTracking/RecordBuilders/AIAssistantReports.php +++ b/plugins/BotTracking/RecordBuilders/AIAssistantReports.php @@ -183,8 +183,8 @@ private function populateTableForActionType(array $tables, int $actionType, LogA ]; // we add all records to both tables, so we in the end have the total count of pages & documents in the main table - $tables[Archiver::AI_ASSISTANTS_PAGES_RECORD]->sumRowWithLabel($label, $metrics); - $tables[Archiver::AI_ASSISTANTS_DOCUMENTS_RECORD]->sumRowWithLabel($label, $metrics); + $tables[Archiver::AI_ASSISTANTS_PAGES_RECORD]->sumRowWithLabel($label, $metrics, [Metrics::COLUMN_ACQUIRED_VISITS => 'max']); + $tables[Archiver::AI_ASSISTANTS_DOCUMENTS_RECORD]->sumRowWithLabel($label, $metrics, [Metrics::COLUMN_ACQUIRED_VISITS => 'max']); } $table = $tables[Archiver::AI_ASSISTANTS_PAGES_RECORD]; diff --git a/plugins/BotTracking/tests/Fixtures/BotTraffic.php b/plugins/BotTracking/tests/Fixtures/BotTraffic.php index e0b5210d289..ae1e99b44ef 100644 --- a/plugins/BotTracking/tests/Fixtures/BotTraffic.php +++ b/plugins/BotTracking/tests/Fixtures/BotTraffic.php @@ -75,6 +75,7 @@ private function trackBotRequests(): void ['MistralAI-User/2.0', $pages[2], 200, 32485, false], ['Claude-User/3.0', $downloads[2], 200, 123456, true], ['ChatGPT-User/1.0', $pages[1], 500, 25896, false], + ['ChatGPT-User/1.0', $downloads[1], 200, 33658, true], ['Perplexity-User/1.0', $pages[2], 200, 36985, false], ['MistralAI-User/2.0', $pages[3], 200, 85236, false], ['Claude-User/3.0', $downloads[3], 200, 12456, true], diff --git a/plugins/BotTracking/tests/System/expected/test__documents__BotTracking.getAIAssistantRequests_day.xml b/plugins/BotTracking/tests/System/expected/test__documents__BotTracking.getAIAssistantRequests_day.xml index 076b59811ba..34da712b105 100644 --- a/plugins/BotTracking/tests/System/expected/test__documents__BotTracking.getAIAssistantRequests_day.xml +++ b/plugins/BotTracking/tests/System/expected/test__documents__BotTracking.getAIAssistantRequests_day.xml @@ -2,10 +2,16 @@ - 1 - 0 + 2 + 1 1 1 + + + + 1 + + diff --git a/plugins/BotTracking/tests/System/expected/test__documents__BotTracking.getAIAssistantRequests_week.xml b/plugins/BotTracking/tests/System/expected/test__documents__BotTracking.getAIAssistantRequests_week.xml index d04ec64529a..05e390d10c2 100644 --- a/plugins/BotTracking/tests/System/expected/test__documents__BotTracking.getAIAssistantRequests_week.xml +++ b/plugins/BotTracking/tests/System/expected/test__documents__BotTracking.getAIAssistantRequests_week.xml @@ -48,10 +48,16 @@ - 4 - 0 + 5 + 1 4 1 + + + + 1 + + diff --git a/plugins/BotTracking/tests/System/expected/test__pages__BotTracking.getAIAssistantRequests_day.xml b/plugins/BotTracking/tests/System/expected/test__pages__BotTracking.getAIAssistantRequests_day.xml index 1d5123afc75..2ecdd671dfb 100644 --- a/plugins/BotTracking/tests/System/expected/test__pages__BotTracking.getAIAssistantRequests_day.xml +++ b/plugins/BotTracking/tests/System/expected/test__pages__BotTracking.getAIAssistantRequests_day.xml @@ -2,8 +2,8 @@ - 1 - 0 + 2 + 1 1 1 diff --git a/plugins/BotTracking/tests/System/expected/test__pages__BotTracking.getAIAssistantRequests_week.xml b/plugins/BotTracking/tests/System/expected/test__pages__BotTracking.getAIAssistantRequests_week.xml index 172b5ab3a4a..0d4cb7f7d51 100644 --- a/plugins/BotTracking/tests/System/expected/test__pages__BotTracking.getAIAssistantRequests_week.xml +++ b/plugins/BotTracking/tests/System/expected/test__pages__BotTracking.getAIAssistantRequests_week.xml @@ -32,8 +32,8 @@ - 4 - 0 + 5 + 1 4 1 From 4441aa08d251110a8802fee3280100dcbc4f4fd2 Mon Sep 17 00:00:00 2001 From: sgiehl Date: Tue, 2 Dec 2025 14:56:20 +0100 Subject: [PATCH 10/13] remove explicit plugin loading from ui tests --- plugins/BotTracking/tests/UI/BotTracking_spec.js | 5 ----- 1 file changed, 5 deletions(-) diff --git a/plugins/BotTracking/tests/UI/BotTracking_spec.js b/plugins/BotTracking/tests/UI/BotTracking_spec.js index b1561627f1f..5abc1efbb72 100644 --- a/plugins/BotTracking/tests/UI/BotTracking_spec.js +++ b/plugins/BotTracking/tests/UI/BotTracking_spec.js @@ -15,11 +15,6 @@ describe("BotTracking", function () { var generalParams = 'idSite=1&period=day&date=2025-02-02', urlBase = 'module=CoreHome&action=index&' + generalParams; - before(function () { - testEnvironment.pluginsToLoad = ['BotTracking', 'AIAgents']; - testEnvironment.save(); - }); - it('should render AI Assistants > Overview bot detail report', async function () { await page.goto("?" + urlBase + "#?" + generalParams + "&category=AIAgents_AIAssistants&subcategory=General_Overview"); await page.waitForNetworkIdle(); From e9a9886379ce78a2e94f73e49ad3278da61f42f8 Mon Sep 17 00:00:00 2001 From: sgiehl Date: Tue, 2 Dec 2025 16:50:30 +0100 Subject: [PATCH 11/13] updates expected UI test file --- .../UI/expected-screenshots/UIIntegrationTest_api_listing.png | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/UI/expected-screenshots/UIIntegrationTest_api_listing.png b/tests/UI/expected-screenshots/UIIntegrationTest_api_listing.png index d69f2910103..6e07940c5cb 100644 --- a/tests/UI/expected-screenshots/UIIntegrationTest_api_listing.png +++ b/tests/UI/expected-screenshots/UIIntegrationTest_api_listing.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:031b27a45ed8600ff49178a02cb70bc806bd3b5900f6286da8c80ef4fcbaf9c9 -size 5007529 +oid sha256:c36f9568e14bb238abd75e2008d8fc00a349ae374a8f41a84f9e0a251597004c +size 5052463 From 6f16d90b816641a1b5aee22c681a8e29a2309a81 Mon Sep 17 00:00:00 2001 From: sgiehl Date: Wed, 3 Dec 2025 09:09:26 +0100 Subject: [PATCH 12/13] Use a ranking query for bot requests --- .../RecordBuilders/AIAssistantReports.php | 104 ++++++++++++----- .../tests/System/RankingQueryApiTest.php | 84 ++++++++++++++ ...BotTracking.getAIAssistantRequests_day.xml | 47 ++++++++ ...otTracking.getAIAssistantRequests_week.xml | 47 ++++++++ ...BotTracking.getAIAssistantRequests_day.xml | 47 ++++++++ ...otTracking.getAIAssistantRequests_week.xml | 105 ++++++++++++++++++ 6 files changed, 405 insertions(+), 29 deletions(-) create mode 100644 plugins/BotTracking/tests/System/RankingQueryApiTest.php create mode 100644 plugins/BotTracking/tests/System/expected/test_ranking_limit_documents__BotTracking.getAIAssistantRequests_day.xml create mode 100644 plugins/BotTracking/tests/System/expected/test_ranking_limit_documents__BotTracking.getAIAssistantRequests_week.xml create mode 100644 plugins/BotTracking/tests/System/expected/test_ranking_limit_pages__BotTracking.getAIAssistantRequests_day.xml create mode 100644 plugins/BotTracking/tests/System/expected/test_ranking_limit_pages__BotTracking.getAIAssistantRequests_week.xml diff --git a/plugins/BotTracking/RecordBuilders/AIAssistantReports.php b/plugins/BotTracking/RecordBuilders/AIAssistantReports.php index e3d644e5cec..9396f966212 100644 --- a/plugins/BotTracking/RecordBuilders/AIAssistantReports.php +++ b/plugins/BotTracking/RecordBuilders/AIAssistantReports.php @@ -22,6 +22,7 @@ use Piwik\Plugins\BotTracking\Archiver; use Piwik\Plugins\BotTracking\Dao\BotRequestsDao; use Piwik\Plugins\BotTracking\Metrics; +use Piwik\RankingQuery; use Piwik\Tracker\Action; use Piwik\Tracker\PageUrl; @@ -40,6 +41,11 @@ class AIAssistantReports extends RecordBuilder 'Devin' => '', ]; + /** + * @var int + */ + private $rankingQueryLimit; + public function __construct() { parent::__construct(); @@ -47,6 +53,7 @@ public function __construct() $this->columnToSortByBeforeTruncation = Metrics::COLUMN_REQUESTS; $this->maxRowsInTable = (int)GeneralConfig::getConfigValue('datatable_archiving_maximum_rows_bots'); $this->maxRowsInSubtable = (int)GeneralConfig::getConfigValue('datatable_archiving_maximum_rows_subtable_bots'); + $this->rankingQueryLimit = $this->getRankingQueryLimit(); } public function getRecordMetadata(ArchiveProcessor $archiveProcessor): array @@ -137,27 +144,9 @@ private function queryAcquiredVisitsByAIAssistant(LogAggregator $logAggregator): */ private function populateTableForActionType(array $tables, int $actionType, LogAggregator $logAggregator, array $visits): void { - $where = $logAggregator->getWhereStatement('bot', 'server_time'); - $bindBase = $logAggregator->getGeneralQueryBindParams(); - - $sql = sprintf( - "SELECT * FROM (SELECT bot.bot_name, log_action.name AS url, COUNT(*) AS requests - FROM %s AS bot - INNER JOIN %s AS log_action ON log_action.idaction = bot.idaction_url - WHERE log_action.name IS NOT NULL - AND log_action.name <> '' - AND log_action.type = %d - AND %s - GROUP BY bot.bot_name, url WITH ROLLUP) AS rollupQuery - ORDER BY bot_name, requests DESC, url", - BotRequestsDao::getPrefixedTableName(), - Common::prefixTable('log_action'), - $actionType, - $where - ); - - $resultSet = Db::query($sql, $bindBase); + $resultSet = $this->queryBotRequests($logAggregator, $actionType); $actionRows = []; + $botTotals = []; while ($row = $resultSet->fetch()) { /** @@ -170,19 +159,28 @@ private function populateTableForActionType(array $tables, int $actionType, LogA continue; } - if (!is_null($url)) { - $actionRows[] = $row; + if (is_null($url)) { continue; } - $metrics = [ - Metrics::COLUMN_REQUESTS => $row['requests'], - Metrics::COLUMN_DOCUMENT_REQUESTS => $actionType === Action::TYPE_DOWNLOAD ? $row['requests'] : 0, - Metrics::COLUMN_PAGE_REQUESTS => $actionType === Action::TYPE_PAGE_URL ? $row['requests'] : 0, - Metrics::COLUMN_ACQUIRED_VISITS => $visits[$label] ?? 0, - ]; + $actionRows[] = $row; + + if (!isset($botTotals[$label])) { + $botTotals[$label] = [ + Metrics::COLUMN_REQUESTS => 0, + Metrics::COLUMN_DOCUMENT_REQUESTS => 0, + Metrics::COLUMN_PAGE_REQUESTS => 0, + Metrics::COLUMN_ACQUIRED_VISITS => 0, + ]; + } + + $botTotals[$label][Metrics::COLUMN_REQUESTS] += $row['requests']; + $botTotals[$label][Metrics::COLUMN_DOCUMENT_REQUESTS] += $actionType === Action::TYPE_DOWNLOAD ? $row['requests'] : 0; + $botTotals[$label][Metrics::COLUMN_PAGE_REQUESTS] += $actionType === Action::TYPE_PAGE_URL ? $row['requests'] : 0; + $botTotals[$label][Metrics::COLUMN_ACQUIRED_VISITS] = max($botTotals[$label][Metrics::COLUMN_ACQUIRED_VISITS], $visits[$label] ?? 0); + } - // we add all records to both tables, so we in the end have the total count of pages & documents in the main table + foreach ($botTotals as $label => $metrics) { $tables[Archiver::AI_ASSISTANTS_PAGES_RECORD]->sumRowWithLabel($label, $metrics, [Metrics::COLUMN_ACQUIRED_VISITS => 'max']); $tables[Archiver::AI_ASSISTANTS_DOCUMENTS_RECORD]->sumRowWithLabel($label, $metrics, [Metrics::COLUMN_ACQUIRED_VISITS => 'max']); } @@ -202,6 +200,10 @@ private function populateTableForActionType(array $tables, int $actionType, LogA $label = $row['bot_name']; $url = $row['url']; + if ($label === RankingQuery::LABEL_SUMMARY_ROW) { + continue; + } + $tableRow = $table->getRowFromLabel($label); if (empty($tableRow)) { @@ -216,4 +218,48 @@ private function populateTableForActionType(array $tables, int $actionType, LogA ]); } } + + private function queryBotRequests(LogAggregator $logAggregator, int $actionType) + { + $where = $logAggregator->getWhereStatement('bot', 'server_time'); + $where .= ' AND log_action.name IS NOT NULL + AND log_action.name <> \'\' + AND log_action.type = ' . $actionType; + + $sql = sprintf( + "SELECT bot.bot_name, log_action.name AS url, COUNT(*) AS requests + FROM %s AS bot + INNER JOIN %s AS log_action ON log_action.idaction = bot.idaction_url + WHERE %s + GROUP BY bot.bot_name, url + ORDER BY bot.bot_name, requests DESC, url", + BotRequestsDao::getPrefixedTableName(), + Common::prefixTable('log_action'), + $where + ); + + if ($this->rankingQueryLimit > 0) { + $rankingQuery = new RankingQuery($this->rankingQueryLimit); + $rankingQuery->addLabelColumn(['bot_name', 'url']); + $rankingQuery->addColumn('requests', 'sum'); + $sql = $rankingQuery->generateRankingQuery($sql); + } + + return Db::query($sql, $logAggregator->getGeneralQueryBindParams()); + } + + private function getRankingQueryLimit(): int + { + $maxRowsInTable = (int)$this->maxRowsInTable; + $maxRowsInSubtable = (int)$this->maxRowsInSubtable; + + $configLimit = (int)GeneralConfig::getConfigValue('archiving_ranking_query_row_limit'); + $configLimit = max($configLimit, 10 * $maxRowsInTable); + + if ($configLimit === 0) { + return 0; + } + + return max($configLimit, $maxRowsInTable, $maxRowsInSubtable); + } } diff --git a/plugins/BotTracking/tests/System/RankingQueryApiTest.php b/plugins/BotTracking/tests/System/RankingQueryApiTest.php new file mode 100644 index 00000000000..990854a3ca3 --- /dev/null +++ b/plugins/BotTracking/tests/System/RankingQueryApiTest.php @@ -0,0 +1,84 @@ +General; + $generalConfig['archiving_ranking_query_row_limit'] = 3; + $generalConfig['datatable_archiving_maximum_rows_bots'] = 0; // no limit here, so we see that the ranking query creates the others row + $generalConfig['datatable_archiving_maximum_rows_subtable_bots'] = 2; + + Cache::flushAll(); + self::deleteArchiveTables(); + + $this->runApiTests(['BotTracking.getAIAssistantRequests'], [ + 'idSite' => 1, + 'date' => '2025-02-03', + 'periods' => ['day', 'week'], + 'otherRequestParameters' => [ + 'expanded' => 1, + 'secondaryDimension' => 'pages', + ], + 'testSuffix' => 'ranking_limit_pages', + ]); + } + + public function testRankingQueryUsesOthersRowDocuments(): void + { + $generalConfig = &Config::getInstance()->General; + $generalConfig['archiving_ranking_query_row_limit'] = 3; + $generalConfig['datatable_archiving_maximum_rows_bots'] = 4; + $generalConfig['datatable_archiving_maximum_rows_subtable_bots'] = 2; + + Cache::flushAll(); + self::deleteArchiveTables(); + + $this->runApiTests(['BotTracking.getAIAssistantRequests'], [ + 'idSite' => 1, + 'date' => '2025-02-03', + 'periods' => ['day', 'week'], + 'otherRequestParameters' => [ + 'expanded' => 1, + 'secondaryDimension' => 'documents', + ], + 'testSuffix' => 'ranking_limit_documents', + ]); + } + + public static function getOutputPrefix() + { + return ''; + } + + public static function getPathToTestDirectory() + { + return __DIR__; + } +} + +RankingQueryApiTest::$fixture = new BotTraffic(); diff --git a/plugins/BotTracking/tests/System/expected/test_ranking_limit_documents__BotTracking.getAIAssistantRequests_day.xml b/plugins/BotTracking/tests/System/expected/test_ranking_limit_documents__BotTracking.getAIAssistantRequests_day.xml new file mode 100644 index 00000000000..34da712b105 --- /dev/null +++ b/plugins/BotTracking/tests/System/expected/test_ranking_limit_documents__BotTracking.getAIAssistantRequests_day.xml @@ -0,0 +1,47 @@ + + + + + 2 + 1 + 1 + 1 + + + + 1 + + + + + + 1 + 0 + 1 + 1 + + + + 2 + 2 + 0 + 0 + + + + 1 + + + + 1 + + + + + + 2 + 0 + 2 + 0 + + \ No newline at end of file diff --git a/plugins/BotTracking/tests/System/expected/test_ranking_limit_documents__BotTracking.getAIAssistantRequests_week.xml b/plugins/BotTracking/tests/System/expected/test_ranking_limit_documents__BotTracking.getAIAssistantRequests_week.xml new file mode 100644 index 00000000000..423e55164d2 --- /dev/null +++ b/plugins/BotTracking/tests/System/expected/test_ranking_limit_documents__BotTracking.getAIAssistantRequests_week.xml @@ -0,0 +1,47 @@ + + + + + 5 + 4 + 1 + 2 + + + + 1 + + + + 3 + + + + + + 5 + 1 + 4 + 1 + + + + 1 + + + + + + 4 + 0 + 4 + 0 + + + + 12 + 5 + 7 + 3 + + \ No newline at end of file diff --git a/plugins/BotTracking/tests/System/expected/test_ranking_limit_pages__BotTracking.getAIAssistantRequests_day.xml b/plugins/BotTracking/tests/System/expected/test_ranking_limit_pages__BotTracking.getAIAssistantRequests_day.xml new file mode 100644 index 00000000000..57897db29d5 --- /dev/null +++ b/plugins/BotTracking/tests/System/expected/test_ranking_limit_pages__BotTracking.getAIAssistantRequests_day.xml @@ -0,0 +1,47 @@ + + + + + 2 + 1 + 1 + 1 + + + + 1 + + + + + + 2 + 2 + 0 + 0 + + + + 2 + 0 + 2 + 0 + + + + 1 + + + + 1 + + + + + + 1 + 0 + 1 + 0 + + \ No newline at end of file diff --git a/plugins/BotTracking/tests/System/expected/test_ranking_limit_pages__BotTracking.getAIAssistantRequests_week.xml b/plugins/BotTracking/tests/System/expected/test_ranking_limit_pages__BotTracking.getAIAssistantRequests_week.xml new file mode 100644 index 00000000000..1170e001888 --- /dev/null +++ b/plugins/BotTracking/tests/System/expected/test_ranking_limit_pages__BotTracking.getAIAssistantRequests_week.xml @@ -0,0 +1,105 @@ + + + + + 4 + 2 + 2 + 2 + + + + 1 + + + + 1 + + + + + + 5 + 1 + 4 + 1 + + + + 1 + + + + 3 + + + + + + 2 + 0 + 2 + 1 + + + + 1 + + + + 1 + + + + + + 5 + 5 + 0 + 1 + + + + 2 + 0 + 2 + 0 + + + + 2 + + + + + + 2 + 2 + 0 + 0 + + + + 3 + 0 + 3 + 0 + + + + 2 + + + + 1 + + + + + + 3 + 0 + 3 + 0 + + \ No newline at end of file From 0f31e020cb3a56278fa3a426a9cc2b6b87340ec1 Mon Sep 17 00:00:00 2001 From: sgiehl Date: Wed, 3 Dec 2025 15:10:45 +0100 Subject: [PATCH 13/13] try using with rollup again --- .../RecordBuilders/AIAssistantReports.php | 44 +++++++------------ 1 file changed, 17 insertions(+), 27 deletions(-) diff --git a/plugins/BotTracking/RecordBuilders/AIAssistantReports.php b/plugins/BotTracking/RecordBuilders/AIAssistantReports.php index 9396f966212..5d70aa7a745 100644 --- a/plugins/BotTracking/RecordBuilders/AIAssistantReports.php +++ b/plugins/BotTracking/RecordBuilders/AIAssistantReports.php @@ -146,7 +146,6 @@ private function populateTableForActionType(array $tables, int $actionType, LogA { $resultSet = $this->queryBotRequests($logAggregator, $actionType); $actionRows = []; - $botTotals = []; while ($row = $resultSet->fetch()) { /** @@ -159,28 +158,18 @@ private function populateTableForActionType(array $tables, int $actionType, LogA continue; } - if (is_null($url)) { + if (!is_null($url)) { + $actionRows[] = $row; continue; } - $actionRows[] = $row; + $metrics = [ + Metrics::COLUMN_REQUESTS => $row['requests'], + Metrics::COLUMN_DOCUMENT_REQUESTS => $actionType === Action::TYPE_DOWNLOAD ? $row['requests'] : 0, + Metrics::COLUMN_PAGE_REQUESTS => $actionType === Action::TYPE_PAGE_URL ? $row['requests'] : 0, + Metrics::COLUMN_ACQUIRED_VISITS => $visits[$label] ?? 0, + ]; - if (!isset($botTotals[$label])) { - $botTotals[$label] = [ - Metrics::COLUMN_REQUESTS => 0, - Metrics::COLUMN_DOCUMENT_REQUESTS => 0, - Metrics::COLUMN_PAGE_REQUESTS => 0, - Metrics::COLUMN_ACQUIRED_VISITS => 0, - ]; - } - - $botTotals[$label][Metrics::COLUMN_REQUESTS] += $row['requests']; - $botTotals[$label][Metrics::COLUMN_DOCUMENT_REQUESTS] += $actionType === Action::TYPE_DOWNLOAD ? $row['requests'] : 0; - $botTotals[$label][Metrics::COLUMN_PAGE_REQUESTS] += $actionType === Action::TYPE_PAGE_URL ? $row['requests'] : 0; - $botTotals[$label][Metrics::COLUMN_ACQUIRED_VISITS] = max($botTotals[$label][Metrics::COLUMN_ACQUIRED_VISITS], $visits[$label] ?? 0); - } - - foreach ($botTotals as $label => $metrics) { $tables[Archiver::AI_ASSISTANTS_PAGES_RECORD]->sumRowWithLabel($label, $metrics, [Metrics::COLUMN_ACQUIRED_VISITS => 'max']); $tables[Archiver::AI_ASSISTANTS_DOCUMENTS_RECORD]->sumRowWithLabel($label, $metrics, [Metrics::COLUMN_ACQUIRED_VISITS => 'max']); } @@ -222,19 +211,20 @@ private function populateTableForActionType(array $tables, int $actionType, LogA private function queryBotRequests(LogAggregator $logAggregator, int $actionType) { $where = $logAggregator->getWhereStatement('bot', 'server_time'); - $where .= ' AND log_action.name IS NOT NULL - AND log_action.name <> \'\' - AND log_action.type = ' . $actionType; $sql = sprintf( - "SELECT bot.bot_name, log_action.name AS url, COUNT(*) AS requests + "SELECT * FROM (SELECT bot.bot_name, log_action.name AS url, COUNT(*) AS requests FROM %s AS bot INNER JOIN %s AS log_action ON log_action.idaction = bot.idaction_url - WHERE %s - GROUP BY bot.bot_name, url - ORDER BY bot.bot_name, requests DESC, url", + WHERE log_action.name IS NOT NULL + AND log_action.name <> '' + AND log_action.type = %d + AND %s + GROUP BY bot.bot_name, url WITH ROLLUP) AS rollupQuery + ORDER BY bot_name, requests DESC, url", BotRequestsDao::getPrefixedTableName(), Common::prefixTable('log_action'), + $actionType, $where ); @@ -242,7 +232,7 @@ private function queryBotRequests(LogAggregator $logAggregator, int $actionType) $rankingQuery = new RankingQuery($this->rankingQueryLimit); $rankingQuery->addLabelColumn(['bot_name', 'url']); $rankingQuery->addColumn('requests', 'sum'); - $sql = $rankingQuery->generateRankingQuery($sql); + $sql = $rankingQuery->generateRankingQuery($sql, true); } return Db::query($sql, $logAggregator->getGeneralQueryBindParams());