diff options
author | Kate Butler <kate@innocraft.com> | 2019-12-17 00:15:11 +0300 |
---|---|---|
committer | Thomas Steur <tsteur@users.noreply.github.com> | 2019-12-17 00:15:11 +0300 |
commit | 72eece3fbbb9df81f941a4cdbe83a928679daa18 (patch) | |
tree | 7d6e7c0cc0f81512891de2ab691a5c07cfdab45b /plugins/VisitFrequency | |
parent | 76102d2c9b21cd7317ed9d4e6ea7879f83b01474 (diff) |
Show 'new' metrics on visitor engagement report/sparklines (#15128)
Diffstat (limited to 'plugins/VisitFrequency')
-rw-r--r-- | plugins/VisitFrequency/API.php | 82 | ||||
-rw-r--r-- | plugins/VisitFrequency/Columns/Metrics/ReturningMetric.php | 12 | ||||
-rw-r--r-- | plugins/VisitFrequency/Controller.php | 38 | ||||
-rw-r--r-- | plugins/VisitFrequency/Reports/Get.php | 45 | ||||
-rw-r--r-- | plugins/VisitFrequency/VisitFrequency.php | 10 | ||||
-rw-r--r-- | plugins/VisitFrequency/lang/en.json | 12 | ||||
-rw-r--r-- | plugins/VisitFrequency/tests/Integration/APITest.php | 84 |
7 files changed, 224 insertions, 59 deletions
diff --git a/plugins/VisitFrequency/API.php b/plugins/VisitFrequency/API.php index 9ecb6b4157..e4155b28ff 100644 --- a/plugins/VisitFrequency/API.php +++ b/plugins/VisitFrequency/API.php @@ -12,6 +12,7 @@ use Piwik\API\Request; use Piwik\Archive; use Piwik\DataTable; use Piwik\Piwik; +use Piwik\Plugins\API\DataTable\MergeDataTables; use Piwik\Plugins\VisitsSummary\API as APIVisitsSummary; use Piwik\Segment\SegmentExpression; @@ -23,7 +24,10 @@ class API extends \Piwik\Plugin\API { // visitorType==returning,visitorType==returningCustomer const RETURNING_VISITOR_SEGMENT = "visitorType%3D%3Dreturning%2CvisitorType%3D%3DreturningCustomer"; - const COLUMN_SUFFIX = "_returning"; + const RETURNING_COLUMN_SUFFIX = "_returning"; + + const NEW_VISITOR_SEGMENT = 'visitorType%3D%3Dnew'; + const NEW_COLUMN_SUFFIX = "_new"; /** * @param int $idSite @@ -36,48 +40,80 @@ class API extends \Piwik\Plugin\API public function get($idSite, $period, $date, $segment = false, $columns = false) { Piwik::checkUserHasViewAccess($idSite); - $segment = $this->appendReturningVisitorSegment($segment); - - $this->unprefixColumns($columns); - $params = array( - 'idSite' => $idSite, - 'period' => $period, - 'date' => $date, - 'segment' => $segment, - 'columns' => implode(',', $columns), - 'format' => 'original', - 'format_metrics' => 0 + + $visitTypes = array( + self::NEW_COLUMN_SUFFIX => self::NEW_VISITOR_SEGMENT, + self::RETURNING_COLUMN_SUFFIX => self::RETURNING_VISITOR_SEGMENT ); - $table = Request::processRequest('VisitsSummary.get', $params); - $this->prefixColumns($table, $period); - return $table; + $columns = Piwik::getArrayFromApiParameter($columns); + + /** @var \Piwik\DataTable\DataTableInterface $resultSet */ + $resultSet = new DataTable(); + + foreach ($visitTypes as $columnSuffix => $visitorTypeSegment) { + $modifiedSegment = $this->appendVisitorTypeSegment($segment, $visitorTypeSegment); + + $columnsForVisitType = empty($columns) ? array() : $this->unprefixColumns($columns, $columnSuffix); + + // Only make the API call if either $columns is empty (i.e. no list of columns was passed in, so we + // should fetch all columns) or if one of the columns that was passed in is for this visitor type + if (!empty($columns) && empty($columnsForVisitType)) { + continue; + } + + $params = array( + 'idSite' => $idSite, + 'period' => $period, + 'date' => $date, + 'segment' => $modifiedSegment, + 'columns' => implode(',', $columnsForVisitType), + 'format' => 'original', + 'format_metrics' => 0 + ); + + /** @var \Piwik\DataTable\Map $response */ + $response = Request::processRequest('VisitsSummary.get', $params); + $this->prefixColumns($response, $period, $columnSuffix); + + if ($resultSet === null) { + $resultSet = $response; + } else { + $merger = new MergeDataTables(); + $merger->mergeDataTables($resultSet, $response); + } + } + + return $resultSet; } - protected function appendReturningVisitorSegment($segment) + protected function appendVisitorTypeSegment($segment, $toAppend) { if (empty($segment)) { $segment = ''; } else { $segment .= urlencode(SegmentExpression::AND_DELIMITER); } - $segment .= self::RETURNING_VISITOR_SEGMENT; + $segment .= $toAppend; return $segment; } - protected function unprefixColumns(&$columns) + protected function unprefixColumns(array $requestedColumns, $suffix) { - $columns = Piwik::getArrayFromApiParameter($columns); - foreach ($columns as &$column) { - $column = str_replace(self::COLUMN_SUFFIX, "", $column); + $result = array(); + foreach ($requestedColumns as $column) { + if (strpos($column, $suffix) !== false) { + $result[] = str_replace($suffix, '', $column); + } } + return $result; } - protected function prefixColumns($table, $period) + protected function prefixColumns($table, $period, $suffix) { $rename = array(); foreach (APIVisitsSummary::getInstance()->getColumns($period) as $oldColumn) { - $rename[$oldColumn] = $oldColumn . self::COLUMN_SUFFIX; + $rename[$oldColumn] = $oldColumn . $suffix; } $table->filter('ReplaceColumnNames', array($rename)); } diff --git a/plugins/VisitFrequency/Columns/Metrics/ReturningMetric.php b/plugins/VisitFrequency/Columns/Metrics/ReturningMetric.php index e0ebe49738..8c1806f9f6 100644 --- a/plugins/VisitFrequency/Columns/Metrics/ReturningMetric.php +++ b/plugins/VisitFrequency/Columns/Metrics/ReturningMetric.php @@ -23,8 +23,13 @@ class ReturningMetric extends ProcessedMetric { private static $translations = array( 'avg_time_on_site_returning' => 'VisitFrequency_ColumnAverageVisitDurationForReturningVisitors', + 'avg_time_on_site_new' => 'VisitFrequency_ColumnAverageVisitDurationForNewVisitors', 'nb_actions_per_visit_returning' => 'VisitFrequency_ColumnAvgActionsPerReturningVisit', + 'nb_actions_per_visit_new' => 'VisitFrequency_ColumnAvgActionsPerNewVisit', 'bounce_rate_returning' => 'VisitFrequency_ColumnBounceRateForReturningVisits', + 'bounce_rate_new' => 'VisitFrequency_ColumnBounceRateForNewVisits', + 'nb_users_returning' => 'VisitFrequency_ColumnReturningUsers', + 'nb_users_new' => 'VisitFrequency_ColumnNewUsers' ); /** @@ -32,14 +37,17 @@ class ReturningMetric extends ProcessedMetric */ private $wrapped; - public function __construct(ProcessedMetric $wrapped) + private $suffix; + + public function __construct(ProcessedMetric $wrapped, $suffix = '_returning') { $this->wrapped = $wrapped; + $this->suffix = $suffix; } public function getName() { - return $this->wrapped->getName() . '_returning'; + return $this->wrapped->getName() . $this->suffix; } public function getTranslatedName() diff --git a/plugins/VisitFrequency/Controller.php b/plugins/VisitFrequency/Controller.php index 479a91da5b..b4d7c4f88d 100644 --- a/plugins/VisitFrequency/Controller.php +++ b/plugins/VisitFrequency/Controller.php @@ -52,32 +52,24 @@ class Controller extends \Piwik\Plugin\Controller . $this->translator->translate('General_BrokenDownReportDocumentation') . '<br />' . $this->translator->translate('VisitFrequency_ReturningVisitDocumentation'); - // Note: if you edit this array, maybe edit the code below as well - $selectableColumns = array( - // columns from VisitFrequency.get - 'nb_visits_returning', - 'nb_actions_returning', - 'nb_actions_per_visit_returning', - 'bounce_rate_returning', - 'avg_time_on_site_returning', - // columns from VisitsSummary.get - 'nb_visits', - 'nb_actions', - 'nb_actions_per_visit', - 'bounce_rate', - 'avg_time_on_site' - ); - $period = Common::getRequestVar('period', false); + $columnNames = array('nb_visits'); if (SettingsPiwik::isUniqueVisitorsEnabled($period)) { - // add number of unique (returning) visitors for period=day - $selectableColumns = array_merge( - array($selectableColumns[0]), - array('nb_uniq_visitors_returning'), - array_slice($selectableColumns, 1, -4), - array('nb_uniq_visitors'), - array_slice($selectableColumns, -4)); + $columnNames[] = 'nb_uniq_visitors'; + } + $columnNames[] = 'nb_actions'; + $columnNames[] = 'nb_actions_per_visit'; + $columnNames[] = 'bounce_rate'; + $columnNames[] = 'avg_time_on_site'; + + $suffixes = array('_returning', '_new', ''); + + $selectableColumns = array(); + foreach ($suffixes as $suffix) { + foreach ($columnNames as $column) { + $selectableColumns[] = $column . $suffix; + } } $view = $this->getLastUnitGraphAcrossPlugins($this->pluginName, __FUNCTION__, $columns, diff --git a/plugins/VisitFrequency/Reports/Get.php b/plugins/VisitFrequency/Reports/Get.php index 97d671e5d5..0599e1cb41 100644 --- a/plugins/VisitFrequency/Reports/Get.php +++ b/plugins/VisitFrequency/Reports/Get.php @@ -17,6 +17,7 @@ use Piwik\Plugins\CoreHome\Columns\Metrics\AverageTimeOnSite; use Piwik\Plugins\CoreHome\Columns\Metrics\BounceRate; use Piwik\Plugins\CoreVisualizations\Visualizations\JqplotGraph\Evolution; use Piwik\Plugins\CoreVisualizations\Visualizations\Sparklines; +use Piwik\Plugins\VisitFrequency\API; use Piwik\Plugins\VisitFrequency\Columns\Metrics\ReturningMetric; use Piwik\Report\ReportWidgetFactory; use Piwik\Widget\WidgetsList; @@ -30,16 +31,25 @@ class Get extends \Piwik\Plugin\Report $this->name = Piwik::translate('VisitFrequency_ColumnReturningVisits'); $this->documentation = ''; // TODO $this->processedMetrics = array( - new ReturningMetric(new AverageTimeOnSite()), - new ReturningMetric(new ActionsPerVisit()), - new ReturningMetric(new BounceRate()) + new ReturningMetric(new AverageTimeOnSite(), API::RETURNING_COLUMN_SUFFIX), + new ReturningMetric(new ActionsPerVisit(), API::RETURNING_COLUMN_SUFFIX), + new ReturningMetric(new BounceRate(), API::RETURNING_COLUMN_SUFFIX), + new ReturningMetric(new AverageTimeOnSite(), API::NEW_COLUMN_SUFFIX), + new ReturningMetric(new ActionsPerVisit(), API::NEW_COLUMN_SUFFIX), + new ReturningMetric(new BounceRate(), API::NEW_COLUMN_SUFFIX) ); $this->metrics = array( 'nb_visits_returning', 'nb_actions_returning', 'nb_uniq_visitors_returning', 'nb_users_returning', - 'max_actions_returning' + 'max_actions_returning', + + 'nb_visits_new', + 'nb_actions_new', + 'nb_uniq_visitors_new', + 'nb_users_new', + 'max_actions_new', ); $this->order = 40; $this->subcategoryId = 'VisitorInterest_Engagement'; @@ -106,6 +116,12 @@ class Get extends \Piwik\Plugin\Report 'nb_actions_per_visit_returning' => 'ReturnAvgActions', 'avg_time_on_site_returning' => 'ReturnAverageVisitDuration', 'bounce_rate_returning' => 'ReturnBounceRate', + + 'nb_visits_new' => 'NewVisits', + 'nb_actions_new' => 'NewActions', + 'nb_actions_per_visit_new' => 'NewAvgActions', + 'avg_time_on_site_new' => 'NewAverageVisitDuration', + 'bounce_rate_new' => 'NewBounceRate', ); foreach ($translations as $metric => $key) { @@ -117,11 +133,20 @@ class Get extends \Piwik\Plugin\Report private function addSparklineColumns(Sparklines $view) { - $view->config->addSparklineMetric(array('nb_visits_returning')); - $view->config->addSparklineMetric(array('avg_time_on_site_returning')); - $view->config->addSparklineMetric(array('nb_actions_per_visit_returning')); - $view->config->addSparklineMetric(array('bounce_rate_returning')); - $view->config->addSparklineMetric(array('nb_actions_returning')); - } + $metrics = array( + 'nb_visits', + 'avg_time_on_site', + 'nb_actions_per_visit', + 'bounce_rate', + 'nb_actions' + ); + $i = 1; + foreach ($metrics as $metric) { + foreach (array('_returning', '_new') as $suffix) { + $view->config->addSparklineMetric(array($metric . $suffix), $i++); + } + } + + } } diff --git a/plugins/VisitFrequency/VisitFrequency.php b/plugins/VisitFrequency/VisitFrequency.php index f6f5ccbcd0..9e64e5a08d 100644 --- a/plugins/VisitFrequency/VisitFrequency.php +++ b/plugins/VisitFrequency/VisitFrequency.php @@ -32,7 +32,15 @@ class VisitFrequency extends \Piwik\Plugin 'bounce_rate_returning' => 'VisitFrequency_ColumnBounceRateForReturningVisits', 'nb_actions_per_visit_returning' => 'VisitFrequency_ColumnAvgActionsPerReturningVisit', 'nb_uniq_visitors_returning' => 'VisitFrequency_ColumnUniqueReturningVisitors', - 'nb_users_returning' => 'VisitFrequency_ColumnReturningUsers' + 'nb_users_returning' => 'VisitFrequency_ColumnReturningUsers', + + 'nb_visits_new' => 'VisitFrequency_ColumnNewVisits', + 'nb_actions_new' => 'VisitFrequency_ColumnActionsByNewVisits', + 'avg_time_on_site_new' => 'VisitFrequency_ColumnAverageVisitDurationForNewVisitors', + 'bounce_rate_new' => 'VisitFrequency_ColumnBounceRateForNewVisits', + 'nb_actions_per_visit_new' => 'VisitFrequency_ColumnAvgActionsPerNewVisit', + 'nb_uniq_visitors_new' => 'VisitFrequency_ColumnUniqueNewVisitors', + 'nb_users_new' => 'VisitFrequency_ColumnNewUsers' ); $translations = array_merge($translations, $metrics); diff --git a/plugins/VisitFrequency/lang/en.json b/plugins/VisitFrequency/lang/en.json index 39b1879852..6cdd0764cf 100644 --- a/plugins/VisitFrequency/lang/en.json +++ b/plugins/VisitFrequency/lang/en.json @@ -1,16 +1,28 @@ { "VisitFrequency": { + "ColumnActionsByNewVisits": "Actions by New Visits", "ColumnActionsByReturningVisits": "Actions by Returning Visits", + "ColumnAverageVisitDurationForNewVisitors": "Avg. Duration of a New Visit (in sec)", "ColumnAverageVisitDurationForReturningVisitors": "Avg. Duration of a Returning Visit (in sec)", + "ColumnAvgActionsPerNewVisit": "Avg. Actions per New Visit", "ColumnAvgActionsPerReturningVisit": "Avg. Actions per Returning Visit", "ColumnBounceCountForReturningVisits": "Bounce Count for Returning Visits", + "ColumnBounceRateForNewVisits": "Bounce Rate for New Visits", "ColumnBounceRateForReturningVisits": "Bounce Rate for Returning Visits", "ColumnMaxActionsInReturningVisit": "Maximum actions in one returning visit", "ColumnNbReturningVisitsConverted": "Number of converted returning visits", + "ColumnNewVisits": "New Visits", "ColumnReturningVisits": "Returning Visits", "ColumnSumVisitLengthReturning": "Total time spent by returning visitors (in seconds)", + "ColumnUniqueNewVisitors": "Unique new visitors", "ColumnUniqueReturningVisitors": "Unique returning visitors", + "ColumnNewUsers": "New Users", "ColumnReturningUsers": "Returning Users", + "NewActions": "actions by the new visits", + "NewAverageVisitDuration": "average visit duration for new visitors", + "NewAvgActions": "actions per new visit", + "NewBounceRate": "new visits have bounced (left the website after one page)", + "NewVisits": "new visits", "PluginDescription": "Reports metrics about your first time new visitors and returning visitors.", "ReturnActions": "actions by the returning visits", "ReturnAverageVisitDuration": "average visit duration for returning visitors", diff --git a/plugins/VisitFrequency/tests/Integration/APITest.php b/plugins/VisitFrequency/tests/Integration/APITest.php new file mode 100644 index 0000000000..dfba727d4f --- /dev/null +++ b/plugins/VisitFrequency/tests/Integration/APITest.php @@ -0,0 +1,84 @@ +<?php +/** + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + +namespace Piwik\Plugins\VisitFrequency\tests; + +use Piwik\DataTable\DataTableInterface; +use Piwik\Plugins\VisitFrequency\API; +use Piwik\Tests\Framework\Fixture; +use Piwik\Tests\Framework\TestCase\IntegrationTestCase; + +class APITest extends IntegrationTestCase +{ + private $api; + + private $idSite; + + public function setUp() + { + parent::setUp(); + $this->api = API::getInstance(); + + $this->idSite = Fixture::createWebsite('2018-12-01'); + } + + public function testNewMetricsOnly() + { + $columns = array('nb_visits_new', 'nb_actions_new'); + + /** @var DataTableInterface $dataTable */ + $dataTable = $this->api->get($this->idSite, 'week', '2019-01-01', false, $columns); + $this->assertEquals($dataTable->getRowsCount(), 1); + $columnsReturned = array_keys($dataTable->getFirstRow()->getArrayCopy()); + + $this->assertEquals($columns, $columnsReturned); + } + + public function testReturningMetricsOnly() + { + $columns = array('nb_visits_returning', 'nb_uniq_visitors_returning'); + + /** @var DataTableInterface $dataTable */ + $dataTable = $this->api->get($this->idSite, 'week', '2019-01-01', false, $columns); + $this->assertEquals($dataTable->getRowsCount(), 1); + $columnsReturned = array_keys($dataTable->getFirstRow()->getArrayCopy()); + + $this->assertEquals($columns, $columnsReturned); + } + + public function testNoNewOrReturningMetrics() + { + $columns = array('nb_visits'); + + /** @var DataTableInterface $dataTable */ + $dataTable = $this->api->get($this->idSite, 'week', '2019-01-01', false, $columns); + $this->assertEquals($dataTable->getRowsCount(), 0); + } + + public function testDifferentNewAndReturningMetrics() + { + $columns = array('nb_visits_new', 'nb_actions_per_visit_new', 'nb_actions_returning', 'avg_time_on_site_returning'); + + /** @var DataTableInterface $dataTable */ + $dataTable = $this->api->get($this->idSite, 'week', '2019-01-01', false, $columns); + $this->assertEquals($dataTable->getRowsCount(), 1); + $columnsReturned = array_keys($dataTable->getFirstRow()->getArrayCopy()); + + $this->assertEquals($columns, $columnsReturned); + } + + public function testNoColumnsPassed() + { + /** @var DataTableInterface $dataTable */ + $dataTable = $this->api->get($this->idSite, 'week', '2019-01-01'); + $this->assertEquals($dataTable->getRowsCount(), 1); + $columnsReturned = array_keys($dataTable->getFirstRow()->getArrayCopy()); + + $this->assertCount(22, $columnsReturned); + } +}
\ No newline at end of file |