Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
<?php
/**
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade Smile ElasticSuite to newer
* versions in the future.
*
* @category Smile
* @package Smile\ElasticsuiteAnalytics
* @author Richard BAYET <richard.bayet@smile.fr>
* @copyright 2020 Smile
* @license Open Software License ("OSL") v. 3.0
*/

namespace Smile\ElasticsuiteAnalytics\Block\Adminhtml\Search\Usage\Chart;

use Smile\ElasticsuiteAnalytics\Block\Adminhtml\Search\Usage\ChartInterface;

/**
* View origins graph block.
*
* @category Smile
* @package Smile\ElasticsuiteAnalytics\Block\Adminhtml\Search\Usage
*/
class ViewOrigins extends \Magento\Backend\Block\Template implements ChartInterface
{
/**
* @var \Smile\ElasticsuiteAnalytics\Model\Search\Usage\Kpi\Report
*/
private $report;

/**
* @var \Magento\Framework\Serialize\Serializer\Json
*/
private $serializer;

/**
* Constructor.
*
* @param \Magento\Backend\Block\Template\Context $context Context.
* @param \Smile\ElasticsuiteAnalytics\Model\Search\Usage\Kpi\Report $report KPI report model.
* @param \Magento\Framework\Serialize\Serializer\Json $serializer Json serializer.
* @param array $data Data.
*/
public function __construct(
\Magento\Backend\Block\Template\Context $context,
\Smile\ElasticsuiteAnalytics\Model\Search\Usage\Kpi\Report $report,
\Magento\Framework\Serialize\Serializer\Json $serializer,
array $data = []
) {
parent::__construct($context, $data);
$this->report = $report;
$this->serializer = $serializer;
}

/**
* {@inheritdoc}
*/
public function getChartOptions()
{
$options = [
'colors' => [
self::COLOR_RED,
self::COLOR_BLUE,
self::COLOR_GREEN,
self::COLOR_YELLOW,
self::COLOR_GRAY,
self::COLOR_PINK,
],
];

return $this->serializer->serialize($options);
}

/**
* {@inheritdoc}
*/
public function getChartData()
{
$rawData = [];
$data = [
'cols' => [
['type' => 'string', 'label' => __('Session type')],
['type' => 'number', 'label' => __('Count')],
],
'rows' => [],
];

try {
$reportData = $this->report->getData();
if (array_key_exists('product_views_count', $reportData)) {
unset($reportData['product_views_count']);
foreach ($reportData as $key => $value) {
if (str_starts_with($key, 'product_views_')) {
$label = $this->report->getLabel($key);
if (!array_key_exists($label, $rawData)) {
$rawData[$label] = 0;
}
$rawData[$label] += (int) $value;
}
}
foreach ($rawData as $label => $count) {
$data['rows'][] = ['c' => [['v' => $label], ['v' => $count]]];
}
}
} catch (\LogicException $e) {
;
}

return $this->serializer->serialize($data);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,21 @@ interface ChartInterface
*/
const COLOR_GREEN = '#25BC94';

/**
* Constant for yellow background/drawing chart color
*/
const COLOR_YELLOW = '#FFB800';

/**
* Constant for gray background/drawing chart color
*/
const COLOR_GRAY = '#6B7280';

/**
* Constant for pink background/drawing chart color
*/
const COLOR_PINK = '#EC4899';

/**
* Return chart data in the format expected by Google Charts API as a JSON encoded string.
* (see https://developers.google.com/chart/interactive/docs/reference#dataparam)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ public function getAggregation()
'name' => 'data',
'queries' => $this->getQueries(),
'metrics' => $this->getMetrics(),
'childBuckets' => $this->getChildBuckets(),
];

return $this->aggregationFactory->create(BucketInterface::TYPE_QUERY_GROUP, $aggParams);
Expand Down Expand Up @@ -143,4 +144,19 @@ private function getQueries()

return $queries;
}

/**
* Return child bucket for query group aggregation.
*
* @return array
*/
private function getChildBuckets(): array
{
return [
'origin' => $this->aggregationFactory->create(
BucketInterface::TYPE_TERM,
['name' => 'origin', 'field' => 'previous_page.type.identifier.keyword']
),
];
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,32 @@ class Report extends AbstractReport
'spellcheck_usage_rate',
];

/**
* Get data label.
*
* @param string $origin Origin code.
* @return string
*/
public function getLabel(string $origin): string
{
switch ($origin) {
case 'product_views_catalog_category_view_count':
return __('Category');
case 'product_views_catalogsearch_result_index_count':
return __('Search');
case 'product_views_catalog_product_view_count':
return __('Recommender');
case 'product_views_catalogsearch_autocomplete_click_count':
return __('Autocomplete');
default:
return __('Other');
}
}

/**
* {@inheritdoc}
* @SuppressWarnings(PHPMD.ElseExpression)
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
*/
protected function processResponse(\Smile\ElasticsuiteCore\Search\Adapter\Elasticsuite\Response\QueryResponse $response)
{
Expand All @@ -62,6 +85,22 @@ protected function processResponse(\Smile\ElasticsuiteCore\Search\Adapter\Elasti
} elseif (in_array($value->getValue(), ['product_views', 'category_views', 'add_to_cart', 'sales'])) {
$key = sprintf("%s_count", $value->getValue());
$data[$key] = (int) $value->getMetrics()['count'];
if ($value->getAggregations()->getBucket('origin')->getValues()) {
$originDetails = '';
$rawData = [];
foreach ($value->getAggregations()->getBucket('origin')->getValues() ?? [] as $originData) {
$key = sprintf("%s_%s_count", $value->getValue(), $originData->getValue());
$data[$key] = (int) $originData->getMetrics()['count'];
$label = $this->getLabel($key);
if (!array_key_exists($label, $rawData)) {
$rawData[$label] = $data[$key];
}
}
foreach ($rawData as $label => $count) {
$originDetails .= "• {$label}: {$count}\n";
}
$data[$value->getValue() . '_origin_details'] = $originDetails;
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,10 @@ public function getAggregation()
'name' => 'search_terms',
'metrics' => $this->getMetrics(),
'pipelines' => $this->getPipelines(),
'childBuckets' => [$this->getFilteredResultCountMetric()],
'childBuckets' => [
$this->getFilteredResultCountMetric(),
$this->getPageTypeIdentifierBucket(),
],
'sortOrder' => ['unique_sessions' => 'desc'],
'size' => $this->helper->getMaxSearchTerms(),
];
Expand Down Expand Up @@ -153,6 +156,36 @@ protected function getFilteredResultCountMetric()
);
}

/**
* Return aggregation providing the page type identifier.
*
* @return BucketInterface
*/
protected function getPageTypeIdentifierBucket()
{
return $this->aggregationFactory->create(
BucketInterface::TYPE_TERM,
[
'name' => 'page_type_identifier',
'field' => 'page.type.identifier',
'metrics' => [
$this->metricFactory->create(
[
'name' => 'unique_sessions',
'field' => 'session.uid',
'type' => MetricInterface::TYPE_CARDINALITY,
]
),
],
'include' => [
'catalogsearch_result_index',
'catalogsearch_autocomplete',
'catalogsearch_autocomplete_click',
],
]
);
}

/**
* Return "only first page" query.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,21 @@
*/
namespace Smile\ElasticsuiteAnalytics\Model\Search\Usage\Terms;

use Magento\Framework\Api\Search\AggregationValueInterface;
use Magento\Framework\Api\Search\BucketInterface;
use Magento\Framework\View\Element\Block\ArgumentInterface;
use Magento\Search\Model\SearchEngine;
use Smile\ElasticsuiteAnalytics\Model\AbstractReport;
use Smile\ElasticsuiteAnalytics\Model\Report\SearchRequestBuilder;
use Smile\ElasticsuiteCore\Search\Adapter\Elasticsuite\Response\QueryResponse;

/**
* Search terms Report
*
* @category Smile
* @package Smile\ElasticsuiteAnalytics
*/
class Report extends AbstractReport implements \Magento\Framework\View\Element\Block\ArgumentInterface
class Report extends AbstractReport implements ArgumentInterface
{
/**
* @var array
Expand All @@ -32,12 +37,12 @@ class Report extends AbstractReport implements \Magento\Framework\View\Element\B
/**
* Constructor.
*
* @param \Magento\Search\Model\SearchEngine $searchEngine Search engine.
* @param SearchRequestBuilder $searchRequestBuilder Search request builder.
* @param array $postProcessors Response post processors.
* @param SearchEngine $searchEngine Search engine.
* @param SearchRequestBuilder $searchRequestBuilder Search request builder.
* @param array $postProcessors Response post processors.
*/
public function __construct(
\Magento\Search\Model\SearchEngine $searchEngine,
SearchEngine $searchEngine,
SearchRequestBuilder $searchRequestBuilder,
array $postProcessors = []
) {
Expand All @@ -49,7 +54,7 @@ public function __construct(
* {@inheritdoc}
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
*/
protected function processResponse(\Smile\ElasticsuiteCore\Search\Adapter\Elasticsuite\Response\QueryResponse $response)
protected function processResponse(QueryResponse $response)
{
$data = [];

Expand All @@ -73,6 +78,13 @@ protected function processResponse(\Smile\ElasticsuiteCore\Search\Adapter\Elasti
}
$data[$searchTerm]['result_count'] = round((float) $resultCountMetrics ?: 0);
}
if ($value->getAggregations()->getBucket('page_type_identifier')) {
$this->processAutocompleteData(
$value->getAggregations()->getBucket('page_type_identifier'),
$searchTerm,
$data
);
}
}
}

Expand All @@ -83,14 +95,38 @@ protected function processResponse(\Smile\ElasticsuiteCore\Search\Adapter\Elasti
return $data;
}

/**
* Process autocomplete data from page type aggregation.
*
* @param BucketInterface $pageTypeIdAgg Page type aggregation bucket.
* @param string $searchTerm Search term.
* @param array $data Aggregated data.
* @return void
*/
private function processAutocompleteData(BucketInterface $pageTypeIdAgg, string $searchTerm, array &$data): void
{
$sessionsByPageType = [];
foreach ($pageTypeIdAgg->getValues() as $pageTypeIdVal) {
$sessionsByPageType[$pageTypeIdVal->getValue()] = $pageTypeIdVal->getMetrics()['unique_sessions'];
}

$typedWithClick = $sessionsByPageType['catalogsearch_autocomplete_click'] ?? 0;
$typedAndPressEnter = $sessionsByPageType['catalogsearch_result_index'] ?? 0;
$typedWithNoClick = $data[$searchTerm]['sessions'] - $typedWithClick - $typedAndPressEnter;

$data[$searchTerm]['sessions_without_click'] = $typedWithNoClick;
$data[$searchTerm]['sessions_with_click'] = $typedWithClick;
$data[$searchTerm]['sessions_with_submit'] = $typedAndPressEnter;
}

/**
* Return the bucket values from the main aggregation
*
* @param \Smile\ElasticsuiteCore\Search\Adapter\Elasticsuite\Response\QueryResponse $response ES Query response.
* @param QueryResponse $response ES Query response.
*
* @return \Magento\Framework\Api\Search\AggregationValueInterface[]
* @return AggregationValueInterface[]
*/
private function getValues(\Smile\ElasticsuiteCore\Search\Adapter\Elasticsuite\Response\QueryResponse $response)
private function getValues(QueryResponse $response)
{
$bucket = $response->getAggregations()->getBucket('search_terms');

Expand Down
3 changes: 3 additions & 0 deletions src/module-elasticsuite-analytics/i18n/de_DE.csv
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,10 @@
"Exact searches","Exakte Suche"
"Conversion rate","Konversionsrate"
"All sessions","Alle Sitzungen"
"with clicks","Mit Klick"
"With search","Mit Suche"
"with submit","Mit Bestätigung"
"without clicks","Ohne Klick"
"Without search","Ohne Suche"
"What is this ?","Was ist das?"
"The terms listed below are the most popular search terms, whether they lead to exact or close matches.<br />The link on a term leads to its edit screen where you can either <a href=""https://github.com/Smile-SA/elasticsuite/wiki/ProductSorting#using-the-merchandiser"" target=""_blank"">merchandise</a> the search results page or configure a redirection - for instance to redirect the user to a dedicated category.<br />The ""conversion rate"" column value is computed as the ratio of the number of sessions where an order was placed and the term(s) searched for on the total number of sessions where the term(s) were searched for.","Die unten aufgeführten Begriffe sind die beliebtesten Suchbegriffe, unabhängig davon, ob sie zu exakten oder geschlossenen Übereinstimmungen führen.<br />Der Link auf einem Begriff führt zu seinem Bearbeiten-Bildschirm, auf dem Sie entweder <a href=""https://github.com/Smile-SA/elasticsuite/wiki/ProductSorting#using-the-merchandiser"" target=""_blank"">Merchandise</a> der Suchergebnisseite vermarkten oder eine Umleitung konfigurieren können - zum Beispiel um den Benutzer in eine eigene Kategorie umzuleiten.<br />Der Spaltenwert der Spalte ""Konversionsrate"" wird als Verhältnis der Anzahl der Sitzungen berechnet, in denen eine Bestellung aufgegeben wurde, und der Suchtermin nach der Gesamtzahl der Sitzungen, nach denen die Begriffe gesucht wurden."
Expand Down
3 changes: 3 additions & 0 deletions src/module-elasticsuite-analytics/i18n/en_US.csv
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,10 @@
"Exact searches","Exact searches"
"Conversion rate","Conversion rate"
"All sessions","All sessions"
"with clicks","with clicks"
"With search","With search"
"with submit","with submit"
"without clicks","without clicks"
"Without search","Without search"
"What is this ?","What is this ?"
"The terms listed below are the most popular search terms, whether they lead to exact or close matches.<br />The link on a term leads to its edit screen where you can either <a href=""https://github.com/Smile-SA/elasticsuite/wiki/ProductSorting#using-the-merchandiser"" target=""_blank"">merchandise</a> the search results page or configure a redirection - for instance to redirect the user to a dedicated category.<br />The ""conversion rate"" column value is computed as the ratio of the number of sessions where an order was placed and the term(s) searched for on the total number of sessions where the term(s) were searched for.","The terms listed below are the most popular search terms, whether they lead to exact or close matches.<br />The link on a term leads to its edit screen where you can either <a href=""https://github.com/Smile-SA/elasticsuite/wiki/ProductSorting#using-the-merchandiser"" target=""_blank"">merchandise</a> the search results page or configure a redirection - for instance to redirect the user to a dedicated category.<br />The ""conversion rate"" column value is computed as the ratio of the number of sessions where an order was placed and the term(s) searched for on the total number of sessions where the term(s) were searched for."
Expand Down
Loading