Skip to content

Commit 0bad824

Browse files
[Analytics] Track Autocomplete Events
1 parent 6ac6559 commit 0bad824

File tree

11 files changed

+193
-17
lines changed

11 files changed

+193
-17
lines changed

src/module-elasticsuite-analytics/Model/Search/Usage/Kpi/Report.php

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ public function getLabel(string $origin): string
5656
return __('Search');
5757
case 'product_views_catalog_product_view_count':
5858
return __('Recommender');
59+
case 'product_views_catalogsearch_autocomplete_click_count':
60+
return __('Autocomplete');
5961
default:
6062
return __('Other');
6163
}
@@ -64,6 +66,7 @@ public function getLabel(string $origin): string
6466
/**
6567
* {@inheritdoc}
6668
* @SuppressWarnings(PHPMD.ElseExpression)
69+
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
6770
*/
6871
protected function processResponse(\Smile\ElasticsuiteCore\Search\Adapter\Elasticsuite\Response\QueryResponse $response)
6972
{
@@ -84,10 +87,17 @@ protected function processResponse(\Smile\ElasticsuiteCore\Search\Adapter\Elasti
8487
$data[$key] = (int) $value->getMetrics()['count'];
8588
if ($value->getAggregations()->getBucket('origin')->getValues()) {
8689
$originDetails = '';
90+
$rawData = [];
8791
foreach ($value->getAggregations()->getBucket('origin')->getValues() ?? [] as $originData) {
8892
$key = sprintf("%s_%s_count", $value->getValue(), $originData->getValue());
8993
$data[$key] = (int) $originData->getMetrics()['count'];
90-
$originDetails .= "{$this->getLabel($key)}: {$originData->getMetrics()['count']}\n";
94+
$label = $this->getLabel($key);
95+
if (!array_key_exists($label, $rawData)) {
96+
$rawData[$label] = $data[$key];
97+
}
98+
}
99+
foreach ($rawData as $label => $count) {
100+
$originDetails .= "{$label}: {$count}\n";
91101
}
92102
$data[$value->getValue() . '_origin_details'] = $originDetails;
93103
}

src/module-elasticsuite-analytics/Model/Search/Usage/Terms/AggregationProvider.php

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,10 @@ public function getAggregation()
8585
'name' => 'search_terms',
8686
'metrics' => $this->getMetrics(),
8787
'pipelines' => $this->getPipelines(),
88-
'childBuckets' => [$this->getFilteredResultCountMetric()],
88+
'childBuckets' => [
89+
$this->getFilteredResultCountMetric(),
90+
$this->getPageTypeIdentifierBucket(),
91+
],
8992
'sortOrder' => ['unique_sessions' => 'desc'],
9093
'size' => $this->helper->getMaxSearchTerms(),
9194
];
@@ -153,6 +156,36 @@ protected function getFilteredResultCountMetric()
153156
);
154157
}
155158

159+
/**
160+
* Return aggregation providing the page type identifier.
161+
*
162+
* @return BucketInterface
163+
*/
164+
protected function getPageTypeIdentifierBucket()
165+
{
166+
return $this->aggregationFactory->create(
167+
BucketInterface::TYPE_TERM,
168+
[
169+
'name' => 'page_type_identifier',
170+
'field' => 'page.type.identifier',
171+
'metrics' => [
172+
$this->metricFactory->create(
173+
[
174+
'name' => 'unique_sessions',
175+
'field' => 'session.uid',
176+
'type' => MetricInterface::TYPE_CARDINALITY,
177+
]
178+
),
179+
],
180+
'include' => [
181+
'catalogsearch_result_index',
182+
'catalogsearch_autocomplete',
183+
'catalogsearch_autocomplete_click',
184+
],
185+
]
186+
);
187+
}
188+
156189
/**
157190
* Return "only first page" query.
158191
*

src/module-elasticsuite-analytics/Model/Search/Usage/Terms/Report.php

Lines changed: 45 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,21 @@
1313
*/
1414
namespace Smile\ElasticsuiteAnalytics\Model\Search\Usage\Terms;
1515

16+
use Magento\Framework\Api\Search\AggregationValueInterface;
17+
use Magento\Framework\Api\Search\BucketInterface;
18+
use Magento\Framework\View\Element\Block\ArgumentInterface;
19+
use Magento\Search\Model\SearchEngine;
1620
use Smile\ElasticsuiteAnalytics\Model\AbstractReport;
1721
use Smile\ElasticsuiteAnalytics\Model\Report\SearchRequestBuilder;
22+
use Smile\ElasticsuiteCore\Search\Adapter\Elasticsuite\Response\QueryResponse;
1823

1924
/**
2025
* Search terms Report
2126
*
2227
* @category Smile
2328
* @package Smile\ElasticsuiteAnalytics
2429
*/
25-
class Report extends AbstractReport implements \Magento\Framework\View\Element\Block\ArgumentInterface
30+
class Report extends AbstractReport implements ArgumentInterface
2631
{
2732
/**
2833
* @var array
@@ -32,12 +37,12 @@ class Report extends AbstractReport implements \Magento\Framework\View\Element\B
3237
/**
3338
* Constructor.
3439
*
35-
* @param \Magento\Search\Model\SearchEngine $searchEngine Search engine.
36-
* @param SearchRequestBuilder $searchRequestBuilder Search request builder.
37-
* @param array $postProcessors Response post processors.
40+
* @param SearchEngine $searchEngine Search engine.
41+
* @param SearchRequestBuilder $searchRequestBuilder Search request builder.
42+
* @param array $postProcessors Response post processors.
3843
*/
3944
public function __construct(
40-
\Magento\Search\Model\SearchEngine $searchEngine,
45+
SearchEngine $searchEngine,
4146
SearchRequestBuilder $searchRequestBuilder,
4247
array $postProcessors = []
4348
) {
@@ -49,7 +54,7 @@ public function __construct(
4954
* {@inheritdoc}
5055
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
5156
*/
52-
protected function processResponse(\Smile\ElasticsuiteCore\Search\Adapter\Elasticsuite\Response\QueryResponse $response)
57+
protected function processResponse(QueryResponse $response)
5358
{
5459
$data = [];
5560

@@ -73,6 +78,13 @@ protected function processResponse(\Smile\ElasticsuiteCore\Search\Adapter\Elasti
7378
}
7479
$data[$searchTerm]['result_count'] = round((float) $resultCountMetrics ?: 0);
7580
}
81+
if ($value->getAggregations()->getBucket('page_type_identifier')) {
82+
$this->processAutocompleteData(
83+
$value->getAggregations()->getBucket('page_type_identifier'),
84+
$searchTerm,
85+
$data
86+
);
87+
}
7688
}
7789
}
7890

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

98+
/**
99+
* Process autocomplete data from page type aggregation.
100+
*
101+
* @param BucketInterface $pageTypeIdAgg Page type aggregation bucket.
102+
* @param string $searchTerm Search term.
103+
* @param array $data Aggregated data.
104+
* @return void
105+
*/
106+
private function processAutocompleteData(BucketInterface $pageTypeIdAgg, string $searchTerm, array &$data): void
107+
{
108+
$sessionsByPageType = [];
109+
foreach ($pageTypeIdAgg->getValues() as $pageTypeIdVal) {
110+
$sessionsByPageType[$pageTypeIdVal->getValue()] = $pageTypeIdVal->getMetrics()['unique_sessions'];
111+
}
112+
113+
$typedWithClick = $sessionsByPageType['catalogsearch_autocomplete_click'] ?? 0;
114+
$typedAndPressEnter = $sessionsByPageType['catalogsearch_result_index'] ?? 0;
115+
$typedWithNoClick = $data[$searchTerm]['sessions'] - $typedWithClick - $typedAndPressEnter;
116+
117+
$data[$searchTerm]['sessions_without_click'] = $typedWithNoClick;
118+
$data[$searchTerm]['sessions_with_click'] = $typedWithClick;
119+
$data[$searchTerm]['sessions_with_submit'] = $typedAndPressEnter;
120+
}
121+
86122
/**
87123
* Return the bucket values from the main aggregation
88124
*
89-
* @param \Smile\ElasticsuiteCore\Search\Adapter\Elasticsuite\Response\QueryResponse $response ES Query response.
125+
* @param QueryResponse $response ES Query response.
90126
*
91-
* @return \Magento\Framework\Api\Search\AggregationValueInterface[]
127+
* @return AggregationValueInterface[]
92128
*/
93-
private function getValues(\Smile\ElasticsuiteCore\Search\Adapter\Elasticsuite\Response\QueryResponse $response)
129+
private function getValues(QueryResponse $response)
94130
{
95131
$bucket = $response->getAggregations()->getBucket('search_terms');
96132

src/module-elasticsuite-analytics/i18n/de_DE.csv

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,10 @@
2828
"Exact searches","Exakte Suche"
2929
"Conversion rate","Konversionsrate"
3030
"All sessions","Alle Sitzungen"
31+
"with clicks","Mit Klick"
3132
"With search","Mit Suche"
33+
"with submit","Mit Bestätigung"
34+
"without clicks","Ohne Klick"
3235
"Without search","Ohne Suche"
3336
"What is this ?","Was ist das?"
3437
"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."

src/module-elasticsuite-analytics/i18n/en_US.csv

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,10 @@
2828
"Exact searches","Exact searches"
2929
"Conversion rate","Conversion rate"
3030
"All sessions","All sessions"
31+
"with clicks","with clicks"
3132
"With search","With search"
33+
"with submit","with submit"
34+
"without clicks","without clicks"
3235
"Without search","Without search"
3336
"What is this ?","What is this ?"
3437
"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."

src/module-elasticsuite-analytics/i18n/fr_FR.csv

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,10 @@
2828
"Exact searches","Recherches exactes"
2929
"Conversion rate","Taux de conversion"
3030
"All sessions","Toute session"
31+
"with clicks","avec clic"
3132
"With search","Avec recherche"
33+
"with submit","avec validation"
34+
"without clicks","sans clic"
3235
"Without search","Sans recherche"
3336
"What is this ?","Qu'est-ce que c'est ?"
3437
"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.","Les termes listés ci-dessous sont les termes les plus populaires, qu'ils amènent à des résultats exacts ou approchants.<br />Le lien sous un terme permet d'atteindre son écran d'édition où vous pouvez soit <a href=""https://github.com/Smile-SA/elasticsuite/wiki/ProductSorting#using-the-merchandiser"" target=""_blank"">merchandiser</a> la page de résultats soit bien configurer une redirection - par exemple en redirigeant l'utilisateur vers une catégorie dédiée.<br />La valeur de la colonne ""taux de conversion"" est calculée comme le rapport du nombre de sessions avec un passage de commande et la recherche du/de ce(s) terme(s) sur le nombre total de sessions avec ce(s) terme(s) de recherche."

src/module-elasticsuite-analytics/i18n/nl_NL.csv

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,10 @@
2828
"Exact searches","Exacte zoekopdrachten"
2929
"Conversion rate","Conversion Rate"
3030
"All sessions","Alle sessies"
31+
"with clicks","Met klik"
3132
"With search","Met zoekopdracht"
33+
"with submit","Met bevestiging"
34+
"without clicks","Zonder klik"
3235
"Without search","Zonder zoekopdracht"
3336
"What is this ?","Wat is dit?"
3437
"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.","De onderstaande termen zijn de populairste zoektermen, ongeacht of ze leiden tot exacte of gesloten matches.<br />De link op een term leidt naar het bewerkingsscherm waar je ofwel <a href=""https://github.com/Smile-SA/elasticsuite/wiki/ProductSorting#using-the-merchandiser"" target=""_blank"">merchandise</a> de zoekresultaten pagina kunt weergeven of een omleiding kunt configureren - bijvoorbeeld om de gebruiker door te verwijzen naar een speciale categorie.<br />De kolom ""conversierative"" wordt berekend als de verhouding van het aantal sessies waar een bestelling is geplaatst en de termen waarnaar is gezocht op het totaal aantal sessies waarnaar de termen(s) werden gezocht."

src/module-elasticsuite-analytics/view/adminhtml/templates/search/usage/terms.phtml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,9 @@ $hiddenTermsData = array_slice($termsData, $maxVisibleTerms);
5151
<tr>
5252
<th class="data-grid-th no-link col-search-query"><span><?= __('Term');?></span></th>
5353
<th class="data-grid-th no-link"><span><?= __('Sessions');?></span></th>
54+
<th class="data-grid-th no-link"><span><?= __('without clicks');?></span></th>
55+
<th class="data-grid-th no-link"><span><?= __('with clicks');?></span></th>
56+
<th class="data-grid-th no-link"><span><?= __('with submit');?></span></th>
5457
<th class="data-grid-th no-link"><span><?= __('Visitors');?></span></th>
5558
<th class="data-grid-th no-link <?php if (!$block->getShowConversionRate()) : ?>col-total<?php endif; ?>"><span><?= __('# Results (avg.)');?></span></th>
5659
<?php if ($block->getShowConversionRate()) : ?>
@@ -82,6 +85,9 @@ $hiddenTermsData = array_slice($termsData, $maxVisibleTerms);
8285
<?php endif; ?>
8386
</td>
8487
<td class="col-number"><?= $termData['sessions']; ?></td>
88+
<td class="col-number"><?= $termData['sessions_without_click'] ?? 0; ?></td>
89+
<td class="col-number"><?= $termData['sessions_with_click'] ?? 0; ?></td>
90+
<td class="col-number"><?= $termData['sessions_with_submit'] ?? 0; ?></td>
8591
<td class="col-number"><?= $termData['visitors']; ?></td>
8692
<td class="col-number"><?= $termData['result_count']; ?></td>
8793
<?php if ($block->getShowConversionRate()) : ?>

src/module-elasticsuite-core/view/frontend/web/js/form-mini.js

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -276,15 +276,55 @@ define([
276276

277277
if (this.responseList.indexList.length) {
278278
this._updateAriaHasPopup(true);
279+
const productCount = data.filter(item => item.type === 'product').length;
280+
const urlObject = new URL(this.options.url);
281+
const trackingEvent = new CustomEvent(
282+
'elasticsuite:autocomplete',
283+
{
284+
detail: {
285+
path: urlObject.pathname,
286+
queryString: value,
287+
productCount: productCount
288+
}
289+
}
290+
);
291+
document.dispatchEvent(trackingEvent);
279292
} else {
280293
this._updateAriaHasPopup(false);
281294
}
282295

283296
this.responseList.indexList
284297
.on('click vclick', function (e) {
285298
self.responseList.selected = $(this);
299+
286300
if (self.responseList.selected.attr("href")) {
287-
window.location.href = self.responseList.selected.attr("href");
301+
// Find the section header (dt) by going up to the dl parent and finding its dt
302+
const sectionHeader = self.responseList.selected.closest('dl').find('dt');
303+
const isProduct = sectionHeader.hasClass('title-product');
304+
305+
// Only dispatch the custom event for products
306+
if (isProduct) {
307+
const trackingEvent = new CustomEvent(
308+
'elasticsuite:autocomplete:product_click',
309+
{
310+
detail: {
311+
href: self.responseList.selected.attr("href"),
312+
text: self.responseList.selected.find('.product-name').text(),
313+
queryString: self.element.val()
314+
},
315+
bubbles: true,
316+
cancelable: true
317+
}
318+
);
319+
320+
document.dispatchEvent(trackingEvent);
321+
}
322+
323+
const href = self.responseList.selected.attr("href");
324+
setTimeout(function() {
325+
window.location.href = href;
326+
}, 100);
327+
288328
e.stopPropagation();
289329
return false;
290330
}

0 commit comments

Comments
 (0)