Skip to content

Commit

Permalink
Report with archived data now available
Browse files Browse the repository at this point in the history
  • Loading branch information
mikkeschiren committed Jan 13, 2025
1 parent 4b9b5f6 commit 5b916c1
Show file tree
Hide file tree
Showing 14 changed files with 249 additions and 176 deletions.
50 changes: 50 additions & 0 deletions API.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@
use Exception;
use Piwik\Plugins\SimpleABTesting\Dao\Experiments;
use Piwik\Container\StaticContainer;
use Piwik\ArchiveProcessor\Parameters;
use Piwik\API\Request;
use Piwik\DataTable;
use Piwik\Archive;
use Piwik\ArchiveProcessor;

/**
* API for plugin RebelNotifications. With this you can handle notifications to
Expand Down Expand Up @@ -47,4 +52,49 @@ public function deleteExperiment(bool $id): void
Piwik::checkUserHasSomeAdminAccess();
$this->experiments->deleteExperiment($id);
}

/**
* Get report data for the experiment report (calls API endpoint).
*/
public function getExperimentReportData($idSite, $period, $date)
{
Piwik::checkUserHasViewAccess($idSite);
// SQL query to fetch experiment report data
$sql = "
SELECT
experiment_name AS `experiment_name`,
COUNT(DISTINCT idvisitor) AS `nb_unique_visitors`,
COUNT(*) AS `nb_visits`
FROM " . Common::prefixTable('simple_ab_testing_log') . "
WHERE idsite = ?
GROUP BY experiment_name
";

// Fetch and return data
return Db::fetchAll($sql, [$idSite]);
}

/**
* Fetch experiment data from the archive blobs for reports or APIs.
*
* @param int $idSite The site ID.
* @param string $period The period (e.g., 'day', 'week', 'month').
* @param string $date The date range (e.g., 'today', 'last7', '2024-01-01').
* @param string|null $segment The segment string (optional, default is null).
* @return DataTable The archived experiment data grouped by experiment_name.
*/
public function getExperimentData(int $idSite, string $period, string $date, string $segment = null): DataTable
{
// Use Matomo's Archive to fetch the archived data
//Piwik::checkUserHasViewAccess($idSite);
$dataTable = Archive::createDataTableFromArchive(
Archiver::RECORD_NAME,
$idSite,
$period,
$date,
$segment
);
// $data = gzuncompress(hex2bin('789C4BB432B0AAAE0500064F01FE'));
return $dataTable;
}
}
76 changes: 76 additions & 0 deletions Archiver.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
<?php

namespace Piwik\Plugins\SimpleABTesting;

use Piwik\Common;
use Piwik\DataTable;
use Piwik\Plugin\Archiver as MatomoArchiver;
use Piwik\Db;
use Piwik\Log\LoggerInterface;
use Piwik\Container\StaticContainer;

class Archiver extends MatomoArchiver
{
const RECORD_NAME = 'SimpleABTesting_ExperimentData';
const DIMENSION = 'experiment_name';

public function aggregateDayReport()
{
// Logger for debugging
/** @var LoggerInterface $logger */
$logger = StaticContainer::get('Psr\Log\LoggerInterface');
$logger->debug('SimpleABTesting: Starting day report aggregation.');

// Step 1: Retrieve archiving parameters from the processor
$params = $this->getProcessor()->getParams();
$idSite =$this->getProcessor()->getParams()->getSite()->getId();
$dateStart = $params->getDateStart()->toString('Y-m-d 00:00:00');
$dateEnd = $params->getDateEnd()->toString('Y-m-d 23:59:59');

$logger->debug("SimpleABTesting: Archiving params: idSite={$idSite}, dateStart={$dateStart}, dateEnd={$dateEnd}");

$query = "
SELECT
experiment_name AS label,
COUNT(*) AS nb_visits,
COUNT(DISTINCT idvisitor) AS nb_unique_visitors
FROM " . Common::prefixTable('simple_ab_testing_log') . "
WHERE idsite = ?
AND server_time BETWEEN ? AND ?
GROUP BY experiment_name
";

$logger->debug("SimpleABTesting: Running query: {$query}");

// Execute the query
$rows = Db::fetchAll($query, [$idSite, $dateStart, $dateEnd]);

if (empty($rows)) {
// Warn if no rows are fetched
$logger->warning("SimpleABTesting: No rows fetched for site: {$idSite}");
} else {
$logger->debug('SimpleABTesting: Rows fetched: ' . print_r($rows, true));
}

// Step 3: Convert SQL rows to DataTable
$dataTable = new DataTable();
foreach ($rows as $row) {
$dataTable->addRowFromSimpleArray([
'label' => $row['label'],
'nb_visits' => $row['nb_visits'],
'nb_unique_visitors' => $row['nb_unique_visitors'],
]);
}

// Step 4: Save the DataTable in archive records as a blob
$this->getProcessor()->insertBlobRecord(self::RECORD_NAME, $dataTable->getSerialized());
}

/**
* Aggregate data across multiple periods (e.g., week, month, year).
*/
public function aggregateMultipleReports()
{
$this->getProcessor()->aggregateDataTableRecords([self::RECORD_NAME]);
}
}
58 changes: 29 additions & 29 deletions Columns/ExperimentCount.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,36 +46,36 @@ class ExperimentCount extends Dimension
* @param Action|null $action
* @return mixed|false
*/
public function onNewVisit(Request $request, Visitor $visitor, $action)
{
$paramValue = Common::getRequestVar('sabt', '', 'string', $request->getParams());
if (isset($paramValue)) {
return 1;
}
return 0;
}
// public function onNewVisit(Request $request, Visitor $visitor, $action)
// {
// $paramValue = Common::getRequestVar('sabt', '', 'string', $request->getParams());
// if (isset($paramValue)) {
// return 1;
// }
// return 0;
// }

/**
* The onExistingVisit method is triggered when a visitor was recognized meaning it is not a new visitor.
* If you want you can overwrite any previous value set by the event onNewVisit. By returning boolean false no value
* will be updated. If you do not want to perform any action on a new visit you can just remove this method.
*
* @param Request $request
* @param Visitor $visitor
* @param Action|null $action
*
* @return mixed|false
*/
public function onExistingVisit(Request $request, Visitor $visitor, $action)
{
$paramValue = Common::getRequestVar('sabt', '', 'string', $request->getParams());
if (isset($paramValue)) {
return $visitor->getVisitorColumn($this->columnName) + 1;
}
if (empty($action)) {
return false; // Do not change an already persisted value
}
}
// /**
// * The onExistingVisit method is triggered when a visitor was recognized meaning it is not a new visitor.
// * If you want you can overwrite any previous value set by the event onNewVisit. By returning boolean false no value
// * will be updated. If you do not want to perform any action on a new visit you can just remove this method.
// *
// * @param Request $request
// * @param Visitor $visitor
// * @param Action|null $action
// *
// * @return mixed|false
// */
// public function onExistingVisit(Request $request, Visitor $visitor, $action)
// {
// $paramValue = Common::getRequestVar('sabt', '', 'string', $request->getParams());
// if (isset($paramValue)) {
// return $visitor->getVisitorColumn($this->columnName) + 1;
// }
// if (empty($action)) {
// return false; // Do not change an already persisted value
// }
// }

/**
* This event is executed shortly after "onNewVisit" or "onExistingVisit" in case the visitor converted a goal.
Expand Down
24 changes: 3 additions & 21 deletions Columns/ExperimentName.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,8 @@

namespace Piwik\Plugins\SimpleABTesting\Columns;

use Piwik\Common;
use Piwik\Tracker\Request;
use Piwik\Columns\Dimension;
use Piwik\Common;

class ExperimentName extends Dimension
{
Expand All @@ -17,25 +16,8 @@ class ExperimentName extends Dimension
protected $sqlSegment = 'simple_ab_testing_log.experiment_name';
protected $segmentName = 'experimentName';

public function onNewVisit(Request $request, $visitor, $action)
public function getExpression()
{
// Extract the experiment name from the tracking request's "experiment" parameter
$experimentName = Common::getRequestVar('experiment', '', 'string', $request->getParams());

if (!empty($experimentName)) {
return $experimentName;
}
return null; // No value to log if there's no experiment name.
}

public function onExistingVisit(Request $request, $visitor, $action)
{
// Extract the experiment name from the tracking request's "experiment" parameter
$experimentName = Common::getRequestVar('experiment', '', 'string', $request->getParams());

if (!empty($experimentName)) {
return $experimentName;
}
return null; // No value to log if there's no experiment name.
return Common::prefixTable($this->sqlSegment); // Matching column in the database table
}
}
54 changes: 27 additions & 27 deletions Columns/IsExperiment.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,34 +46,34 @@ class IsExperiment extends Dimension
* @param Action|null $action
* @return mixed|false
*/
public function onNewVisit(Request $request, Visitor $visitor, $action)
{
$paramValue = Common::getRequestVar('sabt', '', 'string', $request->getParams());
if (isset($paramValue)) {
return $paramValue;
}
return 0;
}
// public function onNewVisit(Request $request, Visitor $visitor, $action)
// {
// $paramValue = Common::getRequestVar('sabt', '', 'string', $request->getParams());
// if (isset($paramValue)) {
// return $paramValue;
// }
// return 0;
// }

/**
* The onExistingVisit method is triggered when a visitor was recognized meaning it is not a new visitor.
* If you want you can overwrite any previous value set by the event onNewVisit. By returning boolean false no value
* will be updated. If you do not want to perform any action on a new visit you can just remove this method.
*
* @param Request $request
* @param Visitor $visitor
* @param Action|null $action
*
* @return mixed|false
*/
public function onExistingVisit(Request $request, Visitor $visitor, $action)
{
$paramValue = Common::getRequestVar('sabt', '', 'string', $request->getParams());
if (isset($paramValue)) {
return $paramValue;
}
return 0;
}
// /**
// * The onExistingVisit method is triggered when a visitor was recognized meaning it is not a new visitor.
// * If you want you can overwrite any previous value set by the event onNewVisit. By returning boolean false no value
// * will be updated. If you do not want to perform any action on a new visit you can just remove this method.
// *
// * @param Request $request
// * @param Visitor $visitor
// * @param Action|null $action
// *
// * @return mixed|false
// */
// public function onExistingVisit(Request $request, Visitor $visitor, $action)
// {
// $paramValue = Common::getRequestVar('sabt', '', 'string', $request->getParams());
// if (isset($paramValue)) {
// return $paramValue;
// }
// return 0;
// }

/**
* This event is executed shortly after "onNewVisit" or "onExistingVisit" in case the visitor converted a goal.
Expand Down
36 changes: 17 additions & 19 deletions Controller.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@
use Piwik\Plugins\SimpleABTesting\API;
use Piwik\Plugins\SimpleABTesting\Helpers;
use Piwik\Request;
use Piwik\View;
use Piwik\Db;
use Piwik\ViewDataTable\Factory;

class Controller extends \Piwik\Plugin\Controller
{
Expand Down Expand Up @@ -90,24 +89,23 @@ private function securityChecks()
}
}

public function getExperimentReport()
public function getExperimentReport($fetch = false)
{
$view = new View('@SimpleABTesting/experiment_report');
$sql = "
SELECT
idvisit,
sabt_experiment_name AS Experiment,
sabt_is_variant AS IsVariant,
sabt_count AS NbVisits
FROM matomo_log_visit
WHERE sabt_experiment_name IS NOT NULL
GROUP BY idvisit, sabt_experiment_name, sabt_is_variant
";

$data = Db::fetchAll($sql);
$view->title = 'Experiment Report';
$view->data = $data;

Piwik::checkUserHasSomeViewAccess();
// Build the ViewDataTable object
$view = Factory::build('table', 'SimpleABTesting.getExperimentData');
//$this->setPeriodVariablesView($view);
$view->config->columns_to_display = ['label', 'nb_visits', 'nb_unique_visitors'];
$view->config->addTranslation('label', Piwik::translate('SimpleABTesting_ExperimentName'));
$view->config->addTranslation('nb_visits', Piwik::translate('SimpleABTesting_NbVisits'));
$view->config->addTranslation('nb_unique_visitors', Piwik::translate('SimpleABTesting_NbUniqueVisitors'));

// Configure sorting options
$view->requestConfig->filter_sort_column = 'nb_visits';
$view->requestConfig->filter_sort_order = 'desc';

// Render the report and return the view (fetched if required)
return $view->render();
}

}
3 changes: 2 additions & 1 deletion Reports/Base.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@
namespace Piwik\Plugins\SimpleABTesting\Reports;

use Piwik\Plugin\Report;
use Piwik\Piwik;

abstract class Base extends Report
{
protected function init()
{
$this->categoryId = 'SimpleABTesting_SimpleABTesting';
$this->categoryId = 'SimpleABTesting_SimpleABTesting'; // Report category
}
}
Loading

0 comments on commit 5b916c1

Please sign in to comment.