matomo / plugins /BotTracking /BotTracking.php
Leon4gr45's picture
Upload source files chunk 18
78185c4 verified
Raw
History Blame Contribute Delete
7.83 kB
<?php
/**
* Matomo - free/libre analytics platform
*
* @link https://matomo.org
* @license https://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
*/
declare(strict_types=1);
namespace Piwik\Plugins\BotTracking;
use Piwik\Date;
use Piwik\Piwik;
use Piwik\Plugin;
use Piwik\Plugins\BotTracking\Dao\BotRequestsDao;
use Piwik\Plugins\SitesManager\API;
use Piwik\Plugins\BotTracking\Metrics as BotMetrics;
use Piwik\Plugins\BotTracking\Reports\AIChatbotsRealTimeWidgets;
use Piwik\Tracker\Request;
/**
* BotTracking Plugin
*
* Tracks AI assistant and bot interactions without creating visits.
* Stores telemetry data in dedicated tables for analysis of bot behavior
* and system performance.
*/
class BotTracking extends Plugin
{
/**
* @return bool
*/
public function isTrackerPlugin()
{
return true;
}
/**
* @return array<string, string>
*/
public function registerEvents(): array
{
return [
'AssetManager.getStylesheetFiles' => 'getStylesheetFiles',
'PrivacyManager.deleteLogsOlderThan' => 'deleteLogsOlderThan',
'PrivacyManager.deleteDataSubjectsForDeletedSites' => 'deleteDataSubjectsForDeletedSites',
'Tracker.isBotRequest' => 'isBotRequest',
'Translate.getClientSideTranslationKeys' => 'getClientSideTranslationKeys',
'Metrics.getEvolutionUnit' => 'getEvolutionUnit',
'Metrics.getDefaultMetricTranslations' => 'addMetricTranslations',
'Metrics.getDefaultMetricDocumentationTranslations' => 'addMetricDocumentationTranslations',
'Metrics.getDefaultMetricSemanticTypes' => 'addMetricSemanticTypes',
'API.addGlossaryItems' => 'addGlossaryItems',
];
}
/**
* @return void
*/
public function install()
{
(new BotRequestsDao())->createTable();
}
/**
* @return void
*/
public function uninstall()
{
(new BotRequestsDao())->dropTable();
}
public function deleteLogsOlderThan(Date $dateUpperLimit): void
{
(new BotRequestsDao())->deleteOldRecords($dateUpperLimit);
}
/**
* @param array<string, int> $result
*/
public function deleteDataSubjectsForDeletedSites(array &$result): void
{
$allExistingIdSites = API::getInstance()->getAllSitesId();
$allExistingIdSites = array_map('intval', $allExistingIdSites);
$maxIdSite = max($allExistingIdSites);
if (empty($maxIdSite)) {
return;
}
$dao = new BotRequestsDao();
$idSitesInTable = $dao->getDistinctIdSitesInTable($maxIdSite);
$idSitesNoLongerExisting = array_diff($idSitesInTable, $allExistingIdSites);
if (count($idSitesNoLongerExisting) > 0) {
$result[$dao::getTableName()] = $dao->deleteRecordsForIdSites($idSitesNoLongerExisting);
}
}
/**
* @todo Remove, once Device Detector is able to detect all known ai bots
*/
public function isBotRequest(bool &$isBot, Request $request): void
{
$botDetector = new BotDetector($request->getUserAgent());
if ($botDetector->isBot()) {
$isBot = true;
}
}
public function getEvolutionUnit(?string &$unit, string $column): void
{
if ($column === Metrics::METRIC_AI_CHATBOTS_CLICK_THROUGH_RATE) {
$unit = '%';
}
}
/**
* @param array<string, string> $translations
*/
public function addMetricTranslations(array &$translations): void
{
$translations = array_merge($translations, BotMetrics::getMetricTranslations());
// Register a default name for the generic 'requests' column used by the new content-URL
// reports. Without this the Glossary majority heuristic renders name = null for the
// 'requests' metric because three reports expose it under different per-report scoped
// documentation strings, leaving no single translation with a majority. Registering the
// default here mirrors the documentation registration in addMetricDocumentationTranslations.
if (!isset($translations[Metrics::COLUMN_REQUESTS])) {
$translations[Metrics::COLUMN_REQUESTS] = Piwik::translate('BotTracking_ColumnRequests');
}
}
/**
* @param array<string, string> $translations
*/
public function addMetricDocumentationTranslations(array &$translations): void
{
$translations = array_merge($translations, BotMetrics::getMetricDocumentation());
// Register a default documentation for the generic 'requests' column used by the
// new content-URL reports. Without this default the Glossary majority heuristic
// (array_sum - max < max) would not pick a winner because the three reports that
// expose 'requests' each use a different documentation string (generic, page-scoped,
// document-scoped), leaving no single value with a majority. Setting a default here
// ensures the metric always appears in the glossary with the generic tooltip.
if (!isset($translations[Metrics::COLUMN_REQUESTS])) {
$translations[Metrics::COLUMN_REQUESTS] = Piwik::translate('BotTracking_ColumnRequestsDocumentation');
}
}
/**
* @param array<string|int, string> $types
*/
public function addMetricSemanticTypes(array &$types): void
{
$types = array_merge($types, BotMetrics::getMetricSemanticTypes());
}
/**
* @param array<string, array{title: string, entries: array<int, array<string, string>>}> $glossaryItems
*/
public function addGlossaryItems(array &$glossaryItems): void
{
Piwik::checkUserHasSomeViewAccess();
$category = Piwik::translate('General_AIAssistants');
foreach (AIChatbotsRealTimeWidgets::getAllWidgets() as $widget) {
$glossaryItems['reports']['entries'][] = [
'name' => sprintf('%s (%s)', Piwik::translate($widget['name']), $category),
'documentation' => Piwik::translate($widget['documentation']),
];
}
}
/**
* @param string[] $translationKeys
* @return void
*/
public function getClientSideTranslationKeys(&$translationKeys)
{
$translationKeys[] = 'BotTracking_DetectingYourSite';
$translationKeys[] = 'BotTracking_SiteWithoutDataBackToMatomo';
$translationKeys[] = 'BotTracking_SiteWithoutDataChooseTrackingMethod';
$translationKeys[] = 'BotTracking_SiteWithoutDataChooseTrackingMethodPreamble1';
$translationKeys[] = 'BotTracking_SiteWithoutDataChooseTrackingMethodPreamble2';
$translationKeys[] = 'BotTracking_SiteWithoutDataInstallWithX';
$translationKeys[] = 'BotTracking_SiteWithoutDataNotYetReady';
$translationKeys[] = 'BotTracking_SiteWithoutDataOtherInstallMethods';
$translationKeys[] = 'BotTracking_SiteWithoutDataOtherInstallMethodsIntro';
$translationKeys[] = 'BotTracking_SiteWithoutDataInstallWithXRecommendation';
$translationKeys[] = 'BotTracking_SiteWithoutDataRecommendationText';
$translationKeys[] = 'General_ErrorRequest';
$translationKeys[] = 'General_Refresh';
$translationKeys[] = 'Mobile_NavigationBack';
$translationKeys[] = 'BotTracking_NoRecentAIBotRequests';
}
/**
* @param string[] $stylesheets
* @return void
*/
public function getStylesheetFiles(&$stylesheets)
{
$stylesheets[] = "plugins/BotTracking/stylesheets/BotTracking.less";
}
}