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,6 +41,26 @@ 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');
default:
return __('Other');
}
}

/**
* {@inheritdoc}
* @SuppressWarnings(PHPMD.ElseExpression)
Expand All @@ -62,6 +82,15 @@ 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 = '';
foreach ($value->getAggregations()->getBucket('origin')->getValues() ?? [] as $originData) {
$key = sprintf("%s_%s_count", $value->getValue(), $originData->getValue());
$data[$key] = (int) $originData->getMetrics()['count'];
$originDetails .= "• {$this->getLabel($key)}: {$originData->getMetrics()['count']}\n";
}
$data[$value->getValue() . '_origin_details'] = $originDetails;
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,12 @@
<argument name="chart_type" xsi:type="string">BarChart</argument>
</arguments>
</block>
<block name="elasticsuite.analytics.view.origin" class="Smile\ElasticsuiteAnalytics\Block\Adminhtml\Search\Usage\Chart\ViewOrigins" template="Smile_ElasticsuiteAnalytics::search/usage/chart.phtml">
<arguments>
<argument name="title" xsi:type="string" translate="true">Views origins</argument>
<argument name="chart_type" xsi:type="string">PieChart</argument>
</arguments>
</block>
</container>
</container>
</referenceContainer>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,12 @@ $data = $block->getKpi();
</li>
<li class="dashboard-totals-item">
<span class="dashboard-totals-label"><?= __('Product views') ?></span>
<strong class="dashboard-totals-value">
<span class="value"><?= $data['product_views_count']; ?></span>
<?php if (!empty($data['product_views_origin_details'])) :?>
<?php endif;?>
<strong class="dashboard-totals-value <?= !empty($data['product_views_origin_details']) ? 'has-details' : '' ?>">
<span class="value" title="<?= $data['product_views_origin_details'] ?? '' ?>">
<?= $data['product_views_count']; ?>
</span>
<span class="dashboard-totals-decimals"></span>
</strong>
</li>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,13 @@
.dashboard-totals-list {
.dashboard-totals-item {
width: 10%;
text-align: center
text-align: center;

.has-details {
cursor: pointer;
text-decoration: underline dotted @color-green-apple;
font-style: oblique;
}
}
}

Expand Down
5 changes: 5 additions & 0 deletions src/module-elasticsuite-tracker/etc/elasticsuite_indices.xml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@
<field name="page.title" type="keyword" />
<field name="page.url" type="keyword" />

<!-- Previous page metadata -->
<field name="previousPage.url" type="keyword" />
<field name="previousPage.type.identifier" type="keyword" />
<field name="previousPage.type.label" type="keyword" />

<!-- Page data (type) -->
<field name="page.type.identifier" type="keyword" />
<field name="page.type.label" type="keyword" />
Expand Down
95 changes: 91 additions & 4 deletions src/module-elasticsuite-tracker/view/frontend/web/js/tracking.js
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ const smileTracker = (function () {
addCampaignVars.bind(this)();
addMetaPageVars.bind(this)();
addResolutionVars.bind(this)();
handlePageHistory.bind(this)();
this.trackerVarsAdded = true;
}

Expand Down Expand Up @@ -275,6 +276,10 @@ const smileTracker = (function () {
addVariable.bind(this)(transformVarName.bind(this)(varName , 'page'), value);
}

function addPreviousPageVar(varName, value) {
addVariable.bind(this)(transformVarName.bind(this)(varName , 'previous_page'), value);
}

function addCustomerVar(varName, value) {
addVariable.bind(this)(transformVarName.bind(this)(varName , 'customer'), value);
}
Expand Down Expand Up @@ -324,6 +329,88 @@ const smileTracker = (function () {
}
}

function handlePageHistory() {
const currentPageData = {
url: this.vars['page[url]'],
type: {
identifier: this.vars['page[type][identifier]'],
label: this.vars['page[type][label]']
}
};

addPageDataToHistory.bind(this)(currentPageData);

const previousPage = getPreviousPageDataFromHistory.bind(this)();
if (previousPage) {
addPreviousPageVar.bind(this)('url', previousPage.url);
addPreviousPageVar.bind(this)('type.identifier', previousPage.type.identifier);
addPreviousPageVar.bind(this)('type.label', previousPage.type.label);
}
}

function fetchPageHistory() {
// Get existing history
let pageHistory = [];
try {
const historyData = localStorage.getItem(this.historyStorageKey);
pageHistory = historyData ? JSON.parse(historyData) : [];
} catch (e) {
console.warn('Elasticsuite tracker: Error retrieving page history:', e);
}

return pageHistory;
}

function persistPageHistory(pageHistory) {
// Limit history size
if (pageHistory.length > this.historyMaxLength) {
pageHistory = pageHistory.slice(0, this.historyMaxLength);
}

// Save updated history
try {
localStorage.setItem(this.historyStorageKey, JSON.stringify(pageHistory));
} catch (e) {
console.warn('Error saving page history:', e);
}
}

function getPreviousPageDataFromHistory() {
const comeFromExternalPage = !document.referrer
|| (document.referrer && !document.referrer.includes(window.location.hostname));

if (comeFromExternalPage) {
return {
url: document.referrer,
type: {
identifier: 'external',
label: 'external'
}
};
}

let pageHistory = fetchPageHistory.bind(this)();
if (pageHistory.length > 1) {
return pageHistory[1]; // Current page is at index 0, previous page at index 1
}

return null;
}

function addPageDataToHistory(pageData) {
let pageHistory = fetchPageHistory.bind(this)();

// Check if user navigated back to a previous page
const pageIndex = pageHistory.findIndex(page => page.url === pageData.url);

// If the page is the same as the last one, do nothing
// If not, we add it
if (pageIndex !== 0) {
pageHistory.unshift(pageData);
persistPageHistory.bind(this)(pageHistory);
}
}

// Implementation of the tracker
const SmileTrackerImpl = function() {
this.vars = {};
Expand Down Expand Up @@ -353,10 +440,10 @@ const smileTracker = (function () {
if (config.hasOwnProperty('endpointUrl') && (config.endpointUrl.length !== 0)) {
this.endpointUrl = config.endpointUrl;
}
this.telemetryEnabled = config.telemetryEnabled;
this.telemetryUrl = config.telemetryUrl;


this.telemetryEnabled = config.telemetryEnabled;
this.telemetryUrl = config.telemetryUrl;
this.historyStorageKey = 'smile_tracker_page_history';
this.historyMaxLength = 5;
};

SmileTrackerImpl.prototype.addPageVar = function (varName, value) {
Expand Down